Multi-Factor Authentication Request Generation
This detection identifies MFA fatigue attacks where adversaries possessing valid credentials repeatedly trigger MFA push notifications, SMS codes, or phone calls to overwhelm target users into approving fraudulent authentication requests. The detection monitors Azure AD and identity provider sign-in logs for abnormally high volumes of MFA challenge events against a single account within a short time window, with elevated severity when a successful authentication follows the bombardment — a pattern consistent with documented TTPs from APT29, Scattered Spider, and LAPSUS$. The technique may also abuse Self-Service Password Reset (SSPR) flows to generate MFA requests without initially possessing valid credentials.
What is T1621 Multi-Factor Authentication Request Generation?
Multi-Factor Authentication Request Generation (T1621) maps to the Credential Access tactic — the adversary is trying to steal account names and passwords in MITRE ATT&CK.
This page provides production-ready detection logic for Multi-Factor Authentication Request Generation, covering the data sources and telemetry it touches: Azure Active Directory / Microsoft Entra ID, Microsoft Sentinel. The queries below are rated high severity at high confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Credential Access
- Canonical reference
- https://attack.mitre.org/techniques/T1621/
let MFAInterruptCodes = dynamic(["50074", "50076", "50158", "500121", "50072", "53003"]);
let LookbackWindow = 24h;
let BinSize = 1h;
let MFABombardThreshold = 5;
// Step 1: Aggregate MFA failures per user per hour
let MFAEvents = SigninLogs
| where TimeGenerated > ago(LookbackWindow)
| where ResultType in~ (MFAInterruptCodes)
or (ResultDescription has_any ("MFA", "multi-factor", "strong authentication") and ResultType != "0")
| summarize
MFAAttempts = count(),
UniqueIPs = dcount(IPAddress),
IPList = make_set(IPAddress, 10),
FirstMFARequest = min(TimeGenerated),
LastMFARequest = max(TimeGenerated),
Apps = make_set(AppDisplayName, 5),
ErrorCodes = make_set(ResultType, 10),
Locations = make_set(tostring(LocationDetails), 5)
by UserPrincipalName, bin(TimeGenerated, BinSize);
// Step 2: Find successful logins in the same lookback window
let SuccessEvents = SigninLogs
| where TimeGenerated > ago(LookbackWindow)
| where ResultType == "0"
| summarize
SuccessCount = count(),
EarliestSuccess = min(TimeGenerated),
SuccessIPs = make_set(IPAddress, 5)
by UserPrincipalName;
// Step 3: Join and flag fatigue success scenarios
MFAEvents
| where MFAAttempts >= MFABombardThreshold
| join kind=leftouter (SuccessEvents) on UserPrincipalName
| extend
FatigueSucceeded = iff(isnotnull(EarliestSuccess) and EarliestSuccess > FirstMFARequest, true, false),
DurationMinutes = datetime_diff('minute', LastMFARequest, FirstMFARequest),
RiskLevel = case(
isnotnull(EarliestSuccess) and EarliestSuccess > FirstMFARequest, "Critical",
MFAAttempts >= 10, "High",
"Medium")
| project
TimeGenerated,
UserPrincipalName,
MFAAttempts,
UniqueIPs,
IPList,
DurationMinutes,
FirstMFARequest,
LastMFARequest,
Apps,
ErrorCodes,
Locations,
FatigueSucceeded,
EarliestSuccess,
SuccessIPs,
RiskLevel
| order by MFAAttempts desc Detects MFA fatigue attacks by aggregating Azure AD sign-in failures with MFA interrupt error codes (50074, 50076, 50158, 500121, 50072, 53003) per user per hour. Alerts when a single account exceeds 5 MFA challenges in one hour. Critically flags scenarios where a successful login follows the MFA bombardment window, indicating the fatigue tactic succeeded. RiskLevel field escalates to Critical when FatigueSucceeded is true.
Data Sources
Required Tables
False Positives
- Users with intermittent network connectivity who retry authentication multiple times legitimately, generating repeated MFA prompts without adversarial intent
- Conditional Access policies configured to always require MFA on every request (rather than session-based) can generate high volumes of 50076 events for normal users
- Automated service accounts or scripts using interactive auth flows that repeatedly fail MFA challenge — these should use device-based or certificate auth instead
- IT administrators testing MFA policies, running phishing simulation exercises, or conducting MFA enrollment drives that generate burst MFA events for multiple accounts
Sigma rule & cross-platform mapping
The detection logic for Multi-Factor Authentication Request Generation (T1621) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
product: azure Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for T1621
References (4)
- https://attack.mitre.org/techniques/T1621/
- https://www.cisa.gov/sites/default/files/publications/fact-sheet-implement-number-matching-in-mfa-applications-508c.pdf
- https://portswigger.net/daily-swig/mfa-fatigue-attacks-users-tricked-into-allowing-device-access
- https://www.crowdstrike.com/blog/scattered-spider-attempts-to-avoid-detection-with-bring-your-own-vulnerable-driver-tactic/
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1MFA Fatigue via Python MSAL Repeated Authentication Requests
Expected signal: Azure AD SigninLogs generates 10 entries for [email protected] with ResultType 50076 or 50158 within a 60-second window, all from the test machine's egress IP. If user approves, a ResultType 0 entry appears.
- Test 2MFA Bombardment via Azure AD Token Endpoint curl Loop
Expected signal: Azure AD SigninLogs shows 10 entries for [email protected] with ResultType 50076 or 500121, all with identical IPAddress (test machine egress IP), within 30 seconds. UserAgent field shows curl version string.
- Test 3Okta MFA Bombing via Okta Authentication API
Expected signal: Okta System Log generates policy.auth.mfa.push.sent events for [email protected], 8 events within 40 seconds. In Splunk: sourcetype=okta:im2:log eventType=policy.auth.mfa.push.sent target{}[email protected]
Unlock Pro Content
Get the full detection package for T1621 including response playbook, investigation guide, and atomic red team tests.