↳ GitHub sourceAnalytics ruleMedium

MFA Fatigue (OKTA)

Description

MFA fatigue attack is a cybersecurity threat where attackers exploit user exhaustion from multi-factor authentication prompts to trick them into approving multi-factor authentication prompts, potentially compromising their own security. The query identifies MFA fatigue attempts in Okta by correlating repeated Okta Verify push requests, denied pushes, and eventual successful MFA authentication within the same session. Ref: https://www.okta.com/blog/identity-security/mfa-fatigue-growing-security-concern/.
Rule type
Scheduled
Version
1.1.3
Declared status
Available
Query frequency
1h
Query period
1h
Trigger
gt 0

Declared MITRE coverage

Declared sources

Metadata from the source file. No dependencies inferred from KQL.

Connectors

Data types

KQL query

Original query, unchanged.

// Adjust threshold for MFA pushes to reduce noise
let PushThreshold = 10;
OktaSSO
| where ((eventType_s =="user.authentication.auth_via_mfa" and column_ifexists('debugContext_debugData_factor_s', '') == "OKTA_VERIFY_PUSH") or eventType_s == "system.push.send_factor_verify_push" or eventType_s == "user.mfa.okta_verify.deny_push") 
| summarize IPAddress = make_set(client_ipAddress_s,100), City = make_set(client_geographicalContext_city_s,100),
          successes = countif(eventType_s == "user.authentication.auth_via_mfa"),
          denies = countif(eventType_s == "user.mfa.okta_verify.deny_push"),
          pushes = countif(eventType_s == "system.push.send_factor_verify_push") by TimeGenerated, authenticationContext_externalSessionId_s, actor_alternateId_s,actor_displayName_s, outcome_result_s 
| summarize lasttime = max(TimeGenerated), firsttime = min(TimeGenerated),
          successes = sum(successes), failures = sum(denies), pushes = sum(pushes) by  authenticationContext_externalSessionId_s, actor_alternateId_s,actor_displayName_s, outcome_result_s 
| extend seconds = lasttime - firsttime
| where pushes > PushThreshold
| extend totalattempts = successes + failures
| extend finding = case(
            failures == pushes and pushes > 1, "Authentication attempts not successful because multiple pushes denied",
            totalattempts == 0, "Multiple pushes sent and ignored",
            successes > 0 and pushes > 3, "Multiple pushes sent, eventual successful authentication!",
            "Normal authentication pattern")
| project lasttime, firsttime, seconds, actor_alternateId_s, actor_displayName_s, authenticationContext_externalSessionId_s, pushes, successes, failures, totalattempts, finding, outcome_result_s
| extend AccountName = tostring(split(actor_alternateId_s, "@")[0]), AccountUPNSuffix = tostring(split(actor_alternateId_s, "@")[1])

Declared entities

Account

Related content

Links established from declared identifiers and solution manifests.

Source provenance

GitHub

Displayed values come from files in Azure/Azure-Sentinel. They describe the published template, not your workspace configuration.

Source identifier
c2697b81-7fe9-4f57-ba1d-de46c6f91f9c
Additional source files 2Solutions/Okta Single Sign-On/Analytic Rules/MFAFatigue.yamlsource ↗Solutions/Okta Single Sign-On/data/Solution_Okta.jsonsolution-membership ↗
GSTEP / CATALOG TRACKING

Added to catalog : 16 Sept 2026 · 05:49 UTC
Last change observed : 16 Sept 2026 · 05:49 UTC

GSTEP sync dates, separate from the source content’s publication dates.