MFASweep: How Multi-Factor Authentication Fails Across Microsoft's Service Archipelago
Hook
Even with MFA enabled, your Microsoft 365 accounts might still be vulnerable through 11 different service endpoints—and a Nintendo Switch user-agent string could be the key to bypassing your conditional access policies.
Context
Microsoft's cloud ecosystem is not a monolithic fortress but an archipelago of services—Graph API, Exchange Web Services, Azure Resource Manager, ActiveSync, ADFS—each with its own authentication endpoint and enforcement mechanisms. When organizations enable multi-factor authentication, they often assume it's enforced uniformly across all these surfaces. The reality is far messier.
Conditional Access policies in Azure AD are powerful but complex, requiring administrators to explicitly configure device platforms, client applications, and authentication flows. A policy that blocks legacy authentication for Outlook might not apply to PowerShell accessing Graph API. An MFA requirement triggered by iOS devices might not fire when the authentication comes from an unrecognized platform. These gaps create exploitable windows where attackers with valid credentials can bypass MFA entirely by simply choosing the right service endpoint or spoofing the right user-agent. MFASweep emerged from the offensive security community to systematically probe these inconsistencies, turning what should be a comprehensive security control into a game of whack-a-mole.
Technical Insight
At its core, MFASweep exploits the Resource Owner Password Credentials (ROPC) flow, a legacy OAuth 2.0 authentication pattern where applications can directly exchange username and password for access tokens. While Microsoft has been trying to deprecate ROPC for years, it remains enabled in many tenants for backward compatibility with older applications that can't support modern interactive authentication flows.
The tool's architecture is deceptively simple: it takes credentials and systematically attempts authentication against a matrix of service endpoints, each identified by a unique resource URL and client ID combination. Here's how it tests the Graph API endpoint:
$body = @{
resource = "https://graph.microsoft.com"
client_id = "1b730954-1685-4b74-9bfd-dac224a7b894"
grant_type = "password"
username = $Username
password = $Password
scope = "openid"
}
$response = Invoke-RestMethod -Uri "https://login.microsoft.com/common/oauth2/token" `
-Method POST -Body $body -ContentType "application/x-www-form-urlencoded"
if ($response.access_token) {
Write-Host "[SUCCESS] Graph API - MFA not required" -ForegroundColor Red
$response | Add-Member -NotePropertyName "Service" -NotePropertyValue "Graph"
$tokens += $response
}
What makes this particularly effective is the client ID manipulation. Each Microsoft application—the Azure CLI, PowerShell modules, mobile apps, web portals—has its own client ID. Conditional Access policies can target specific client applications, so a policy blocking legacy auth for the Outlook client (client ID d3590ed6-52b3-4102-aeff-aad2292ab01c) won't necessarily block the same authentication flow using the Azure PowerShell client ID (1950a258-227b-4e31-a9cf-717495945fc2). MFASweep ships with lists of 514 known client IDs and systematically tries different combinations.
The user-agent spoofing is where things get creative. Conditional Access policies often enforce MFA based on device platform—requiring it for Windows and macOS but perhaps being more lenient with mobile devices. MFASweep includes a test using a Nintendo Switch user-agent:
$headers = @{
"User-Agent" = "Mozilla/5.0 (Nintendo Switch; WifiWebAuthApplet) AppleWebKit/609.4 (KHTML, like Gecko) NF/6.0.1.15.4 NintendoBrowser/5.1.0.20393"
}
$body = @{
resource = "https://management.core.windows.net/"
client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
grant_type = "password"
username = $Username
password = $Password
}
$response = Invoke-RestMethod -Uri "https://login.microsoft.com/common/oauth2/token" `
-Method POST -Body $body -Headers $headers -ContentType "application/x-www-form-urlencoded"
This registers as an "Unknown Platform" in Azure AD's conditional access engine. If an administrator has only configured MFA policies for known platforms (Windows, iOS, Android, macOS), this unknown platform slips through. It's the authentication equivalent of walking into a building through a door nobody thought to put a lock on.
The tool also includes specific error handling to distinguish between authentication failures and Conditional Access blocks:
if ($_.Exception.Response.StatusCode -eq 400) {
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$responseBody = $reader.ReadToEnd() | ConvertFrom-Json
if ($responseBody.error_description -match "AADSTS53003") {
Write-Host "[BLOCKED] Conditional Access policy blocked this attempt" -ForegroundColor Yellow
} elseif ($responseBody.error_description -match "AADSTS50076") {
Write-Host "[MFA] MFA required - authentication blocked" -ForegroundColor Green
}
}
Error code AADSTS50076 means MFA is required and working as intended. Error code AADSTS53003 means a Conditional Access policy explicitly blocked the attempt. No error and a successful token response means MFA was bypassed entirely. This granular feedback is critical for understanding not just whether authentication succeeded, but why it succeeded or failed.
The tool dumps successful access tokens to AccessTokens.json, which can then be used with other tools like the Microsoft Graph PowerShell SDK or Azure CLI to perform authenticated actions without ever triggering an MFA challenge. For penetration testers and red teams, this transforms a credential compromise into persistent, MFA-free access to the target environment.
Gotcha
The most dangerous aspect of MFASweep is the volume of authentication attempts it generates. Each execution performs 11-12 separate login attempts against different endpoints. If you're using incorrect credentials or the account has an aggressive lockout policy (say, 3 failed attempts), you'll lock the account before the tool completes its sweep. This isn't a subtle reconnaissance tool—it's loud, generates authentication logs across multiple services, and will trigger alerts in any properly configured SIEM. For authorized penetration tests, this is acceptable risk. For anything else, it's a detection timebomb.
The reliance on ROPC flow is increasingly problematic. Microsoft has been deprecating this authentication method for years, and modern Azure AD tenants—especially those with security defaults enabled—often have ROPC completely disabled. When this happens, MFASweep will fail across all endpoints regardless of MFA configuration. The tool also doesn't capture tokens for Exchange Web Services, ActiveSync, and ADFS connections, only providing success/failure indicators for those services. If you need to actually use those authentication vectors post-exploitation, you'll need different tooling. Finally, the effectiveness of the platform spoofing techniques depends entirely on how the target organization has configured their Conditional Access policies—well-designed policies that default-deny unknown platforms will block these attempts entirely.
Verdict
Use MFASweep if: you're conducting authorized security assessments or red team engagements against Microsoft 365 environments and need to systematically identify MFA enforcement gaps across service endpoints. It's particularly valuable when you have valid credentials but no MFA token, and you need to discover which services might grant access anyway. The tool provides quick, actionable intelligence about conditional access misconfigurations that can be exploited or, for blue teamers, remediated. Skip if: you're working without proper authorization, testing accounts with unknown lockout policies, or operating in modern tenants with security defaults enabled (where ROPC is likely disabled). Also skip if you need stealthy reconnaissance—this tool generates significant authentication noise. For those scenarios, consider token theft and refresh token abuse with tools like TokenTactics, or comprehensive Azure AD reconnaissance with AADInternals that doesn't require repeated authentication attempts.