Back to Intelligence

EvilTokens PhaaS Takedown: Defending Entra ID Against Device Code Phishing and Token Theft

SA
Security Arsenal Team
September 23, 2026
13 min read

Microsoft's Digital Crimes Unit (DCU), working with industry partners, has facilitated a disruption of infrastructure belonging to EvilTokens — a Phishing-as-a-Service (PhaaS) platform that had rapidly risen to become one of the most prolific kits enabling device code social engineering attacks against Microsoft Entra ID environments. According to Microsoft's September 2026 disclosure, EvilTokens industrialized a technique we've been tracking in hands-on intrusions for over a year: abusing the legitimate OAuth 2.0 device authorization grant flow to trick users into handing over access tokens that bypass MFA entirely.

The kit lowered the barrier to entry dramatically. Subscribers got AI-assisted lure generation, automated phishing infrastructure, and turnkey token harvesting — meaning a low-skill criminal could run campaigns that previously required nation-state tradecraft. We attributed multiple 2025-2026 intrusions to this exact technique family, including campaigns Microsoft has publicly tied to both financially motivated actors and state-aligned groups.

The DCU disruption will degrade EvilTokens operations in the near term, but let's be blunt: the underlying technique is not patched, and it cannot be patched, because it abuses an authentication flow working exactly as designed. Other PhaaS platforms will absorb the displaced customer base within weeks. If your defensive strategy was "wait for the takedown," you don't have a strategy.

Technical Analysis: How Device Code Social Engineering Works

The Attack Chain

