Steal Web Session Cookie — Microsoft Entra ID Session Token Theft and Replay
Session token theft (also called token replay or pass-the-cookie) is one of the most prevalent identity attacks targeting Microsoft 365 and Entra ID in 2025-2026. Adversaries use adversary-in-the-middle (AiTM) proxy frameworks (Evilginx2, Modlishka, Muraena, Tycoon 2FA, EvilProxy) to intercept valid session cookies from M365 sign-in flows, then replay those cookies to authenticate as the victim without needing their credentials or MFA code. The attack works because Microsoft's authentication cookies are bound to the browser session but not to the originating IP — replaying the cookie from a different IP is detected by Entra ID's risk engine but is not blocked by default. Scattered Spider and Storm-0539 are documented using this technique at scale against SMBs and mid-market organisations, primarily targeting financial fraud (payment diversion, payroll fraud) and IT admin compromise to then facilitate SIM swapping.
What is THREAT-EntraID-TokenTheft Microsoft Entra ID Session Token Theft and Replay?
Microsoft Entra ID Session Token Theft and Replay (THREAT-EntraID-TokenTheft) is a sub-technique of Steal Web Session Cookie (T1539) in the MITRE ATT&CK framework. It maps to the Credential Access and Defense Evasion tactics — the adversary is trying to steal account names and passwords.
This page provides production-ready detection logic for Microsoft Entra ID Session Token Theft and Replay, covering the data sources and telemetry it touches: Azure AD Sign-In Logs (AADSignInLogs), Azure AD Identity Protection (AADRiskyUsers, AADUserRiskEvents), Microsoft 365 Defender Advanced Hunting. The queries below are rated critical severity at high confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Credential Access Defense Evasion
// THREAT: Entra ID Session Token Theft & Replay (AiTM)
// Detects session token replay indicators: impossible travel, sign-in after
// MFA followed by no-MFA sign-in, new IP using existing session
// Alert 1: Impossible travel — same user, successful sign-in from two
// geographically distant IPs within a short time window
let MaxTravelTimeMinutes = 60;
let ImpossibleTravel = AADSignInLogs
| where TimeGenerated > ago(24h)
| where Status.errorCode == 0
| where IPAddress != "" and Location != ""
| summarize
SignInTimes=make_list(TimeGenerated),
IPs=make_list(IPAddress),
Locations=make_list(Location),
MFAResults=make_list(tostring(AuthenticationDetails))
by UserPrincipalName
| mv-expand TimeGenerated=SignInTimes, IP=IPs, Location=Locations to typeof(string)
| order by UserPrincipalName, TimeGenerated asc
| extend PrevTime=prev(TimeGenerated), PrevIP=prev(IP), PrevLoc=prev(Location)
| where UserPrincipalName == prev(UserPrincipalName)
| extend TimeDiff = datetime_diff('minute', todatetime(TimeGenerated), todatetime(PrevTime))
| where TimeDiff between (1 .. MaxTravelTimeMinutes)
and Location != PrevLoc
and IP != PrevIP
| project TimeGenerated, UserPrincipalName, IP, Location, PrevIP, PrevLoc, TimeDiff
| extend ThreatType = "ImpossibleTravel_TokenReplay";
// Alert 2: Successful sign-in from IP not associated with the user's last 30 days
// with no MFA performed (token replay bypasses MFA)
let UserIPBaseline = AADSignInLogs
| where TimeGenerated between (ago(30d) .. ago(1d))
| where Status.errorCode == 0
| summarize KnownIPs=make_set(IPAddress) by UserPrincipalName;
AADSignInLogs
| where TimeGenerated > ago(24h)
| where Status.errorCode == 0
| where AuthenticationRequirement =~ "singleFactorAuthentication"
or (AuthenticationDetails !has "MFA" and AuthenticationDetails !has "Passwordless")
| join kind=leftouter UserIPBaseline on UserPrincipalName
| where not(IPAddress in~ (KnownIPs))
| project TimeGenerated, UserPrincipalName, IPAddress, Location,
AppDisplayName, AuthenticationRequirement, AuthenticationDetails,
RiskLevelDuringSignIn, ConditionalAccessStatus
| extend ThreatType = "NoMFA_NewIP_PossibleTokenReplay" Dual-alert detection for Entra ID token theft: (1) impossible travel — two successful sign-ins from geographically distant locations within a short window, classic AiTM proxy indicator; (2) single-factor authentication from a new IP not seen in the user's 30-day baseline — indicates session token replay bypassing MFA. Both should be correlated with Conditional Access evaluation failures and Entra ID Identity Protection risk events.
Data Sources
Required Tables
False Positives
- Users legitimately travelling who sign in from airports, hotels, or multiple mobile data providers within a short window
- Shared accounts used by multiple team members from different locations (should be eliminated as an SMB practice)
- VPN use that changes apparent location between sign-ins (user connects to VPN on second sign-in but not first)
- Users with MFA remembered on trusted devices who then sign in from a new device without MFA prompt (MFA remembered state is a Conditional Access configuration)
Sigma rule & cross-platform mapping
The detection logic for Microsoft Entra ID Session Token Theft and Replay (THREAT-EntraID-TokenTheft) 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 THREAT-EntraID-TokenTheft
Testing Methodology
Validate this detection against 1 adversary technique 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 1Session Cookie Replay using Evilginx2 Captured Cookie
Expected signal: Azure AD Sign-in logs record a session established from the test IP without MFA, using the replayed cookie. Entra ID Identity Protection may generate an 'Unfamiliar sign-in properties' risk event.
Response Playbook
Triage
- Immediately check Entra ID Identity Protection risk events for the user (Azure AD > Security > Identity Protection > Risky sign-ins). Microsoft's own risk engine may have already flagged this as 'Anonymous IP address', 'Unfamiliar sign-in properties', or 'Impossible travel'.
- Determine whether Conditional Access evaluated and allowed the sign-in. If CA should have blocked the risky sign-in but didn't, investigate the CA policy configuration (is Identity Protection risk evaluated by CA?).
- Identify the application the token was issued for — AiTM token theft most commonly targets: Microsoft 365 (EWS, Graph), SharePoint, or Teams. The application name in the sign-in log indicates what the attacker accessed.
- Review MailItemsAccessed audit log for the user in the 24 hours post-compromise to determine if email was accessed by the attacker. Cross-reference the attacker IP against the Entra ID sign-in logs.
- Determine the vector: did the user receive and interact with an AiTM phishing email? Check email received in the 24 hours before the suspicious sign-in for links to lookalike Microsoft login pages.
Containment
- Immediately revoke all refresh tokens: Azure AD > Users > [User] > Revoke sessions. This invalidates all active sessions and forces re-authentication. Confirm with PowerShell: Revoke-AzureADUserAllRefreshToken.
- Block the attacker IP address(es) in Entra ID Named Locations and create a Conditional Access policy to block sign-in from those IPs.
- Reset the user's password (even though password was not stolen, this forces session invalidation).
- Require re-registration of MFA devices for the affected user to prevent attacker-registered MFA methods.
- Enable Entra ID Identity Protection Conditional Access risk policies: require MFA on medium+ risk and block on high risk sign-ins.
Evidence Collection
- Azure AD Sign-in logs with all fields for the incident window
- Entra ID Identity Protection risk events for the affected user
- O365 MailItemsAccessed audit events
- Conditional Access evaluation logs for the suspicious sign-in
- Network logs from corporate proxy/firewall showing user activity before the phishing click
Escalation Criteria
- ! Attacker accessed financial applications, HR systems, or executive mailboxes
- ! OAuth consent granted to third-party applications by the compromised account
- ! Evidence of internal phishing from the compromised account
- ! Attacker MFA methods registered on the account (attacker persistence)
- ! SharePoint or OneDrive data access suggesting sensitive file exfiltration
Investigation Guide
Forensic Artifacts
- >
Azure AD Sign-in logs with IP, UserAgent, AuthenticationDetails - >
Identity Protection risk event details including IP reputation and geolocation - >
O365 MailItemsAccessed events with ClientIPAddress and OperationProperties - >
Browser forensics on victim endpoint: history, cookies, downloaded files from phishing proxy - >
Email headers of phishing message containing AiTM proxy link
Tuning Guidance
Token theft detection produces the most actionable results when combined with Entra ID Identity Protection risk policies. If Identity Protection is licensed, enable risk-based Conditional Access policies to automatically block high-risk sign-ins rather than just alerting. The impossible travel logic can be tuned by adding an exclusion list for users with known travel patterns or VPN use. Consider using Named Locations in Conditional Access to define expected countries for sign-in, which reduces false positives significantly for most SMBs.
Hunting Queries
Hunt for users with medium/high-risk sign-ins that Conditional Access did not block — these represent gaps in your Identity Protection enforcement that should be remediated.
AADSignInLogs
| where TimeGenerated > ago(7d)
| where Status.errorCode == 0
| where RiskLevelDuringSignIn in ("medium", "high")
| where ConditionalAccessStatus !in ("success") // CA didn't block a risky sign-in
| summarize RiskySignIns=count(), Apps=make_set(AppDisplayName)
by UserPrincipalName, bin(TimeGenerated, 1d)
| sort by RiskySignIns desc index=azure sourcetype="azure:aad:signin" properties.status.error_code=0
properties.risk_level_during_sign_in IN ("medium", "high")
NOT properties.conditional_access_status="success"
| stats count AS RiskySignIns, values(properties.app_display_name) AS Apps
BY properties.user_principal_name, _time span=1d
| sort - RiskySignIns Atomic Red Team Tests
Simulates token replay by extracting a valid Microsoft session cookie from a captured Evilginx2 phishing session and replaying it from a different IP address using a browser automation tool.
Command
python3 -c "import requests; s = requests.Session(); s.cookies.set('ESTSAUTH', '<stolen_cookie>', domain='outlook.office.com'); r = s.get('https://outlook.office.com/mail/'); print(f'Status: {r.status_code}')" Expected Telemetry
Azure AD Sign-in logs record a session established from the test IP without MFA, using the replayed cookie. Entra ID Identity Protection may generate an 'Unfamiliar sign-in properties' risk event.
Expected Detection
Alert fires on single-factor authentication from new IP not in user's 30-day baseline.