Detect Microsoft Entra ID Session Token Theft and Replay in CrowdStrike LogScale
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.
MITRE ATT&CK
- Tactic
- Credential Access Defense Evasion
LogScale Detection Query
// Entra ID Session Token Theft & Replay — CrowdStrike Falcon LogScale (CQL)
// Requires: Microsoft 365 / Entra ID data ingested via CrowdStrike Falcon for Microsoft 365
#event_simpleName="AzureADSignIn" status.errorCode=0
| eval user=userPrincipalName, ip=ipAddress, loc=location, auth=authenticationDetails
| eval mfa_used=if(match(auth, "(?i)(MFA|Passwordless|FIDO)"), "true", "false")
| sort user, @timestamp
| groupBy([user], function=[
collect([ip, loc, mfa_used, @timestamp], limit=1000)
])
// Flatten and compute sequential pairs
| mvexpand field=ip limit=1000
| rename ip as current_ip
// --- Impossible Travel sub-detection ---
// Join consecutive events per user and flag travel > impossible threshold
#event_simpleName="AzureADSignIn" status.errorCode=0
| eval user=userPrincipalName, ip=ipAddress, loc=location
| eval mfa_used=if(match(authenticationDetails, "(?i)(MFA|Passwordless|FIDO)"), "true", "false")
| sort user, @timestamp
| delta(field=@timestamp, as=time_diff_ms, window=1, partition=user)
| eval time_diff_minutes=time_diff_ms / 60000
| delta(field=ip, as=prev_ip_val, window=1, partition=user)
| delta(field=loc, as=prev_loc_val, window=1, partition=user)
| delta(field=mfa_used, as=prev_mfa_val, window=1, partition=user)
| eval impossible_travel=if(
ip != prev_ip_val
AND loc != prev_loc_val
AND time_diff_minutes > 0
AND time_diff_minutes < 60,
"true", "false"
)
| eval token_replay=if(
mfa_used="false"
AND prev_mfa_val="true"
AND ip != prev_ip_val,
"POSSIBLE_TOKEN_REPLAY", "NORMAL"
)
| where impossible_travel="true" OR token_replay="POSSIBLE_TOKEN_REPLAY"
| eval threat_type=if(impossible_travel="true", "ImpossibleTravel_TokenReplay", "NoMFA_NewIP_TokenReplay")
| eval threat_actors="Scattered Spider, Storm-0539, Midnight Blizzard"
| table(@timestamp, user, ip, loc, prev_ip_val, prev_loc_val, time_diff_minutes, mfa_used, prev_mfa_val, threat_type, threat_actors)
| sort -@timestamp CrowdStrike Falcon LogScale CQL query detecting Entra ID session token theft and replay (AiTM). Uses delta() to compute per-user sequential sign-in deltas, then flags impossible travel (two different geo IPs within 60 min) and MFA downgrade (prior MFA session followed by no-MFA sign-in from new IP). Covers Scattered Spider and Storm-0539 TTPs.
Data Sources
Required Tables
False Positives & Tuning
- VPN split-tunnel configurations causing IP changes between authenticated API calls
- Legitimate roaming users switching between office, hotel, and mobile hotspot networks
- Conditional Access policies that explicitly exempt compliant devices from step-up MFA
- Federated SSO where upstream IdP handles MFA and Entra ID does not record MFA in auth details
- Automated scripts or service principals authenticating from multiple Azure regions using cached tokens
Other platforms 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
Related Techniques
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.