The promise of multi-factor authentication was simple: even if an attacker steals your password, they cannot log in without the second factor. That promise holds true against automated credential stuffing. It does not hold against an attacker willing to pick up the phone.
MFA fatigue attacks — also called push bombing or push spam — expose the human layer of authentication. They require no malware, no CVE, no zero-day. They require only valid credentials, a flood of push notifications, and occasionally a phone call. In 2022, this technique helped breach Uber, Cisco, and multiple other major organizations. Understanding how it works, how to detect it, and how to eliminate the attack surface is essential for any organization relying on push-based MFA.
How MFA Fatigue Works
Push-based MFA (used by Microsoft Authenticator, Duo, Okta Verify, and others) works by sending a notification to a registered mobile device: “Approve this sign-in?” The user taps Approve or Deny.
The attack exploits that simple interaction:
Step-by-Step Attack Flow
1. Credential acquisition
The attacker obtains valid username and password through one of several channels:
- Credential dump purchased on dark web markets (e.g., Genesis Market, now seized, or successor markets)
- Phishing campaign targeting the organization
- Password reuse from an unrelated breach (credential stuffing)
- Infostealer malware (RedLine, Raccoon, Vidar) extracting saved browser credentials
2. Initial MFA push — testing the waters
The attacker attempts to authenticate with the stolen credentials. The identity provider (Entra ID, Okta, Ping) validates the password and sends a push notification. The attacker watches the attempt fail (the user denied it or ignored it) and prepares to escalate.
3. Rapid push flooding
The attacker’s tooling — often a simple loop using the target application’s authentication endpoint — triggers repeated authentication attempts in rapid succession. The victim’s phone is flooded with push notifications.
1# Educational demonstration of rapid auth attempts — for SOC/red team awareness only
2import time
3import requests
4
5# This represents the ATTACKER-SIDE view of triggering repeated auth flows
6# to a service that sends push MFA — purely illustrative of the timing pattern
7auth_endpoint = "https://target-app.example.com/auth/initiate"
8credentials = {"username": "victim@corp.com", "password": "OBTAINED_CREDENTIAL"}
9headers = {"Content-Type": "application/json", "User-Agent": "Mozilla/5.0"}
10
11attempt = 0
12while attempt < 20:
13 response = requests.post(auth_endpoint, json=credentials, headers=headers)
14 print(f"[{attempt+1}] Status: {response.status_code} — MFA push triggered")
15 attempt += 1
16 time.sleep(15) # 15-second intervals to avoid rate-limiting while still overwhelming user
Each iteration sends a push notification to the victim’s device. After 20+ notifications, many users either:
- Accidentally tap Approve (especially if half-asleep or using the phone for another task)
- Deliberately approve to make the notifications stop, assuming it is a system glitch
4. Social engineering escalation
If flooding alone fails, attackers add a social engineering layer. They contact the victim directly — via phone, SMS, Teams, Slack, or WhatsApp — impersonating IT support:
“Hi, this is [FirstName] from the IT helpdesk. We’re migrating some accounts tonight and our system is generating these authentication prompts. Could you approve the next one you receive? It’s needed to complete your account migration. Reference ticket IT-48291.”
The combination of technical stimulus (real push notifications) and social context (fake IT authority) is highly effective.
5. Access granted
The victim approves. The attacker’s authentication session completes. They land in the identity provider’s portal — Microsoft 365, Okta, Salesforce, VPN, or whatever the target application is.
Real Incidents
Uber — September 2022
In September 2022, a threat actor believed to be affiliated with the LAPSUS$ group breached Uber’s internal systems. The initial access vector was a contractor’s credentials purchased from a dark web marketplace. After the push flooding failed to immediately produce an approval, the attacker messaged the contractor on WhatsApp, claiming to be from Uber’s IT security team and stating the MFA prompts were routine. The contractor approved the notification.
Post-compromise, the attacker found a PowerShell script on an internal network share that contained hardcoded credentials for Uber’s PAM (Privileged Access Management) system. This gave them access to AWS production secrets, GCP console, HackerOne bug bounty reports (including unfixed vulnerabilities), and Duo console. The PAM breach was arguably worse than the initial push fatigue.
Key takeaway: MFA fatigue is rarely the final impact — it is the door. What is behind the door determines the severity.
Cisco — August 2022
Cisco disclosed in August 2022 that an employee’s credentials had been compromised following an MFA fatigue attack combined with vishing (voice phishing). The attacker impersonated a Cisco IT support representative. After initial resistance, the employee approved the push.
The attacker’s tooling included Cobalt Strike and a series of privilege escalation attempts. Cisco’s internal EDR and SIEM detected the lateral movement before production systems were impacted. The threat actor (attributed to UNC2447 / a LAPSUS$ affiliate) managed to exfiltrate box.com contents before being evicted.
LAPSUS$ Group — 2021–2022
Microsoft’s March 2022 analysis of LAPSUS$ (tracked internally as DEV-0537) documented MFA push bombing as a primary initial access technique at multiple targets including Microsoft, Okta, T-Mobile, Samsung, Nvidia, and Ubisoft. The group layered push bombing with:
- SIM swapping to take control of the victim’s phone number
- Helpdesk social engineering to reset MFA registrations
- Employee recruitment — paying insiders at target organizations to approve MFA requests or provide VPN access
The Okta breach (January 2022, disclosed March 2022) originated with LAPSUS$ compromising a support engineer at a third-party contractor (Sitel). The initial access was enabled by an MFA push approval on a compromised device.
Detection
Microsoft Entra ID — KQL for MFA Fatigue Pattern
// Detect repeated MFA failures followed by success — classic fatigue pattern
SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType != 0 // Non-zero = failure
| where AuthenticationRequirement == "multiFactorAuthentication"
| summarize
MFA_Failures = countif(ResultType != 0),
First_Failure = min(TimeGenerated),
Last_Failure = max(TimeGenerated)
by UserPrincipalName, IPAddress, AppDisplayName
| where MFA_Failures >= 5
| join kind=inner (
SigninLogs
| where ResultType == 0
| where AuthenticationRequirement == "multiFactorAuthentication"
| project Success_Time = TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, DeviceDetail
) on UserPrincipalName
| where Success_Time between (First_Failure .. (Last_Failure + 30m))
| project UserPrincipalName, IPAddress, MFA_Failures, First_Failure, Last_Failure, Success_Time, AppDisplayName, DeviceDetail
| order by MFA_Failures desc
// Detect MFA success from new country after recent failures
let prior_countries = SigninLogs
| where TimeGenerated between (ago(30d) .. ago(1d))
| where ResultType == 0
| summarize known_countries = make_set(Location) by UserPrincipalName;
SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType == 0
| where AuthenticationRequirement == "multiFactorAuthentication"
| join kind=inner prior_countries on UserPrincipalName
| where not(Location in (known_countries))
| project TimeGenerated, UserPrincipalName, Location, IPAddress, AppDisplayName, UserAgent
| order by TimeGenerated desc
Splunk SPL — MFA Push Fatigue Detection
index=azure_signin OR index=okta_logs
| eval mfa_result = coalesce(authenticationResult, status.value)
| where mfa_result IN ("failure", "denied", "MFA_DENIED")
| bin _time span=10m
| stats
count as mfa_failures,
values(src_ip) as source_ips,
min(_time) as window_start,
max(_time) as window_end
by user, _time
| where mfa_failures >= 5
| join type=inner user [
search index=azure_signin OR index=okta_logs mfa_result="success"
| where _time >= window_end AND _time <= (window_end + 1800)
| stats min(_time) as success_time by user
]
| eval minutes_to_success = round((success_time - window_end) / 60, 1)
| table user, mfa_failures, window_start, success_time, minutes_to_success, source_ips
| sort - mfa_failures
Conditional Access Policy — Limit Auth Frequency
Deploy a Conditional Access policy in Microsoft Entra ID to enforce sign-in frequency limits and block authentication from unknown devices:
1{
2 "displayName": "MFA Fatigue Mitigation — Require Compliant Device + Limit Frequency",
3 "state": "enabled",
4 "conditions": {
5 "users": {
6 "includeUsers": ["All"]
7 },
8 "applications": {
9 "includeApplications": ["All"]
10 },
11 "signInRiskLevels": ["medium", "high"]
12 },
13 "grantControls": {
14 "operator": "AND",
15 "builtInControls": [
16 "mfa",
17 "compliantDevice"
18 ]
19 },
20 "sessionControls": {
21 "signInFrequency": {
22 "value": 1,
23 "type": "hours",
24 "isEnabled": true
25 },
26 "persistentBrowser": {
27 "mode": "never",
28 "isEnabled": true
29 }
30 }
31}
IOCs and Behavioral Indicators
- More than 5 MFA push attempts within 10 minutes from the same user
- Authentication source IP geolocated outside employee’s typical country
- Sign-in attempts at 2–5 AM local time for the account (common for overseas attackers)
- Successful MFA following a burst of failures from the same IP or user agent
- Authenticator app registration of a new device shortly after push flooding
Defense and Mitigation
1. Number Matching (Deploy Immediately)
Number matching is the single highest-impact control against MFA fatigue. Since May 2023, Microsoft has enforced it by default in Authenticator for Entra ID. If your tenant has not migrated, enable it explicitly:
In Entra ID > Authentication methods > Microsoft Authenticator:
- Enable Number matching for all users
- Enable Additional context (shows app name and sign-in location in the push)
With number matching active, the attacker’s push shows a number the victim is not seeing — approval requires deliberate action matching the displayed code, not a simple tap.
2. FIDO2 Security Keys / Passkeys
FIDO2 is the only authentication method that is both phishing-resistant and fatigue-resistant. There is no push to spam. Replace push MFA with FIDO2 security keys (YubiKey, Feitian, etc.) or platform passkeys (Windows Hello, Touch ID, Face ID) for all privileged users and high-risk populations first.
1# Enable FIDO2 authentication method in Entra ID via Microsoft Graph
2$body = @{
3 "@odata.type" = "#microsoft.graph.fido2AuthenticationMethodConfiguration"
4 state = "enabled"
5 isAttestationEnforced = $false
6 keyRestrictions = @{
7 isEnforced = $false
8 enforcementType = "allow"
9 }
10} | ConvertTo-Json
11
12Invoke-MgGraphRequest -Method PATCH `
13 -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/fido2" `
14 -Body $body
3. Entra ID Identity Protection — Risky Sign-In Policies
Enable Identity Protection policies that require re-authentication or block access when sign-in risk is elevated:
- User risk policy: Require password change when user risk is High
- Sign-in risk policy: Block access or require strong auth when sign-in risk is Medium or High
- MFA registration policy: Require MFA registration for all users
These policies integrate with Conditional Access and can automatically block fatigue-based sign-in attempts when anomalous patterns are detected.
4. Helpdesk Verification Procedures
Most push fatigue attacks involve a vishing component. Harden helpdesk procedures:
- Require out-of-band identity verification before any MFA resets (manager approval, video call with ID, callback to known phone number on file)
- Prohibit helpdesk staff from approving MFA prompts on behalf of users
- Train users explicitly: “IT will never call you to ask you to approve a push notification”
5. Entra ID Authentication Strength Policies
Create an Authentication Strength policy that excludes push MFA for access to sensitive applications (Azure Portal, Exchange Admin, SharePoint Admin):
In Entra ID > Security > Authentication Methods > Authentication strengths:
- Create a custom strength requiring only FIDO2 or certificate-based authentication for Tier 0/Tier 1 app access
- Apply via Conditional Access to privileged role holders
6. Monitor and Alert on MFA Anomalies
Deploy automated alerting via Microsoft Sentinel or your SIEM for the patterns described in the detection section. Wire alerts to SOAR playbooks that can automatically:
- Disable the user account in Entra ID (temporarily)
- Revoke active sessions
- Page the security team for manual review
Summary
MFA fatigue is a social engineering attack at its core — one that uses a legitimate technical mechanism (push notifications) as the weapon. The defense is not to abandon MFA but to upgrade to phishing-resistant MFA (FIDO2/passkeys) and add friction to push-based approvals through number matching and additional context. Robust detection — specifically hunting for bursts of MFA failures followed by success — enables SOC teams to respond before the attacker establishes persistence.
MITRE ATT&CK: T1621 — Multi-Factor Authentication Request Generation
Related Attacks in This Series
- OAuth Token Theft: Hijacking App Permissions
- SIM Swap Attack: Taking Over Your Phone Number
- Golden Ticket Attack: Forging Kerberos Tickets
- Deepfake CEO Fraud: Voice Cloning and Social Engineering
- QR Code Phishing (Quishing): Malicious QR Codes
References
- MITRE ATT&CK T1621 — MFA Request Generation
- Microsoft MSTIC — DEV-0537 (LAPSUS$) Techniques
- Uber Security Incident 2022 — Uber Newsroom
- Cisco Talos — Cisco Security Incident Disclosure August 2022
- Microsoft — Number Matching in Microsoft Authenticator
- CISA — Phishing-Resistant MFA Fact Sheet
- Microsoft Entra ID — Identity Protection Overview
- FIDO Alliance — FIDO2 Technical Specifications






