AiTM Phishing (Adversary-in-the-Middle)
ATT&CK: T1557 — Adversary-in-the-Middle, T1539 — Steal Web Session Cookie
AiTM phishing uses a reverse proxy between the victim and the legitimate identity provider. The victim authenticates normally — including completing MFA — but the proxy captures both the password and the authenticated session cookie (post-MFA). The attacker replays the session cookie and gains authenticated access, bypassing MFA entirely.
Why Classic MFA Fails Against AiTM
Traditional MFA protects against password theft but not session cookie theft. Once the user completes authentication (including MFA), the IDP issues a session token. AiTM steals that token:
Normal flow:
Browser → [password + MFA] → IDP → [session cookie] → SaaS app
AiTM flow:
Browser → [password + MFA] → Proxy → [relays everything] → IDP
↓
Proxy captures session cookie
↓
Attacker uses cookie directly
Toolkits
| Toolkit | Technique |
|---|---|
| Evilginx2 | Reverse proxy; captures sessionid + cookie for any IDP |
| Modlishka | Similar reverse proxy approach |
| Muraena + NecroBrowser | Headless browser-based session capture |
| Storm-0867 / Caffeine kit | Phishing-as-a-Service platforms (pre-built AiTM) |
Evilginx2 Attack Flow
1. Attacker configures Evilginx2 with "phishlets" for M365 / Okta / etc.
2. Phishlet intercepts and proxies all authentication traffic
3. Victim receives phishing link → lands on fake domain (e.g., login.microsoftonline[.]attackerdomain[.]com)
4. Victim enters credentials and completes MFA normally
5. Evilginx2 captures:
- Username + password
- Session cookies (e.g., ESTSAUTH, ESTSAUTHPERSISTENT for M365)
6. Attacker extracts cookies from Evilginx2 → imports into browser
7. Attacker is logged in as victim without triggering any MFA challenge
Real-World Campaigns
Storm-0558 (2023)
Chinese-attributed APT used forged tokens AND session cookie hijacking against M365. Compromised multiple US government email accounts. MSA (Microsoft Account) key compromise allowed forging any cloud identity token — the extreme end of session token theft.
Business Email Compromise + AiTM
Microsoft Threat Intelligence documented large-scale AiTM campaigns in 2022-2023:
-
10,000 organizations targeted in a single campaign
- Phishing emails with HTML attachment that redirected to Evilginx2 infrastructure
- Stolen sessions used immediately for BEC (business email compromise) fraud
APT29 / Midnight Blizzard
Used a combination of residential proxy services (to match victim geolocations) and session token replays to maintain persistent access to M365 after initial compromise.
What Gets Stolen
| Token Type | Where Used | Lifetime |
|---|---|---|
| ESTSAUTH (M365) | Browser session cookie for authenticated state | Session |
| ESTSAUTHPERSISTENT (M365) | Persistent session (keep-me-signed-in) | Up to 90 days |
| refresh_token | OAuth refresh; can get new access tokens | 14-90 days |
| access_token | Bearer token for API calls | 1 hour |
| PRT (Primary Refresh Token) | Windows device-level token; can mint any M365 token | 14 days |
Detection
Microsoft Entra ID Signals
| Signal | Event / Category |
|---|---|
| Sign-in from anonymous IP (Tor, VPN) | Entra ID Protection: anonymizedIPAddress risk |
| AiTM session cookie detected | Entra ID Protection: aiTMAttack risk detection (GA 2023) |
| Token replay from different IP | Entra ID Protection: tokenIssuerAnomaly |
| Impossible travel | Entra ID Protection: impossibleTravel |
| Unusual inbox rules created post-auth | Defender for Office 365 / MCAS |
| Mass email forwarding rule created | Defender for Office 365 |
KQL — Detect AiTM Session Anomaly
// Entra sign-in cookie reuse from different IP than original authentication
SigninLogs
| where RiskEventTypes_V2 has "aiTMAttack"
| project TimeGenerated, UserPrincipalName, IPAddress, RiskLevel, RiskEventTypes_V2, DeviceDetail, LocationDetails
| order by TimeGenerated desc
// MFA success followed immediately by sign-in from different country
let mfa_successes = SigninLogs
| where AuthenticationRequirement == "multiFactorAuthentication"
| where ResultType == 0
| project UserPrincipalName, TimeGenerated, IPAddress, LocationDetails;
SigninLogs
| where TimeGenerated > ago(1h)
| join kind=inner mfa_successes on UserPrincipalName
| where IPAddress != IPAddress1
| where LocationDetails.countryOrRegion != LocationDetails1.countryOrRegion
| project UserPrincipalName, AuthTime=TimeGenerated1, MFACountry=LocationDetails1.countryOrRegion, SessionCountry=LocationDetails.countryOrRegion
Microsoft 365 — Post-Auth Indicators
// Inbox forwarding rules created after suspicious sign-in
OfficeActivity
| where Operation in ("Set-Mailbox", "New-InboxRule", "Set-InboxRule")
| where Parameters has "ForwardTo" or Parameters has "RedirectTo"
| join kind=inner (
SigninLogs | where RiskLevel in ("medium", "high")
) on $left.UserId == $right.UserPrincipalName
| project TimeGenerated, UserId, Operation, Parameters
Bypass: What Does NOT Stop AiTM
| Control | Stops AiTM? | Reason |
|---|---|---|
| TOTP / Push MFA | No | Victim completes MFA; cookie stolen post-auth |
| SMS OTP | No | Same — token stolen post-auth |
| Password + MFA combined | No | Both completed through the proxy |
| Conditional Access (IP-based) | Partial | If attacker uses residential proxy matching victim location |
| Legacy MFA "require MFA" policy | No | Policy is satisfied through the proxy |
What STOPS AiTM
| Control | Why It Works |
|---|---|
| FIDO2 / Passkeys | Origin-binding — FIDO2 credential is cryptographically bound to the legitimate domain, not the attacker's proxy domain. Phishing domain gets a different assertion → authentication fails. |
| Certificate-based auth (smart card) | Client cert is issued for the legitimate domain — cannot be relayed |
| Conditional Access: Compliant Device | Attacker doesn't have a compliant device; session cookie alone is insufficient |
| Token Binding | Cryptographically binds tokens to the TLS session — not widely deployed yet |
| Continuous Access Evaluation (CAE) | Detects token replay from unexpected IP/conditions and revokes mid-session |
Response Actions
- Revoke all active sessions:
Revoke-AzureADUserAllRefreshTokenor Entra admin portal - Reset password + force MFA re-enrollment
- Investigate post-compromise activity: forwarding rules, OAuth app consent, mailbox exports
- Check for PRT compromise (if on Windows device) → pass-the-prt
- Enable Conditional Access: require compliant device or FIDO2 for high-risk users
Cross-Links
| Topic | Link |
|---|---|
| MFA Fatigue | mfa-fatigue |
| Pass-the-PRT | pass-the-prt |
| MFA Technologies | mfa-technologies |
| Entra ID Identity Protection | identity-protection |
| Detect: MFA Fatigue | detect-mfa-fatigue |