Skip to content

Password Spraying & Brute-Force Telemetry Analysis

Despite the widespread promotion of passwordless authentication, passwords remain the primary authentication factor for the vast majority of Microsoft 365 enterprise tenants. While traditional brute-force attacks (rapidly testing thousands of passwords against a single target account) are rendered obsolete by Microsoft Entra ID’s Smart Lockout mechanisms, Password Spraying remains an extraordinarily effective initial access vector.

In a password spray attack, the threat actor reverses the brute-force paradigm: rather than trying many passwords against one user, they test a single common password (e.g., Autumn2026!, Company123#) across thousands of distinct tenant identities over an extended period. By distributing requests across rotating residential proxy networks and targeting legacy authentication protocols, adversaries stay beneath rate-limiting thresholds and evade automated perimeter blocks.

This guide provides an exhaustive architectural and forensic dissection of password spraying in Entra ID, analyzes pre-attack user enumeration techniques, details critical sign-in error codes, and delivers production-grade KQL detection queries.


1. Attack Mechanics: Brute Force vs Distributed Password Spraying

Section titled “1. Attack Mechanics: Brute Force vs Distributed Password Spraying”
graph TD
subgraph "Vertical Brute Force (Defeated by Smart Lockout)"
ATT1[Attacker] -->|1,000 Passwords / 1 User| USER_A[alice@target.com]
USER_A --> LOCKOUT[Smart Lockout Triggered<br/>ResultType: 50053<br/>IP Banned / Account Frozen]
end
subgraph "Horizontal Password Spray (Stealthy)"
ATT2[Attacker Botnet / Residential Proxies] -->|Single Password: Spring2026!| POOL{User Pool}
POOL -->|Attempt 1 / IP 1| U1[user1@target.com]
POOL -->|Attempt 1 / IP 2| U2[user2@target.com]
POOL -->|Attempt 1 / IP 3| U3[user3@target.com]
POOL -->|Attempt 1 / IP N| UN[userN@target.com]
U1 & U2 & U3 & UN --> IDP[Entra ID Security Token Service]
IDP -->|Thresholds Not Exceeded| STEALTH[Bypasses Account Lockout & Egress Blocks]
end

Why Password Spraying Evades Traditional Defenses:

Section titled “Why Password Spraying Evades Traditional Defenses:”
  1. Low Frequency per Identity: Testing one password every 2 to 4 hours per account avoids triggering Entra ID Smart Lockout (which typically locks accounts after 10 failed attempts within a rolling window).
  2. Residential IP Rotation: Modern spray tooling routes each HTTP request through rotating residential proxy networks (e.g., BrightData, Oxylabs), ensuring that no single egress IP address executes more than 1 or 2 attempts.
  3. Legacy Protocol Exploitation: Threat actors frequently direct spray attempts against legacy mail endpoints (IMAP4, POP3, ActiveSync, SMTP AUTH) that do not support interactive MFA challenges or Conditional Access device compliance checks.

2. Pre-Attack Reconnaissance: The GetCredentialType Endpoint

Section titled “2. Pre-Attack Reconnaissance: The GetCredentialType Endpoint”

Before launching a spray campaign, sophisticated adversaries curate their target user list to eliminate nonexistent usernames, ensuring they do not generate unnecessary audit noise or invalid-user error codes.

2.1 Probing the Authentication Metadata API

Section titled “2.1 Probing the Authentication Metadata API”

Entra ID exposes an unauthenticated, publicly accessible API endpoint used by the Microsoft login portal to determine tenant branding, realm type (managed vs federated), and credential requirements:

POST /common/GetCredentialType?mkt=en-US HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/json
{
"username": "victim.user@target.com",
"isOtherIdpSupported": true,
"checkPhones": false,
"isRemoteNGCSupported": true,
"isCookieBannerShown": false,
"isFidoSupported": true,
"country": "US",
"forceotclogin": false,
"isExternalFederationDisallowed": false,
"isRemoteConnectSupported": false,
"federationFlags": 0,
"isSignup": false,
"flowToken": "..."
}

2.2 Forensic Interpretation of IfExistsResult

Section titled “2.2 Forensic Interpretation of IfExistsResult”

The API response returns an internal integer field, IfExistsResult, which discloses the existence of the identity without recording any entry in SigninLogs:

IfExistsResult ValueIdentity State in Entra IDForensic Implication
0User Exists (Valid Account)The account is an active cloud identity in the tenant. Added to spray target list.
1User Does Not ExistThe username is invalid. Discarded by attacker.
5Throttled / Rate LimitedMicrosoft STS throttled the request from this specific IP address.
6Domain Exists, Realm is FederatedThe tenant uses federated authentication (ADFS/Ping); requests redirect to on-premises STS.

3. Entra ID Sign-In Telemetry & Error Code Decoding

Section titled “3. Entra ID Sign-In Telemetry & Error Code Decoding”

When an adversary executes a password spray campaign, Entra ID records each attempt in the SigninLogs table. Understanding the exact ResultType status codes is critical for separating benign user mistyping from an active adversary who has uncovered valid credentials:

graph TD
ATT[Spray Attempt Received by STS] --> EVAL{Credential Evaluation}
EVAL -->|Wrong Password| RT_50126[ResultType: 50126<br/>Invalid username or password]
EVAL -->|Account Locked| RT_50053[ResultType: 50053<br/>Smart Lockout triggered]
EVAL -->|Nonexistent User| RT_50056[ResultType: 50056<br/>User does not exist in tenant]
EVAL -->|Password is Correct!| MFA_CHECK{Does User Have MFA Required?}
MFA_CHECK -->|Yes| RT_50076[ResultType: 50076<br/>CRITICAL FORENSIC SIGNAL:<br/>Password valid, redirected to MFA!]
MFA_CHECK -->|No / Legacy Protocol| RT_0[ResultType: 0<br/>SUCCESS: Complete account takeover]

3.1 Essential Sign-In Error Codes for Spray Analysis

Section titled “3.1 Essential Sign-In Error Codes for Spray Analysis”
ResultTypeError DescriptionInvestigation Significance
0SuccessSuccessful authentication. If preceded by multiple 50126 errors, marks a successful spray penetration.
50126Invalid username or passwordThe standard failed attempt. Baseline indicator of password spraying when observed across many accounts.
50053Account is locked (Smart Lockout)The account exceeded lockout thresholds. Indicates aggressive or concurrent spraying.
50056User does not existIndicates the attacker sprayed without prior user enumeration (dirty user dictionary).
50076User redirected to MFAHIGHEST FORENSIC VALUE. Proves the attacker guessed the correct password, but the session was intercepted by an MFA requirement. Immediate containment required!
50079User must register for MFAAttacker guessed valid password on an un-onboarded account; attacker can register their own MFA!
50074Strong Auth Failed (MFA Rejected)The user was prompted for MFA (push/SMS) and rejected or ignored the prompt.
53003Blocked by Conditional AccessCredential was valid, but a CA policy (e.g., location, platform, device) blocked access.

4.1 Detecting Distributed Password Sprays Across Multiple Accounts

Section titled “4.1 Detecting Distributed Password Sprays Across Multiple Accounts”

Identify instances where many unique accounts experience failed logins (50126) within a 2-hour window, originating from multiple distinct IP addresses sharing similar client characteristics:

let ThresholdFailedUsers = 15; // Minimum unique targeted users
let TimeWindow = 2h;
SigninLogs
| where TimeGenerated >= ago(24h)
| where ResultType in (50126, 50053) // Invalid password or locked out
| summarize
FailedAttemptCount = count(),
TargetedUsers = make_set(UserPrincipalName),
TargetedUserCount = dcount(UserPrincipalName),
IPAddresses = make_set(IPAddress),
IPCount = dcount(IPAddress),
Locations = make_set(Location),
AppNames = make_set(AppDisplayName),
UserAgents = make_set(UserAgent)
by bin(TimeGenerated, TimeWindow), ClientAppUsed
| where TargetedUserCount >= ThresholdFailedUsers
| project TimeGenerated, ClientAppUsed, TargetedUserCount, FailedAttemptCount, IPCount, AppNames, UserAgents, TargetedUsers, IPAddresses
| sort by TargetedUserCount desc

4.2 The “Valid Credential Discovery” Query (50126 Followed by 50076 or 0)

Section titled “4.2 The “Valid Credential Discovery” Query (50126 Followed by 50076 or 0)”

Identify specific accounts where an adversary successfully discovered the correct password during a spray campaign:

let SprayedUsers = SigninLogs
| where TimeGenerated >= ago(24h)
| where ResultType == 50126
| distinct UserPrincipalName;
SigninLogs
| where TimeGenerated >= ago(24h)
| where UserPrincipalName in (SprayedUsers)
| where ResultType in (0, 50076, 50079) // Succeeded or valid password requiring MFA
| project TimeGenerated, UserPrincipalName, IPAddress, Location, ResultType, ResultDescription, AppDisplayName, ClientAppUsed, UserAgent
| sort by TimeGenerated asc

4.3 Hunting Legacy Authentication Password Spraying

Section titled “4.3 Hunting Legacy Authentication Password Spraying”

Detect brute-force or spray attacks targeting legacy protocols that bypass modern authentication:

SigninLogs
| where TimeGenerated >= ago(7d)
| where ClientAppUsed in ("IMAP4", "POP3", "SMTP", "Exchange ActiveSync", "MAPI over HTTP", "Autodiscover")
| where ResultType in (50126, 50053, 0)
| summarize
Attempts = count(),
SuccessfulLogins = countif(ResultType == 0),
FailedLogins = countif(ResultType != 0),
DistinctUsers = dcount(UserPrincipalName),
TargetedAccounts = make_set(UserPrincipalName)
by IPAddress, Location, AutonomousSystemNumber, ClientAppUsed, bin(TimeGenerated, 1h)
| where DistinctUsers >= 5
| sort by DistinctUsers desc

5. Architectural Hardening & Mitigation Strategy

Section titled “5. Architectural Hardening & Mitigation Strategy”

To effectively neutralize password spraying, organizations must deploy layered defenses targeting protocol availability, lockout intelligence, and credential requirements:

graph TD
DEF[Anti-Password Spray Architecture] --> L1[1. Block Legacy Authentication<br/>Conditional Access: Client apps = Other / Exchange ActiveSync]
DEF --> L2[2. Configure Entra Smart Lockout<br/>Lockout threshold = 5 / Duration = 15 min / Separate on-prem vs cloud]
DEF --> L3[3. Enforce Phishing-Resistant MFA<br/>Require FIDO2 / Windows Hello / CBA via CA Authentication Strengths]
DEF --> L4[4. Deploy Passwordless Authentication<br/>FIDO2 Keys, Microsoft Authenticator Passwordless, Temporary Access Pass]
  1. Block Legacy Authentication via Conditional Access:
    • Create a tenant-wide Conditional Access policy blocking all client apps categorized as "Exchange ActiveSync clients" and "Other clients" (IMAP, POP, SMTP, MAPI).
  2. Harden Entra ID Smart Lockout:
    • In the Entra Admin Center (Protection $\rightarrow$ Authentication methods $\rightarrow$ Password protection), set Lockout threshold to 5 or 10, and Lockout duration to at least 60 seconds. Smart Lockout tracks IP familiarity, locking out adversary IPs without locking out legitimate users on corporate networks.
  3. Transition to Passwordless Authentication:
    • Eliminating the user password completely removes the attack surface targeted by password spraying.

6. Cross-Reference & Investigation Navigation

Section titled “6. Cross-Reference & Investigation Navigation”