The OAuth 2.0 Device Authorization Grant (RFC 8628) was designed for input-constrained devices — smart TVs, IoT hardware, CLI tools — that can't render a browser. The flow works like this:

  1. A client application requests a device code and user code from the authorization server's device authorization endpoint (for Entra ID: https://login.microsoftonline.com/{tenant}/oauth2/v2.0/devicecode).
  2. The server returns a short alphanumeric user code and a verification URL (https://microsoft.com/devicelogin).
  3. The user navigates to the URL on any device, enters the code, and authenticates — including completing MFA.
  4. The client application polls the token endpoint until the user completes authentication, then receives access and refresh tokens.

Attackers weaponize this by initiating the flow themselves and socially engineering the victim into completing step 3:

  1. Lure delivery. The victim receives an email, Teams message, SMS, or QR code — EvilTokens used AI to generate highly contextual lures — impersonating IT, HR, or a document-sharing notification. The lure instructs the user to visit microsoft.com/devicelogin (a genuine Microsoft domain, which defeats URL reputation filtering) and enter a provided code.
  2. Victim authenticates. The user enters the code, sees a legitimate Microsoft sign-in page, completes MFA if prompted, and clicks "Continue." Critically, the MFA happens on the attacker's session, not the victim's.
  3. Token harvest. The attacker's polling client receives valid access and refresh tokens for the victim's account — with whatever scopes the attacker requested (commonly Mail.Read, offline_access, Files.ReadWrite.All).
  4. Persistence and pivoting. Refresh tokens enable long-lived access independent of the user's password. Attackers register MFA methods, add devices, or consent-grant malicious OAuth apps to survive password resets.

Why This Defeats Conventional Controls

  • MFA is satisfied. The victim legitimately completes MFA during the device code flow. Your MFA coverage statistics look great while the attacker walks in.
  • The domain is trusted. microsoft.com/devicelogin passes every URL filter and user training heuristic that says "check the domain."
  • Conditional Access gaps. Many Conditional Access policies apply at the point of interactive sign-in; the device code flow's subsequent token use comes from attacker infrastructure with different IP/device characteristics that legacy policies don't constrain.
  • Token replay from anywhere. Stolen tokens are used from the attacker's infrastructure — often residential proxies or cloud VPS geolocated near the victim to defeat impossible-travel detections.

Exploitation Status

This technique has been actively exploited in the wild at scale throughout 2025 and 2026, by actors including Storm-2372 and numerous financially motivated groups, and was productized by EvilTokens and competing PhaaS kits. No CVE applies — this is abuse of a standards-compliant protocol feature. Microsoft has published updated guidance on restricting the device code flow and continues to expand Conditional Access controls for authentication flows.

Detection & Response

Device code phishing is an identity-layer attack. Your EDR will see nothing on the endpoint during token theft — the detection surface is Entra ID sign-in telemetry, audit logs, and post-compromise behavior. The single highest-fidelity signal is authentication via the device code flow from users or applications that have no legitimate reason to use it.

Sigma Rules

YAML
---
title: Entra ID Device Code Flow Authentication
description: Detects sign-ins using the OAuth 2.0 device authorization grant flow in Microsoft Entra ID. Device code authentication is rare in most organizations and is a hallmark of PhaaS kits such as EvilTokens that socially engineer users into entering attacker-generated codes at microsoft.com/devicelogin. Baseline legitimate usage (e.g., Azure CLI, PowerShell device login, Teams phones) before deploying at high severity.
logsource:
    product: azure
    service: signinlogs
detection:
    selection:
        authentication_protocol: 'deviceCode'
    filter_known_apps:
        app_display_name:
            - 'Microsoft Azure CLI'
            - 'Microsoft Azure PowerShell'
            - 'Microsoft Teams'
            - 'Microsoft Intune Company Portal'
    condition: selection and not filter_known_apps
falsepositives:
    - Legitimate device code flow usage by IoT devices, conference room equipment, or developers using CLI tools in environments without browser access
    - 'Legitimate first-time device registration'
level: high
---
title: Entra ID Suspicious OAuth Consent Grant to Unverified Application
description: Detects user or admin consent grants to OAuth applications requesting high-risk mail and file access scopes, a common persistence step following device code token theft campaigns such as EvilTokens.
logsource:
    product: azure
    service: auditlogs
detection:
    selection:
        operation_name:
            - 'Consent to application'
            - 'Add service principal'
            - 'Add delegated permission grant'
    filter_admin:
        initiated_by_user_principal_name|endswith: '@yourdomain.onmicrosoft.com'
        initiated_by_user_principal_name|contains: 'admin'
    condition: selection and not filter_admin
falsepositives:
    - Users consenting to legitimate third-party business applications (CRM, productivity tools)
    - 'Application onboarding projects'
level: medium
---
title: Impossible Travel Device Code Token Usage
description: Detects successful device code flow sign-in followed by token usage from a geographically distant or previously unseen location within a short window, consistent with PhaaS token replay from attacker infrastructure.
logsource:
    product: azure
    service: signinlogs
detection:
    selection:
        authentication_protocol: 'deviceCode'
        status_error_code: 0
    condition: selection
falsepositives:
    - VPN egress shifting apparent location
    - Users traveling internationally
level: medium

KQL Hunting (Microsoft Sentinel / Defender)

The following query correlates device code flow sign-ins with anomalous source characteristics and flags downstream token usage from a different ASN or geography than where the code was redeemed — the strongest indicator of token replay by PhaaS infrastructure.

KQL — Microsoft Sentinel / Defender
// Hunt: Device code flow authentication followed by token replay from disparate infrastructure
// Tune KnownGoodASNs and the lookback window to your environment
let KnownGoodASNs = dynamic(["Your Corporate ISP ASN", "Your VPN Egress ASN"]);
let Lookback = 14d;
let DeviceCodeSignins =
    SigninLogs
    | where TimeGenerated > ago(Lookback)
    | where AuthenticationProtocol == "deviceCode" or ClientAppUsed =~ "Device Code"
    | where ResultType == 0
    | project DeviceCodeTime = TimeGenerated, UserPrincipalName, DeviceCodeIP = IPAddress,
              DeviceCodeLocation = Location, AppDisplayName, AppId, CorrelationId, UserAgent;
DeviceCodeSignins
| join kind=inner (
    SigninLogs
    | where TimeGenerated > ago(Lookback)
    | where ResultType == 0
    | project ReplayTime = TimeGenerated, UserPrincipalName, ReplayIP = IPAddress,
              ReplayLocation = Location, ReplayApp = AppDisplayName, ResourceDisplayName
) on UserPrincipalName
| where ReplayTime > DeviceCodeTime and ReplayTime < DeviceCodeTime + 2h
| where ReplayIP != DeviceCodeIP
| extend ASNMismatch = iif(ReplayLocation != DeviceCodeLocation, "LocationMismatch", "SameLocation")
| project DeviceCodeTime, UserPrincipalName, DeviceCodeIP, DeviceCodeLocation,
          ReplayTime, ReplayIP, ReplayLocation, ReplayApp, ResourceDisplayName, AppDisplayName
| order by DeviceCodeTime desc;

// Hunt: First-time device code flow usage per user (novel protocol adoption = phishing indicator)
SigninLogs
| where TimeGenerated > ago(90d)
| where AuthenticationProtocol == "deviceCode" or ClientAppUsed =~ "Device Code"
| summarize FirstSeen = min(TimeGenerated), TotalCount = count(), IPs = make_set(IPAddress),
            Apps = make_set(AppDisplayName) by UserPrincipalName
| where FirstSeen > ago(7d)
| order by FirstSeen desc;

// Hunt: OAuth consent grants with high-risk scopes in the window after a device code sign-in
AuditLogs
| where TimeGenerated > ago(14d)
| where OperationName in ("Consent to application", "Add delegated permission grant")
| mv-expand TargetResources
| mv-expand TargetResources_mod = TargetResources.modifiedProperties
| where TargetResources_mod.displayName == "ConsentContext.IsAdminConsent" or TargetResources_mod.newValue has_any ("Mail.Read", "Files.ReadWrite", "offline_access", "full_access_as_app")
| project TimeGenerated, OperationName, InitiatedBy = tostring(InitiatedBy.user.userPrincipalName),
          AppName = tostring(TargetResources.displayName), Scopes = tostring(TargetResources_mod.newValue)
| order by TimeGenerated desc;

Velociraptor VQL Hunt

While the token theft itself happens in the cloud, the lure delivery and user interaction leave endpoint artifacts. Browser history showing visits to microsoft.com/devicelogin — especially when the user has no history of authenticating IoT devices — is a strong triage lead during scoping. This artifact hunts Chromium and Edge history databases for device login URL visits.

VQL — Velociraptor
-- Hunt for browser visits to the Microsoft device login verification page
-- Indicates a user entered a device code; correlate with Entra sign-in logs to confirm malicious flow
LET history_files = SELECT FullPath
FROM glob(globs=[
    'C:/Users/*/AppData/Local/Google/Chrome/User Data/*/History',
    'C:/Users/*/AppData/Local/Microsoft/Edge/User Data/*/History'
])
WHERE NOT IsDir;

SELECT FullPath AS HistoryDB,
       url.URL AS VisitedURL,
       url.Title AS PageTitle,
       timestamp(winfiletime=url.LastVisitTime) AS VisitTime,
       url.VisitCount AS VisitCount
FROM foreach(
    row=history_files,
    query={
        SELECT FullPath, urls.URL, urls.Title, urls.LastVisitTime, urls.VisitCount
        FROM sqlite(file=FullPath, query='SELECT url AS URL, title AS Title, last_visit_time AS LastVisitTime, visit_count AS VisitCount FROM urls')
        WHERE URL =~ 'microsoft.com/devicelogin'
    })
ORDER BY VisitTime DESC;

When you get hits, pivot immediately to the sign-in log: if the user visited devicelogin and a device code flow sign-in succeeded minutes later from an unfamiliar IP or ASN, you have a confirmed compromise and should initiate the response steps below.

Incident Response for Confirmed Device Code Compromise

Token theft requires more than a password reset. Execute these steps in order:

  1. Revoke all tokens immediately. Reset the password AND revoke all refresh tokens and sign-in sessions (RevokeSignInSessions). A password reset alone does not invalidate existing refresh tokens.
  2. Audit registered authentication methods. Attackers commonly register their own MFA methods (phone, Authenticator) post-compromise to survive resets. Remove anything not user-verified.
  3. Review OAuth consent grants. Remove suspicious delegated permission grants and service principals added after the compromise timestamp.
  4. Hunt the mailbox. Device code campaigns overwhelmingly target email: search audit logs for MailItemsAccessed, inbox rules created (New-InboxRule forwarding externally), and outbound phishing sent from the compromised account.
  5. Check for device registration. Look for attacker-registered devices in Entra ID audit logs ("Add device", "Register device").
  6. Preserve evidence. Export sign-in logs, audit logs, and unified audit log entries covering the compromise window before retention expires.

Remediation and Hardening

There is no patch — but there are highly effective controls. Prioritize in this order:

1. Block or Constrain the Device Code Flow (Highest Impact)

If your organization doesn't operate input-constrained devices, block the device code flow entirely via Conditional Access. Microsoft added an authentication flows condition to Conditional Access specifically for this threat. For organizations that legitimately need it (Azure CLI on jump boxes, Teams devices), scope the flow to named locations, compliant devices, or specific users only.

2. Deploy Phishing-Resistant MFA with Token Binding

FIDO2 security keys, Windows Hello for Business, and certificate-based authentication are bound to the origin and cannot be replayed through the device code flow from attacker infrastructure. Combined with Conditional Access token protection (which binds tokens to the device), stolen refresh tokens become useless when replayed from attacker machines. Note that token protection currently applies to Exchange Online, SharePoint Online, and Teams on Windows devices.

3. Conditional Access Policy Script

The following PowerShell creates a Conditional Access policy blocking the device code authentication flow for all users, with an exclusion group for legitimate use cases. Run with an account holding the Conditional Access Administrator role.

PowerShell
# Requires: Microsoft.Graph PowerShell SDK (Install-Module Microsoft.Graph)
# Connect with required scopes
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess","Policy.Read.All"

# 1. Create (or reference) an exclusion group for legitimate device code users
#    Populate this group ONLY with accounts/devices that require the flow (e.g., Teams phones, CLI-only build agents)
$exclusionGroupId = (Get-MgGroup -Filter "displayName eq 'CA-Exclusion-DeviceCodeFlow'").Id
if (-not $exclusionGroupId) {
    $exclusionGroupId = (New-MgGroup -DisplayName "CA-Exclusion-DeviceCodeFlow" ``
        -MailEnabled:$false -MailNickname "CAExclDeviceCode" ``
        -SecurityEnabled:$true -Description "Excluded from device code flow block - approved legitimate use cases only").Id
    Write-Host "Created exclusion group: $exclusionGroupId - populate it with approved exceptions only."
}

# 2. Build the Conditional Access policy blocking the device code authentication flow
$policy = @{
    displayName = "BLOCK - Device Code Authentication Flow (EvilTokens Mitigation)"
    state       = "enabledForReportingButNotEnforced"   # Start in report-only; flip to 'enabled' after impact review
    conditions  = @{
        users = @{
            includeUsers  = @("All")
            excludeGroups = @($exclusionGroupId)
        }
        applications = @{
            includeApplications = @("All")
        }
        clientAppTypes = @("all")
        authenticationFlows = @{
            transferMethods = @("deviceCodeFlow")
        }
    }
    grantControls = @{
        operator        = "OR"
        builtInControls = @("block")
    }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $policy
Write-Host "Policy created in REPORT-ONLY mode. Review sign-in log impact, then set state to 'enabled'."

# 3. Audit: report all device code flow sign-ins from the last 30 days to validate impact
$signins = Get-MgAuditLogSignIn -All -Filter "authenticationProtocol eq 'deviceCode'" -Top 1000
$signins | Select-Object CreatedDateTime, UserPrincipalName, AppDisplayName, IPAddress, ``
    @{N='Location';E={$_.Location.City + ', ' + $_.Location.CountryOrRegion}}, Status |
    Export-Csv -Path ".\DeviceCodeSignins_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
Write-Host "Audit exported. Any account in this CSV NOT in your exclusion group would be blocked once the policy is enforced."

# 4. Revoke sessions for any user with a suspicious device code sign-in (uncomment per-account after investigation)
# Revoke-MgUserSignInSession -UserId "user@yourdomain.com"

4. Reduce Token Lifetime and Blast Radius

  • Shorten refresh token lifetimes via Conditional Access sign-in frequency policies for sensitive roles.
  • Restrict user consent: configure Entra ID so users cannot consent to applications without admin approval (Admin consent workflow).
  • Enable Continuous Access Evaluation (CAE) so revoked or anomalous sessions are killed in near-real-time rather than at token expiry.
  • Alert on devicelogin URL visits in your web proxy/DNS logs for user populations that never legitimately authenticate devices.

5. User Awareness — Updated for This Technique

Standard phishing training ("check the URL") actively fails here because the URL is genuine Microsoft. Retrain on one simple rule: no legitimate IT process will ever ask you to enter a code someone else gives you at microsoft.com/devicelogin. Any unsolicited device code is an attack in progress — report it, don't enter it.

The Bigger Picture

The EvilTokens disruption is a meaningful win for Microsoft's DCU and its partners, and takedowns like this impose real costs on the PhaaS economy. But device code social engineering is a technique, not an infrastructure — it survived the Storm-2372 disclosures, it will survive this takedown, and successor kits are already absorbing the customer base. The defenders who win here are the ones who treat authentication flows themselves as an attack surface: inventory which flows your tenants actually use, block the rest, and bind tokens to devices wherever possible. That work is unglamorous, but it's the difference between reading about the next PhaaS disruption and being a case study in it.

Related Resources

Security Arsenal Alert Triage Automation AlertMonitor Platform Book a SOC Assessment platform Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.