Agent Foskett Academy • KQL Academy • Module 11 • Lesson 132

Lesson 132 — Hunting MFA Fatigue and Repeated Authentication Attempts

MFA fatigue attacks rely on repetition.

An attacker already has, or believes they have, the user's first factor. They repeatedly trigger authentication attempts and hope the user eventually approves one, misreads a prompt, or simply wants the notifications to stop.

This lesson uses KQL to hunt the pattern rather than wait for a single alert. We will look for bursts of failures, repeated attempts from the same source, authentication detail patterns and the most dangerous sequence of all: many failures followed by a success.

One failed MFA prompt may be noise. Twenty prompts followed by one success is a story.
Agent Foskett KQL Academy MFA fatigue threat hunting lesson
What you will hunt

Repeated Microsoft Entra authentication activity that may indicate MFA fatigue or credential abuse.

✓ Identify bursts of failures
✓ Group activity by source IP
✓ Inspect authentication details
✓ Find failure-to-success sequences

The investigation begins

08:42 UTC ↓ Failed sign-in ↓ 08:43 Another failure ↓ 08:44 Another authentication attempt ↓ 08:46 Another ↓ 08:49 Another ↓ 09:02 Successful sign-in ↓ QUESTION Did the user finally sign in legitimately... or did repeated authentication pressure end with attacker access?

Learning objectives

Use KQL to identify repeated sign-in failures, group authentication pressure into time windows, compare activity by IP address, inspect authentication details and detect a suspicious transition from repeated failures to success.

Why this matters

MFA reduces account compromise risk, but analysts still need to investigate repeated prompts and unusual authentication sequences. Strong controls improve security; telemetry tells us whether someone is trying to push through them.

Step 1 — review the user's sign-in sequence

Start broad. Before building thresholds, look at the account's actual sign-in sequence.

review-user-signin-sequence.kql
1234567891011121314
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| project TimeGenerated,
          UserPrincipalName,
          IPAddress,
          Location,
          AppDisplayName,
          ResultType,
          ResultDescription,
          AuthenticationRequirement,
          ConditionalAccessStatus
| order by TimeGenerated desc

Read the sequence, not one row

Repeated failures close together in time can mean mistyped credentials, a broken application, stale saved credentials, or hostile activity. The sequence becomes more meaningful when we add source, application and authentication context.

Do not label too early

"Many failures" is not the same as "MFA fatigue." A scheduled client with an expired credential can generate noise. Hunting should identify activity worth investigating, then test competing explanations.

Step 2 — count attempts in 15-minute windows

Summarising activity into short time windows makes bursts easier to see.

count-authentication-bursts.kql
1234567891011
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| summarize AttemptCount=count(),
            FailureCount=countif(ResultType != "0"),
            SuccessCount=countif(ResultType == "0"),
            FirstSeen=min(TimeGenerated),
            LastSeen=max(TimeGenerated)
          by bin(TimeGenerated, 15m), IPAddress
| order by TimeGenerated desc

Why 15 minutes?

It is an investigation choice, not a universal rule. Short windows expose concentrated activity. In your own environment you may test 5, 10, 15 or 30 minutes depending on normal sign-in behaviour.

Failures plus success

The columns FailureCount and SuccessCount let us immediately distinguish a noisy failure burst from a burst that ends with successful access.

Step 3 — find noisy source IP addresses

Now widen the scope. Is one source generating repeated failed sign-ins against one account, or many accounts?

find-noisy-source-ip-addresses.kql
123456789
SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType != "0"
| summarize FailureCount=count(),
            Users=dcount(UserPrincipalName),
            Apps=make_set(AppDisplayName, 10)
          by IPAddress, bin(TimeGenerated, 15m)
| where FailureCount >= 10
| order by FailureCount desc

One user or many?

A source IP targeting multiple identities may indicate password spraying or automated credential testing. A source repeatedly targeting one identity may suggest focused account abuse. Both deserve context.

Thresholds are environment-specific

The example uses ten failures in fifteen minutes only as a hunting starting point. Production detections should be tuned against your organisation's normal traffic and false-positive patterns.

Step 4 — focus on interactive sign-ins

MFA prompt activity is most relevant when the user is actively involved in authentication. Filtering on interactive sign-ins helps reduce unrelated background token activity.

review-interactive-authentication.kql
123456789101112131415
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| where IsInteractive == true
| project TimeGenerated,
          IPAddress,
          Location,
          AppDisplayName,
          ResultType,
          AuthenticationRequirement,
          AuthenticationMethodsUsed,
          AuthenticationDetails,
          CorrelationId
| order by TimeGenerated asc

Authentication requirement

AuthenticationRequirement helps show the highest level of authentication required for the sign-in. It is useful context, but remember that existing MFA claims and session behaviour can affect how an individual sign-in appears.

Methods used

AuthenticationMethodsUsed and AuthenticationDetails give the analyst deeper evidence about how authentication was attempted and what happened at each step.

Step 5 — inspect authentication steps

AuthenticationDetails can contain richer step-by-step information. Parse and expand it so each authentication step can be reviewed separately.

inspect-authentication-steps.kql
1234567891011121314151617
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| extend AuthDetails = parse_json(AuthenticationDetails)
| mv-expand AuthStep = AuthDetails
| extend Method = tostring(AuthStep.authenticationMethod),
         StepResult = tostring(AuthStep.authenticationStepResultDetail),
         StepSucceeded = tostring(AuthStep.succeeded)
