
Even MFA Isn’t Enough: How Attackers Are Hijacking Microsoft 365 Sessions – And What You Can Do About It
In February 2025, Microsoft disclosed an active phishing campaign conducted by a Russian state-aligned threat actor, Storm-2372. Unlike conventional phishing, this campaign exploited a legitimate Microsoft login feature—device code flow authentication—to bypass even phishing-resistant MFA and gain access to Microsoft 365 accounts. The attack is deceptively simple, difficult for victims to detect, and effective even in mature security environments.
What Is Device Code Authentication?
Device code flow is an OAuth 2.0 authentication method intended for devices without keyboards—like smart TVs, printers, or meeting room consoles. Instead of typing usernames and passwords, users are shown a short code and asked to visit https://microsoft.com/devicelogin
on another device, where they enter the code and complete the login.
It’s secure when used as intended.
But Storm-2372 weaponized it.
The Attack Explained: How Storm-2372 Abused Device Codes
Step-by-step attack flow:
Generate Device Code: The attacker uses a legitimate Microsoft application ID (like Microsoft Teams or Authenticator Broker) to generate a device code and user code from Microsoft’s endpoint.
Send the Code via Phishing: The attacker sends an email or message impersonating someone familiar, often with a fake Teams invite. The message includes:
A code (e.g.,
CMUZKJSCW
)A legitimate Microsoft URL (e.g.,
https://microsoft.com/devicelogin
)
Victim Logs In: The victim, thinking it’s a meeting invite, enters the code on Microsoft’s legitimate site, then completes username + password + MFA.
Token Issued to Attacker: Microsoft links the authentication to the original request (from the attacker). The attacker gets:
An Access Token to act as the user
Often a Refresh Token to maintain access
Data Access and Lateral Movement:
Storm-2372 uses Microsoft Graph API to access email, search for sensitive content (e.g., “password”, “gov”, “secret”), and exfiltrate data.
Compromised accounts are used to send additional phishing messages internally.
Advanced Persistence:
Storm-2372 escalated by using the Microsoft Authentication Broker client ID to register a new device in Azure AD.
This gives them a Primary Refresh Token (PRT), which enables seamless SSO access—bypassing device-based Conditional Access policies.
Why MFA Didn’t Help
This attack doesn’t bypass MFA technically—instead, it tricks the user into completing a real MFA challenge.
The login page is legitimate
The app appears to be a known Microsoft application
Users unknowingly approve a login request for the attacker’s session
Because of this, even phishing-resistant MFA (like FIDO2 keys or Authenticator apps) offers no protection if the user is socially engineered to approve the wrong request.
Why FIDO2 won't work either?
FIDO2 and other phishing-resistant MFA methods are designed to stop attackers from stealing or replaying authentication credentials. But in this attack, users willingly authenticate the attacker’s session via Microsoft’s legitimate login page. The victim is not tricked into giving away their credentials—instead, they complete a valid MFA challenge, unknowingly for a malicious request.
Since FIDO2 confirms who is authenticating, but not what session they’re authenticating, it doesn’t stop this type of deception. The user believes they’re signing into a Teams meeting—they’re actually granting token access to a rogue application. The weakest link remains the human behind the authenticator.
Detection: How to Spot a Device Code Phishing
1. Azure AD Sign-in Logs
Look for:
Error Code 50199 followed shortly by a success (Error Code 0)
Authentication Protocol:
deviceCode
Unexpected app names (e.g., Microsoft Authenticator Broker used for a Teams invite)
2. New Device Registrations
Storm-2372 registered attacker-controlled devices in Entra ID:
Check Azure AD > Devices for unexpected joins
Look for log entries by the “Device Registration Service”
3. Phishing Email Traits
Emails referencing
microsoft.com/devicelogin
Fake meeting invites with suspicious “Meeting IDs” that are actually device codes
Use Defender for Office 365 to scan for these URLs.
4. Risky Sign-ins
Azure AD Identity Protection flags:
Anonymous IP usage
Unfamiliar sign-in properties
Microsoft Defender Detection Queries
1. Detect Device Code Authentication Attempts
SigninLogs
| where AuthenticationProtocol == "deviceCode"
| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress, Status, ClientAppUsed
Purpose: Identifies any sign-in attempts using the device code flow. Investigate users or apps that typically don’t use this method.
2. Look for Error Code 50199 Followed by Success (Token Granted Pattern)
SigninLogs
| where ErrorCode in (50199, 0)
| summarize Codes = make_set(ErrorCode) by UserPrincipalName, SessionId, AppDisplayName
| where 50199 in (Codes) and 0 in (Codes)
Purpose: This pattern shows a pending device code login followed by success — often indicating the victim entered the code and logged in.
3. Find Device Registrations via Microsoft Authentication Broker
AuditLogs
| where OperationName has "Join device"
| where InitiatedBy.user.userPrincipalName has "@"
| project TimeGenerated, InitiatedBy, TargetResources, Result
Purpose: Detects if an attacker used the device registration trick for persistence using the Microsoft Authentication Broker.
4. Find Inbox Rule Manipulations (Persistence or Data Exfiltration)
CloudAppEvents
| where ActionType in ('New-InboxRule','Set-InboxRule','UpdateInboxRules')
| project TimeGenerated, AccountDisplayName, ActionType, Application, IPAddress
Purpose: Attackers sometimes create inbox rules to hide alerts or exfiltrate emails.
5. Email Clicks on microsoft.com/devicelogin
EmailUrlInfo
| where Url has "microsoft.com/devicelogin"
| project TimeGenerated, RecipientEmailAddress, Url, NetworkMessageId
Purpose: Shows if any user clicked on a phishing link containing the legit-looking device login URL.
6. Sign-ins From Anonymous IPs or Known Bad Locations
SigninLogs
| where RiskLevelDuringSignIn in ("medium", "high")
| where RiskEventTypes contains "anonymousIPAddress" or RiskEventTypes contains "investigationsThreatIntelligence"
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, AuthenticationProtocol
Purpose: Shows sign-ins flagged by Azure AD as risky (e.g., Tor, VPN, or threat intelligence sources).
7. Correlate Clicked Emails and Sign-ins
let clicks = EmailUrlInfo
| where Url has "microsoft.com/devicelogin"
| project ClickTime = TimeGenerated, User = RecipientEmailAddress;
let logins = SigninLogs
| where AuthenticationProtocol == "deviceCode"
| project LoginTime = TimeGenerated, UserPrincipalName, IPAddress;
clicks
| join kind=inner (
logins
) on $left.User == $right.UserPrincipalName
| where datetime_diff("minute", ClickTime, LoginTime) <= 10
Purpose: Finds users who clicked a device login link and authenticated shortly after — strong compromise indicator.
How to Defend Your Organization
Block Device Code Flow (Best Option)
Use Conditional Access to block device code flow completely if your org doesn’t use it.
How to set it up:
Go to Microsoft Entra Admin Center > Conditional Access
Create a new policy:
Users: All users (exclude break-glass)
Cloud apps: All apps
Conditions > Authentication flows:
device code
selectedGrant:
Block access
Run in report-only mode first
Turn on if no legitimate use detected
👉 Microsoft Guide: Block authentication flows
Allow Device Code Flow with Restrictions
If you must use device code flow:
Restrict it to specific users or IP ranges
Apply sign-in risk policies to block or MFA challenge risky logins
Audit Device Joins
Restrict device join permissions to only IT or specific groups
Set maximum devices per user to 1–2 where possible
Investigate new joins from unfamiliar devices
Harden Token Lifetime Policies
Reduce Refresh Token lifetime
Use Continuous Access Evaluation (CAE) to auto-revoke tokens on risk events
Train Your Users
Educate staff—especially execs and VIPs—on:
How device code phishing works
How to verify app names during login
Why they should never enter codes unless explicitly instructed by IT
Share sanitized examples to improve awareness.
If You’ve Been Compromised
- Revoke Sessions: In Entra ID > User > Revoke Sign-in Sessions
Reset Passwords and MFA for affected users
Remove Suspicious Devices from Azure AD
Check Mailbox Rules for forwarding or hiding rules
Investigate Sent Items for lateral phishing emails
Search Logs for data access and token issuance
Key Hunting Queries
- Device Code Authentication Attempts:
SigninLogs
| where AuthenticationProtocol == "deviceCode"
Suspicious Token Issuance:
SigninLogs
| where AppDisplayName == "Microsoft Authenticator" and AuthenticationProtocol == "deviceCode"
New Device Registrations:
AuditLogs
| where OperationName contains "Join device"
Inbox Rule Changes (Advanced Hunting):
CloudAppEvents
| where ActionType in ('UpdateInboxRules','New-InboxRule','Set-InboxRule')
Final Thoughts
Storm-2372’s campaign is a wake-up call: even MFA or FIDO2 can’t save you if users authenticate malicious sessions. Fortunately, you can stop this specific attack by disabling device code authentication or restricting its use to safe conditions.
Security is layered—MFA, training, monitoring, and policy controls must all work together. Now’s the time to review your Microsoft 365 auth flows and get ahead of the next Storm.