An adversary-in-the-middle (AiTM) phishing attack steals the session that a user creates after completing a legitimate sign-in, including MFA, so the attacker never needs to defeat MFA directly. To investigate it, you find the sign-in that created the session, follow that session ID through interactive and non-interactive sign-ins, check what the attacker changed afterwards (inbox rules, authentication methods, devices), and then revoke sessions and remove the persistence they added.
This article gives you a repeatable sequence for that work using Microsoft Entra ID Protection, the Entra sign-in and audit logs in Log Analytics, and Microsoft Defender XDR advanced hunting.
Who this is for and what you will have at the end
This is for security and identity administrators who have a suspected compromised account, an Entra ID Protection alert, or a user report of a fake Microsoft sign-in page, and need to decide quickly whether a session was stolen. By the end you will have:
- A short list of the risk detections that point to token theft and what each one means.
- A set of KQL queries that pivot on session ID, IP address and token details.
- A check for the persistence attackers commonly leave behind.
- A containment and recovery order, with the PowerShell and Graph calls to carry it out.
- A list of preventive controls ranked by how directly they address token replay.
How AiTM token theft works
In an AiTM attack the victim is sent to a phishing site that acts as a reverse proxy in front of the real sign-in page. Microsoft's analysis of a large campaign describes the proxy keeping two TLS sessions, one with the victim and one with the real site, so it can capture both the password and the session cookie that proves the user is signed in. The attacker then injects that cookie into their own browser and skips authentication. Microsoft stresses this is not a flaw in MFA: the cookie is valid regardless of which sign-in method the user completed.
The same analysis describes what followed in that campaign. Roughly five minutes after the victim's first sign-in to the phishing site, the attacker used the stolen cookie to open Outlook on the web. Over the following days they searched finance-related mail, deleted the original phishing message, created inbox rules that moved mail from a target's domain to the Archive folder and marked it read, and replied to existing payment threads. Your investigation therefore has two halves: prove the session was replayed, and find what the attacker did with it.
Token theft is broader than AiTM. Malware on an endpoint can also steal tokens, including the Primary Refresh Token (PRT) on Windows, which is why some detections below come from Microsoft Defender for Endpoint rather than from the sign-in itself.
Prerequisites
- Access to the sign-in and audit logs. For the Entra admin center views, Reports Reader is the least privileged role for the sign-in and audit logs, and Global Reader is the least privileged role to view ID Protection risk reports, per Microsoft's investigation guidance.
- Microsoft Entra ID P2 for full ID Protection detection details. Without P2, premium detections surface as "Additional risk detected" with no details.
- Entra sign-in logs, including non-interactive sign-ins, sent to a Log Analytics workspace so the KQL below runs against
SigninLogsandAADNonInteractiveUserSignInLogs. If you only retain logs in the Entra portal, you can still do the manual steps, but long-range pivots are much harder. See Microsoft Graph PowerShell recipes for user, licence and sign-in reports for pulling sign-in data without a workspace. - Defender XDR with the Entra sign-in data available in advanced hunting for the hunting queries. Microsoft notes that the
EntraIdSignInEventstable needs a Microsoft Entra ID P2 license. - For the response steps, the Microsoft Graph PowerShell SDK and a role that can disable users and revoke sessions. Microsoft's revoke-access guidance lists User Administrator for non-admin users and Privileged Authentication Administrator for admin accounts, and Cloud Device Administrator at minimum to disable devices.
Know the risk detections that point to token theft
ID Protection exposes several detections relevant to stolen sessions. The riskEventType value is what you see in Graph and in the AADUserRiskEvents table.
| Detection | riskEventType | Type | What it tells you |
|---|---|---|---|
| Attacker in the Middle | attackerinTheMiddle | Offline, user risk | An authentication session was linked to a malicious reverse proxy; raises the user to High risk |
| Anomalous token | anomalousToken | Real-time or offline | Unusual token lifetime or a token played from an unfamiliar location |
| Unfamiliar sign-in properties | unfamiliarFeatures | Real-time | Sign-in properties (IP, ASN, location, device, browser) new for this user |
| Token issuer anomaly | tokenIssuerAnomaly | Offline | The SAML token issuer may be compromised; claims look unusual |
| Possible attempt to access PRT | attemptedPrtAccess | Offline, user risk | Defender for Endpoint saw suspicious access to the Primary Refresh Token |
| Suspicious inbox manipulation rules | mcasSuspiciousInboxManipulationRules | Offline | Rules that delete or move messages or folders |
| Suspicious inbox forwarding | suspiciousInboxForwarding | Offline | Rule forwarding mail to an external address |
| Anonymous IP address | anonymizedIPAddress | Real-time | Sign-in from Tor or an anonymous VPN |
Two points from Microsoft's documentation shape how you read these. First, Attacker in the Middle is described as a high-precision detection, but the page lists Microsoft 365 E5 with Enterprise Mobility + Security E5 as the license requirement, so many tenants will never see it. Second, Anomalous token is described as having a higher than normal chance of false positives at low and medium risk levels, so treat it as a trigger to investigate rather than proof.
Microsoft also notes that unfamiliar sign-in properties can fire on non-interactive sign-ins, and that this case deserves increased scrutiny because of the risk of token replay. That is your first hint that the non-interactive table matters.
Check whether a detection already exists for your user:
AADUserRiskEvents
| where RiskEventType in~ ("attackerinTheMiddle", "anomalousToken", "unfamiliarFeatures", "tokenIssuerAnomaly", "attemptedPrtAccess")
| where TimeGenerated > ago(14d)
| sort by TimeGenerated descThis table is populated only if you send the ID Protection risk data to Log Analytics through Entra diagnostic settings. Microsoft's token theft playbook lists RiskyUsers, UserRiskEvents, RiskyServicePrincipals and ServicePrincipalRiskEvents as the categories you can export.
Step 1: Build a timeline for the suspect user
Start with every sign-in for the user across both tables, grouped by session. Interactive sign-ins are those where the user provides an authentication factor; non-interactive sign-ins are where a client uses a token or code on the user's behalf, which is the pattern a replayed token produces.
let target = "[email protected]";
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(7d)
| where UserPrincipalName =~ target
| summarize
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
Events = count(),
IPs = make_set(IPAddress, 10),
ASNs = make_set(AutonomousSystemNumber, 10),
Apps = make_set(AppDisplayName, 10),
UserAgents = make_set(UserAgent, 10)
by SessionId, IsInteractive
| sort by FirstSeen ascRead it like this:
- A session that starts interactively from the user's normal network and device, then shows later events from a different ASN or a different user agent, is the classic replay shape.
- A session with several IPs is not proof on its own. Mobile users roam between networks, so look for combinations: new ASN, new user agent family, a hosting or anonymizing network, and resources the user does not normally touch.
- Compare
AuthenticationRequirement. If the attacker's activity showsmultiFactorAuthenticationbut the user never saw an MFA prompt from that location, the MFA claim was inherited from the stolen session.
Pivot on the attacker IP
Once you have a suspicious IP, find every user it touched. Microsoft's playbook uses a simple SigninLogs | where IPAddress == "x" query; extend it to non-interactive sign-ins as well:
let badIp = "198.51.100.23";
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(30d)
| where IPAddress == badIp
| summarize
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
Successes = countif(ResultType == "0"),
Failures = countif(ResultType != "0")
by UserPrincipalName, AppDisplayName, ResourceDisplayName
| sort by FirstSeen ascResultType of 0 is success in the table reference. Users with successes from the attacker IP are in scope even if ID Protection never flagged them. Also search on the user agent string and the ASN, because attackers rotate IP addresses.
Find sessions that jump networks
To hunt without a known IP, look for successful sessions that span more than one ASN in a short window:
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(1d)
| where ResultType == "0" and isnotempty(SessionId)
| summarize
ASNCount = dcount(AutonomousSystemNumber),
IPs = make_set(IPAddress, 10),
UserAgents = make_set(UserAgent, 10),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by UserPrincipalName, SessionId
| where ASNCount > 1
| sort by ASNCount descExpect noise from phones moving between Wi-Fi and cellular. Use it to build a short list, then review each candidate's user agent, application and resource.
Step 2: Hunt for the phishing session in Defender XDR
Microsoft's AiTM write-up includes advanced hunting queries that find a cookie created at the OfficeHome sign-in and later used from another application in a different country. The queries were published against AADSignInEventsBeta. Microsoft's table page states that EntraIdSignInEvents replaces AADSignInEventsBeta on October 19, 2026 and that existing queries will be migrated automatically, so write new queries against EntraIdSignInEvents. The version below changes the table name and leaves out the original LogonType filter; add it back after confirming the values in your tenant.
let OfficeHomeSessionIds =
EntraIdSignInEvents
| where Timestamp > ago(1d)
| where ErrorCode == 0
| where ApplicationId == "4765445b-32c6-49b0-83e6-1d93765276ca" //OfficeHome application
| where ClientAppUsed == "Browser"
| summarize arg_min(Timestamp, Country) by SessionId;
EntraIdSignInEvents
| where Timestamp > ago(1d)
| where ApplicationId != "4765445b-32c6-49b0-83e6-1d93765276ca"
| where ClientAppUsed == "Browser"
| project OtherTimestamp = Timestamp, Application, ApplicationId, AccountObjectId, AccountDisplayName, OtherCountry = Country, SessionId
| join OfficeHomeSessionIds on SessionId
| where OtherTimestamp > Timestamp and OtherCountry != CountryA hit means a browser session first seen at one country was later used by another application from a different country. Treat each result as a lead, then confirm in the full sign-in timeline from Step 1.
Defender XDR can also raise a "Stolen session cookie was used" alert and correlate related alerts into a single incident, according to the same Microsoft article, so check the Incidents queue before building queries from scratch.
Step 3: Check what the attacker changed
A confirmed or likely stolen session needs a persistence review. Attackers want a way back in that survives session revocation, and a way to hide their activity from the user.
Inbox rules and mailbox changes
The Microsoft campaign analysis shows rules that move mail from a target domain to Archive and mark it read. If an Anomalous token detection tagged a session, this query from the same article finds inbox rules created during that session:
//Find suspicious tokens tagged by AAD "Anomalous Token" alert
let suspiciousSessionIds = materialize(
AlertInfo
| where Timestamp > ago(7d)
| where Title == "Anomalous Token"
| join (AlertEvidence | where Timestamp > ago(7d) | where EntityType == "CloudLogonSession") on AlertId
| project sessionId = todynamic(AdditionalFields).SessionId);
//Find Inbox rules created during a session that used the anomalous token
let hasSuspiciousSessionIds = isnotempty(toscalar(suspiciousSessionIds));
CloudAppEvents
| where hasSuspiciousSessionIds
| where Timestamp > ago(21d)
| where ActionType == "New-InboxRule"
| where RawEventData.SessionId in (suspiciousSessionIds)For a full walk through rule types, forwarding and cleanup, follow Finding malicious inbox and forwarding rules after a compromised mailbox.
New authentication methods
The playbook lists adding a multifactor or passwordless credential as a sign of token theft. Search the audit log for security info changes on the affected user, using the activity names Microsoft's playbook lists:
let target = "[email protected]";
let security_info_actions = dynamic(["User registered security info", "User changed default security info", "User deleted security info", "Admin updated security info", "User reviewed security info", "Admin deleted security info", "Admin registered security info"]);
AuditLogs
| where TimeGenerated > ago(14d)
| where Category =~ "UserManagement"
| where ActivityDisplayName in (security_info_actions)
| extend Initiator = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatorIP = tostring(InitiatedBy.user.ipAddress)
| extend Target = tolower(tostring(TargetResources[0].userPrincipalName))
| where Target =~ target
| project TimeGenerated, ActivityDisplayName, Initiator, InitiatorIP, Target
| sort by TimeGenerated ascA registration from the attacker's IP, or minutes after a suspicious sign-in, means that method must be removed before the account is trusted again. Do the same check for newly registered or enrolled devices in the same window, because a device registered by the attacker can mint new tokens.
What was accessed
Use the unified audit log or CloudAppEvents to see what the attacker's IP did: mail access, file downloads, sharing changes. Microsoft's playbook calls out mass or unusual file downloads and new mailbox forwarding rules as other suspicious behaviours to check. Your goal is to answer one question for the incident record: which data could the attacker read or send. See Searching the Microsoft 365 unified audit log for the search mechanics.
Step 4: Contain the account
Order matters because an attacker who still has a valid password or a registered method can sign in again after you revoke sessions. Microsoft's token theft playbook lists password change, blocking the user, marking the account as compromised in ID Protection, blocking the attacker IP and enabling MFA and risk policies as containment tasks, and advises weighing the business effect of disabling accounts.
A practical sequence for a cloud or hybrid user:
- Mark the user as compromised in ID Protection, in the admin center or through Microsoft Graph. This lets risk-based Conditional Access policies act on the user.
- Disable the account and revoke sessions.
- Reset the password. For a hybrid account, Microsoft's guidance is to reset the password twice in on-premises Active Directory, to reduce the pass-the-hash risk when replication is delayed.
- Remove attacker-registered authentication methods and devices.
- Remove malicious inbox rules and forwarding.
- Re-enable the account, require re-registration of MFA where needed, and watch the sign-in logs for recurrence.
Disable the user, revoke refresh tokens and disable registered devices with Microsoft Graph PowerShell, as in Microsoft's revoke-access article:
Connect-MgGraph -Scopes "User.ReadWrite.All","Directory.AccessAsUser.All"
$User = Get-MgUser -Search UserPrincipalName:'[email protected]' -ConsistencyLevel eventual
Update-MgUser -UserId $User.Id -AccountEnabled:$false
Revoke-MgUserSignInSession -UserId $User.Id
Get-MgUserRegisteredDevice -UserId $User.Id -All | ForEach-Object {
Update-MgDevice -DeviceId $_.Id -AccountEnabled:$false
}In the Entra admin center the same actions are available from the user's page: clear Account enabled under Account status, and select Revoke sessions on the Overview page.
Disabling every registered device is a heavy step for a user who has legitimate managed devices. Review the list first and disable devices the user did not enrol themselves.
Remove attacker-added methods and devices
Microsoft's playbook shows Graph calls for deleting an email method, an authenticator method and a device that the attacker added. Review the user's registered methods first, then delete only the unknown ones:
DELETE /users/{id | userPrincipalName}/authentication/emailMethods/{id}
DELETE /users/{id | userPrincipalName}/authentication/microsoftAuthenticatorMethods/{microsoftAuthenticatorAuthenticationMethodId}
DELETE /devices/{id}Understand the revocation delay
Revoking sessions stops new tokens being issued, but it does not instantly kill every token. Microsoft documents that access tokens issued by Entra ID last 1 hour by default, and that an application using access tokens loses access when the token expires. Applications that use their own session tokens control access with their own authorization policies, and Entra ID cannot revoke those session tokens directly. Continuous access evaluation helps for applications that support it, which is why the preventive controls below matter.
When you cannot safely wait out the delay for a sensitive application, block the attacker IP with a Conditional Access policy or at your federation front end if you are federated, and use Defender for Cloud Apps session controls where you have them.
Step 5: Verify the attacker is out
After containment, confirm three things:
- No successful sign-ins from the attacker IP, ASN or user agent after the revocation time. Re-run the Step 1 pivot query with the time window starting at revocation.
- No new
New-InboxRuleevents or security info changes for the user. - The risk state in ID Protection reflects your decision. Microsoft's investigation guidance describes marking the user or sign-in as confirmed compromised, confirmed safe, or dismissing the risk, depending on what you concluded.
Then widen the net. Search for other users sharing the attacker's IP, ASN or user agent, and for other recipients of the same phishing message. Microsoft's playbook says to iterate until you have found all affected accounts and the attack has stopped. For the mailbox-side response, see Responding to a compromised Microsoft 365 account.
Prevent the next one
| Control | What it does against token theft | Notes |
|---|---|---|
| Phishing-resistant authentication (FIDO2, certificate-based) | Removes credentials that a proxy can relay | Microsoft recommends these methods for AiTM; see Passkeys in Entra ID: deployment guide |
| Conditional Access with device compliance and location | Evaluates signals even when a cookie is replayed | Replayed sessions from an unmanaged device or untrusted location can be blocked |
| Token protection | Binds sign-in session tokens to the device | See Conditional Access token protection for supported apps and rollout |
| Risk-based Conditional Access | Forces password reset, MFA or block on high-risk users and sign-ins | Requires Entra ID P2 |
| Continuous access evaluation | Revokes tokens for CAE-capable apps in near real time | Not every application supports it |
| Anti-phishing and browser protection | Reduces the chance the user reaches the proxy | Microsoft names Edge SmartScreen and email scanning |
Token protection and phishing-resistant authentication address the root cause. Detections and response shorten the time an attacker has once the first two controls are missing.
Troubleshooting
Anomalous token alert but nothing in SigninLogs. Microsoft notes that not every Entra activity-generating alert has a corresponding SigninLogs entry, giving anomalous token detection as an example. Query AADNonInteractiveUserSignInLogs, OfficeActivity, AuditLogs and CloudAppEvents as well.
AADUserRiskEvents returns no rows. The risk data is not in your workspace until you export it with diagnostic settings. Check the Entra diagnostic settings for the risk categories, or review the detections directly in the ID Protection reports.
Attacker still active after revoking sessions. Check for a registered authentication method or device you missed, an application that holds its own session token, and an access token still within its one-hour life. Remove the method, then end application-side sessions where the application supports it.
Many false positives from the cross-ASN query. Add corporate VPN and egress ranges as named locations, which Microsoft also recommends to reduce false positives, and exclude known mobile carriers' ASNs only after reviewing them.
User cannot sign in after you re-enable the account. If you deleted their authentication methods, they need to register again. Issue a Temporary Access Pass if you use one, or follow your normal re-registration process.
Checklist
- Confirm the trigger: ID Protection detection, Defender incident or user report.
- Build the user's timeline across
SigninLogsandAADNonInteractiveUserSignInLogs, grouped bySessionId. - Pivot on attacker IP, ASN and user agent to find other affected users.
- Check inbox rules, security info changes and newly registered devices.
- Disable the account, revoke sessions, reset the password (twice for hybrid).
- Delete attacker-registered methods and devices, and remove malicious rules.
- Mark the user compromised, re-enable, and monitor for recurrence.
- Move to phishing-resistant authentication, token protection and risk-based Conditional Access.
References
- Token theft playbook: https://learn.microsoft.com/en-us/security/operations/token-theft-playbook
- What are risk detections? (Entra ID Protection): https://learn.microsoft.com/en-us/entra/id-protection/concept-identity-protection-risks
- Investigate risk with Microsoft Entra ID Protection: https://learn.microsoft.com/en-us/entra/id-protection/howto-identity-protection-investigate-risk
- Revoke user access in an emergency in Microsoft Entra ID: https://learn.microsoft.com/en-us/entra/identity/users/users-revoke-access
- SigninLogs table reference: https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/signinlogs
- AADNonInteractiveUserSignInLogs table reference: https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/aadnoninteractiveusersigninlogs
- EntraIdSignInEvents table in advanced hunting: https://learn.microsoft.com/en-us/defender-xdr/advanced-hunting-entraidsigninevents-table
- From cookie theft to BEC: AiTM phishing sites as entry point to further financial fraud: https://www.microsoft.com/en-us/security/blog/2022/07/12/from-cookie-theft-to-bec-attackers-use-aitm-phishing-sites-as-entry-point-to-further-financial-fraud/
Comments
Questions and tips are welcome. Comments are checked by the EpiFive team before they appear; please do not share passwords, phone numbers or other private details.