HuntCONSTRUCTED

Hunt: repeated MFA prompts denied or unanswered for one account

Accounts with five or more failed MFA challenges in an hour, in Entra ID and Okta. The signature of somebody holding the password and waiting for a tired approval.

Credential AccessT1621checked 2026-09-26

Needs

  • Entra ID sign-in logs, or the Okta System Log, in your SIEM

Will also return

  • A user with a flat phone battery or no signal, retrying repeatedly. Usually a short burst from their own address.
  • A misconfigured device or mail client retrying authentication in a loop.

Reading the results

The count is not the finding; the pattern is. Many prompts from an address the user has never used, at an hour they are asleep, followed by a success, is the row that matters. Many prompts from the user's own address in office hours is usually a phone problem.

Every row, even a benign one, means the password was typed correctly by somebody. When it was not the user, the first-15-minutes checklist starts with changing it.

KQL

Microsoft SentinelUntestedwindow: 1 day, bucketed by hour

500121 is 'authentication failed during strong authentication request', which covers denied and timed-out prompts. Add a join to later successful sign-ins to find the account where one was approved.

SigninLogs
| where TimeGenerated > ago(1d)
| where ResultType == "500121"
| summarize failures = count(), first_seen = min(TimeGenerated), last_seen = max(TimeGenerated),
            source_ips = make_set(IPAddress, 10), apps = make_set(AppDisplayName, 5)
    by UserPrincipalName, bin(TimeGenerated, 1h)
| where failures >= 5
| order by failures desc

SPL

Splunk with the Okta Identity Cloud add-onUntestedwindow: 24 hours

Counts pushes sent and pushes denied per user. Check the sourcetype and the actor field name against one event from your add-on.

index=okta sourcetype="OktaIM2:log" earliest=-24h
  (eventType="system.push.send_factor_verify_push" OR eventType="user.mfa.okta_verify.deny_push")
| stats count(eval(eventType="system.push.send_factor_verify_push")) as pushes_sent
        count(eval(eventType="user.mfa.okta_verify.deny_push")) as pushes_denied
        values(client.ipAddress) as source_ips
    by actor.alternateId
| where pushes_sent >= 5
| sort - pushes_sent

Elastic

ES|QL, Elastic Agent Okta integrationUntestedwindow: 1 day, set in the query
FROM logs-okta.system-*
| WHERE @timestamp > NOW() - 1 day
    AND okta.event_type IN ("system.push.send_factor_verify_push", "user.mfa.okta_verify.deny_push")
| STATS pushes = COUNT(*) BY okta.actor.alternate_id
| WHERE pushes >= 5
| SORT pushes DESC

sources

  1. MITRE ATT&CK T1621, Multi-Factor Authentication Request Generation · primary
  2. Microsoft Learn: Entra authentication and authorization error codes
  3. Okta Developer: System Log API

Tags: hunting · mfa · mfa-fatigue · entra-id · okta · sentinel · splunk · elastic · T1621