Web Session Cookie
Adversaries steal and reuse valid web session cookies to authenticate to web applications and cloud services, effectively bypassing multi-factor authentication. Because session cookies represent a completed authentication event, they allow adversaries to impersonate users without knowing credentials or possessing their MFA device. Cookies are commonly obtained via adversary-in-the-middle (AiTM) phishing frameworks such as Evilginx2, Modlishka, or Muraena, which proxy the legitimate login flow and capture the post-MFA session token in real time. Once imported into an attacker-controlled browser or HTTP client, the stolen cookie grants full access to the victim's SaaS applications, cloud consoles, and email for the lifetime of the session. Star Blizzard (APT29 affiliate) has used this technique via EvilGinx to compromise email accounts protected by MFA.
// T1550.004 — Web Session Cookie Theft: Impossible Travel + MFA-Bypass via Existing Session
let LookbackPeriod = 24h;
let ImpossibleTravelWindowMinutes = 60;
let SuspiciousSingleFactorApps = dynamic(["Microsoft 365", "Office 365", "Azure Portal", "Microsoft Teams", "SharePoint", "OneDrive", "Exchange Online", "Outlook"]);
// Step 1: Build baseline of successful sign-ins with location context
let Signins = SigninLogs
| where TimeGenerated > ago(LookbackPeriod)
| where ResultType == 0
| extend Country = tostring(LocationDetails.countryOrRegion)
| extend City = tostring(LocationDetails.city)
| extend State = tostring(LocationDetails.state)
| extend AuthMethod = tostring(parse_json(tostring(AuthenticationDetails))[0].authenticationMethod)
| extend AuthStepResult = tostring(parse_json(tostring(AuthenticationDetails))[0].authenticationStepResultDetail)
| extend IsCookieReuse = AuthStepResult has_any ("Previously satisfied", "Token broker")
| extend IsInteractiveSession = IsInteractive == true
| project TimeGenerated, UserPrincipalName, IPAddress, Country, City, State,
AppDisplayName, ResourceDisplayName, AuthenticationRequirement, ConditionalAccessStatus,
AuthMethod, AuthStepResult, IsCookieReuse, IsInteractiveSession,
RiskLevelDuringSignIn, RiskLevelAggregated, TokenIssuerType, CorrelationId,
DeviceDetail, ClientAppUsed;
// Step 2: Detect impossible travel — same user, different countries, within threshold
let ImpossibleTravel = Signins
| join kind=inner (
Signins
| project TimeGenerated2=TimeGenerated, UserPrincipalName, IPAddress2=IPAddress,
Country2=Country, City2=City, CorrelationId2=CorrelationId,
AppDisplayName2=AppDisplayName
) on UserPrincipalName
| where CorrelationId != CorrelationId2
| where TimeGenerated > TimeGenerated2
| where Country != Country2 and isnotempty(Country) and isnotempty(Country2)
| where datetime_diff('minute', TimeGenerated, TimeGenerated2) between (0 .. ImpossibleTravelWindowMinutes)
| extend DetectionType = "ImpossibleTravel"
| extend TimeDiffMinutes = datetime_diff('minute', TimeGenerated, TimeGenerated2)
| project TimeGenerated, UserPrincipalName, IPAddress, Country, City, AppDisplayName,
AuthenticationRequirement, IsCookieReuse, RiskLevelDuringSignIn,
PriorIPAddress=IPAddress2, PriorCountry=Country2, PriorApp=AppDisplayName2,
PriorSignIn=TimeGenerated2, TimeDiffMinutes, DetectionType, CorrelationId;
// Step 3: Detect MFA bypass — single-factor auth on MFA-required app with cookie satisfaction
let MFABypassViaCookie = Signins
| where AuthenticationRequirement == "singleFactorAuthentication"
| where IsCookieReuse == true
| where AppDisplayName has_any (SuspiciousSingleFactorApps)
| extend DetectionType = "MFABypassCookieReuse"
| project TimeGenerated, UserPrincipalName, IPAddress, Country, City, AppDisplayName,
AuthenticationRequirement, IsCookieReuse, AuthStepResult,
RiskLevelDuringSignIn, ConditionalAccessStatus, CorrelationId, DetectionType;
// Step 4: Union both detection paths
ImpossibleTravel
| union MFABypassViaCookie
| sort by TimeGenerated desc Data Sources
Required Tables
False Positives
- Legitimate VPN use where user authenticates from one country then routes traffic through another country's VPN exit node
- Corporate proxy or split-tunnel configurations that cause authentication events to appear from multiple geographic locations
- Travel — a user who physically travels between countries, especially with short flights or near-border regions
- Conditional Access policies that explicitly allow persistent browser sessions, generating 'Previously satisfied' MFA claims for legitimate users
- Shared accounts or break-glass emergency accounts accessed from multiple locations by different administrators
References (10)
- https://attack.mitre.org/techniques/T1550/004/
- https://wunderwuzzi23.github.io/blog/passthecookie.html
- https://unit42.paloaltonetworks.com/mac-malware-steals-cryptocurrency-exchanges-cookies/
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-347a
- https://learn.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-sign-ins
- https://learn.microsoft.com/en-us/microsoft-365/security/defender/advanced-hunting-cloudappevents-table
- https://learn.microsoft.com/en-us/microsoft-365/compliance/audit-mailitemsaccessed
- https://github.com/kgretzky/evilginx2
- 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/
- https://techcommunity.microsoft.com/t5/microsoft-entra-blog/how-to-break-the-aitm-phishing-chain/ba-p/3557300
Unlock Pro Content
Get the full detection package for T1550.004 including response playbook, investigation guide, and atomic red team tests.