| project TimeGenerated,
          IPAddress,
          AppDisplayName,
          ResultType,
          Method,
          StepResult,
          StepSucceeded
| order by TimeGenerated asc

Why parse the details?

A top-level sign-in result may hide the sequence inside the authentication flow. Expanding the authentication steps can expose which method was used and whether a step succeeded or failed.

Schema can evolve

Authentication detail properties can vary by sign-in type and platform updates. Always inspect the raw field in your own tenant before relying on a specific nested property in a production detection.

Step 6 — hunt the dangerous pattern: failures followed by success

This is one of the most useful hunting pivots. We are not proving MFA fatigue; we are surfacing windows where repeated failures and at least one success occur together.

find-failure-to-success-windows.kql
1234567891011121314
let TargetUser = "alex.wilson@contoso.com";
let Window = 30m;
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| summarize FailureCount=countif(ResultType != "0"),
            SuccessCount=countif(ResultType == "0"),
            FirstSeen=min(TimeGenerated),
            LastSeen=max(TimeGenerated),
            IPs=make_set(IPAddress, 20),
            Apps=make_set(AppDisplayName, 20)
          by bin(TimeGenerated, Window)
| where FailureCount >= 5 and SuccessCount >= 1
| order by TimeGenerated asc

Why this pattern matters

A success after repeated failures can be completely legitimate. But it deserves priority because the outcome changed. The analyst should immediately compare IPs, locations, applications, devices and authentication details around the success.

Look for source continuity

If the failures and success come from the same source IP and application within a tight window, the sequence becomes more interesting. If the success comes from the user's normal device and network, a benign explanation may be stronger.

What number matching changes

Microsoft Authenticator number matching is enabled for Authenticator push notifications. It improves resistance to accidental approval because the user must match the sign-in challenge rather than simply approve a generic prompt. That reduces one classic MFA fatigue path, but repeated authentication attempts are still valuable identity telemetry and should still be investigated when the pattern is abnormal.

Evidence table

ObservationWhat it suggestsWhat it does not prove
Repeated failed sign-insAuthentication pressure or a broken credential flow.That an attacker is responsible.
Same IP repeatedly targeting one userFocused activity against one identity.That the IP is malicious.
Same IP targeting many usersPossible automated credential testing or password spray.That every attempt is hostile.
Interactive MFA-related activityThe user may have been involved in the authentication flow.That a prompt was necessarily seen or approved.
Failures followed by successThe authentication outcome changed.That the success belongs to the attacker.
New location/device after failuresThe successful event differs from prior user behaviour.That compromise is confirmed without corroboration.

Agent Foskett's investigation

08:42 First failed sign-in ↓ More failures arrive ↓ Same user ↓ Same source IP ↓ Short time window ↓ KQL groups the activity ↓ Failure count climbs ↓ Authentication details show repeated interactive attempts ↓ 09:02 One sign-in succeeds ↓ The analyst does not stop at "Success" ↓ The successful event is compared with the user's normal location and device ↓ The source is unfamiliar ↓ The timeline is escalated ↓ The pattern is no longer just failed authentication ↓ It is repeated pressure followed by access
Attackers do not need every prompt to work. They only need one.

Investigation questions to ask next

  • Did the failures and success originate from the same IP address?
  • Was the successful sign-in from a known device or location?
  • Which authentication method was used?
  • Was the user actively signing in at the time?
  • Were multiple users targeted by the same source?
  • Did the account access unusual applications after the successful sign-in?
  • Were any authentication methods added or changed around the event?
  • Does the user's normal sign-in history support a benign explanation?
  • Should the successful session be investigated across email, cloud and endpoint telemetry?

Lesson 132 key takeaways

  • MFA fatigue hunting is about patterns, not a single failed event.
  • Use time windows to expose concentrated authentication pressure.
  • Group activity by user and source IP.
  • Distinguish interactive activity from background sign-in noise.
  • AuthenticationDetails can provide deeper step-level evidence.
  • Failures followed by success deserve immediate investigation.
  • Thresholds must be tuned to the environment.
  • Repeated attempts can have benign causes, so preserve alternative explanations.
  • Number matching strengthens Authenticator push security but does not remove the need for hunting.
  • The strongest conclusion comes from sequence plus context.

Continue your KQL investigation training

Lesson 132 continues Module 11: Identity Threat Hunting. Next we move from authentication pressure to identity change: newly registered authentication methods.

Related Agent Foskett Investigations

See how repeated authentication pressure and identity signals appear in investigation stories. Use the lesson queries first, then follow the evidence through these related cases.

🔎 KQL Academy — Module 11: Identity Threat Hunting

Use KQL to investigate identity behaviour as evidence.

Hunt MFA fatigue with KQL

Lesson 132 of the Agent Foskett KQL Academy teaches analysts how to hunt repeated Microsoft Entra authentication attempts using SigninLogs, time-window summaries, source IP correlation, authentication details and failure-to-success sequences.

Microsoft Entra repeated authentication investigation

MFA fatigue investigations require analysts to distinguish normal sign-in noise from concentrated authentication pressure and suspicious successful access. KQL helps expose the sequence and supporting evidence.