Report an Incident Become a Partner Careers Contact
Book a Demo
Threat Research

Password In The Email, Code On Microsoft's Page: Hunting The SkyW4lker Device-Code Kit In Microsoft 365

Heider Albadawi · Senior SOC Analyst 5 November 2026 8 min read
Four numbered steps: an email with a password-protected Contract.pdf, a CAPTCHA box, a red code HQ7K-2PXM entered on the real Microsoft device login page, and a purple attacker server receiving access and refresh tokens, beside the headline "The code is real. The device isn't."

The email has an attachment and a password in the body. The attachment opens to a link, the link to a CAPTCHA, and the CAPTCHA to a page asking the user to enter a short code on Microsoft's own sign-in site. The URL really is Microsoft's. The sign-in really is the user's. When they finish, the attacker has tokens for their Microsoft 365 account, and no password was ever typed into a fake page.

That is SkyW4lker, a phishing kit analysed by ANY.RUN on 27 October and widely reported on 4 November. It abuses the OAuth device code flow, and its use is growing fast. This post explains how the chain works and how to hunt for it in Microsoft Defender and Sentinel.

What's been reported

  • ANY.RUN tied 618 sandbox analyses to the kit between June and 21 October 2026. Monthly analyses grew from 20 in June to 200 in September.
  • It was first seen on 23 June 2026. Researchers listed 173 domains hosting it, and 50 of 92 backend IP addresses were with a single cloud hosting provider.
  • Submissions came mostly from the United States, followed by India, Canada and the United Kingdom. Sectors named were technology, manufacturing and government.
  • ANY.RUN assesses "with high confidence" that SkyW4lker and an older credential-phishing kit, Gabagool, are built by the same developer. They share JavaScript modules, landing-URL formats and hosting, and look like two attack modes of one platform.

Sandbox analyses are submissions, not confirmed victims, so treat the figures as a measure of activity rather than of compromise.

How the chain works

1. A password-protected lure

Emails are themed as commercial offers, contracts, invoices, payment notices or confidential documents. The attachment is a PDF, Word or Excel file, with the password in the email body. Encryption stops many gateways from looking inside the file, so the link it contains isn't scanned at delivery.

2. Redirects through trusted services

Some variants route the victim through a page on a well-known collaboration, mapping or site-building service, or through cloud object storage, before reaching the kit. A reputable first hop gets past link filters.

3. A CAPTCHA gate

The kit uses a CAPTCHA, either a commercial one or its own self-hosted widget, to keep automated scanners and sandboxes from seeing the phishing page.

4. The device code

The phishing page registers a session with the kit's backend (sending the visitor's IP address and location), requests a device code from Microsoft, and shows it to the victim with instructions to enter it at Microsoft's device login page. The page then polls every few seconds until the victim completes sign-in.

Device code flow exists for devices without a keyboard, such as conference room displays. The user signs in on another device and the waiting device receives the tokens. Here, the "waiting device" is the attacker's server. The victim completes their normal sign-in, MFA included, so MFA doesn't stop it. Our explainer on device code phishing covers the mechanism in more depth.

5. Collection

The kit also logs what it can about the visitor, including email address, browser, MFA status and country, and offers an admin panel. Like Gabagool, it can also harvest typed credentials.

Hunting in Defender and Sentinel

These queries are starting points to tune for your environment. ANY.RUN gives no queries of its own, so they are built from the indicators and patterns in its report.

1. Device code sign-ins, and who normally uses them

SigninLogs
| where TimeGenerated > ago(30d)
| where AuthenticationProtocol =~ "deviceCode"
| summarize SignIns = count(), Apps = make_set(AppDisplayName, 10),
            IPs = make_set(IPAddress, 10), Countries = make_set(Location, 10),
            First = min(TimeGenerated), Last = max(TimeGenerated)
          by UserPrincipalName, ResultType
| order by Last desc

In most organisations, very few people legitimately use device code flow. Anyone outside that list, especially from a hosting provider IP, needs a look.

2. A device code sign-in shortly after a lure arrives

let Lures = EmailEvents
| where Timestamp > ago(14d)
| where DeliveryAction == "Delivered"
| where Subject has_any ("statement", "invoice", "contract", "submission", "Fedwire", "approved", "confidential")
| join kind=inner (EmailAttachmentInfo | where FileType in~ ("pdf","docx","xlsx","xls"))
    on NetworkMessageId
| project LureTime = Timestamp, UserPrincipalName = tolower(RecipientEmailAddress), Subject, FileName;
SigninLogs
| where TimeGenerated > ago(14d)
| where AuthenticationProtocol =~ "deviceCode" and ResultType == 0
| extend UserPrincipalName = tolower(UserPrincipalName)
| join kind=inner Lures on UserPrincipalName
| where TimeGenerated between (LureTime .. LureTime + 2d)
| project TimeGenerated, UserPrincipalName, IPAddress, Location, AppDisplayName, Subject, FileName, LureTime

Defender doesn't flag password protection as a field, so the subject list does the filtering. Adjust it to the lures you see.

3. Clicks to lookalike Microsoft hostnames

UrlClickEvents
| where Timestamp > ago(30d)
| extend Host = tostring(parse_url(Url).Host)
| where Host matches regex @"(?i)(docshare|sdocshares|pdocshared|pdfdocshared|efaxdoc|reauth|statement|copilot|login|auth).*(outlook|onedrive|copilot|office365)"
| where not(Host endswith "microsoft.com" or Host endswith "office.com"
            or Host endswith "live.com" or Host endswith "microsoftonline.com"
            or Host endswith "sharepoint.com")
| project Timestamp, AccountUpn, Host, Url, ActionType, IsClickedThrough

The regex is ANY.RUN's pattern for the kit's hostnames. The exclusions keep genuine Microsoft domains out. Add your own SharePoint and other tenant domains if they cause noise.

4. The kit's URL paths in web traffic

union isfuzzy=true
  (DeviceNetworkEvents | where Timestamp > ago(30d)
     | where RemoteUrl has_any ("session_public.php", "private_captcha", "confirm_visit.php", "mstoken_document_")
     | project Timestamp, Who = DeviceName, Url = RemoteUrl),
  (CommonSecurityLog | where TimeGenerated > ago(30d)
     | where RequestURL has_any ("session_public.php", "private_captcha", "confirm_visit.php", "mstoken_document_")
     | project Timestamp = TimeGenerated, Who = SourceIP, Url = RequestURL)

Encrypted traffic often hides full URLs from endpoint telemetry, so a proxy that inspects TLS gives better coverage here. Repeated action=poll requests are the kit waiting for the victim to finish signing in.

5. What happened after a suspect device code sign-in

let Suspect = SigninLogs
| where TimeGenerated > ago(14d)
| where AuthenticationProtocol =~ "deviceCode" and ResultType == 0
| project UserId, SuspectTime = TimeGenerated;
CloudAppEvents
| where Timestamp > ago(14d)
| join kind=inner Suspect on $left.AccountObjectId == $right.UserId
| where Timestamp between (SuspectTime .. SuspectTime + 3d)
| where ActionType in ("New-InboxRule", "Set-InboxRule", "MailItemsAccessed", "FileDownloaded",
                       "AnonymousLinkCreated", "Add registered owner to device", "Register device.")
| summarize Actions = count(), Kinds = make_set(ActionType) by AccountDisplayName, bin(Timestamp, 1h), IPAddress

Look for mailbox rules, bulk mail access, file downloads, sharing links, and device registration, which attackers use to turn a token into longer-lived access.

If you find one

  1. Revoke the user's sessions and refresh tokens in Entra ID. Device code flow normally issues a refresh token as well as an access token, so a password reset alone isn't enough.
  2. Check for new devices, authentication methods, app consents and inbox rules added since the sign-in, and remove them.
  3. Search for the same lure across other mailboxes and purge it.
  4. Block the kit's domains and the first-hop pages you found in mail flow and web filtering.

Prevention

  • Block device code flow with Conditional Access. Use the authentication flows condition to block it for everyone, then exclude only the accounts or devices that need it, such as meeting room systems on known networks.
  • Require a compliant or hybrid-joined device for Microsoft 365. The attacker's server isn't a managed device, so this can stop many device code sign-ins as well. Test how it behaves in your tenant before relying on it alone.
  • Turn on token protection where your apps and platforms support it, so stolen tokens are harder to replay.
  • Tell users the rule plainly: nobody legitimate will ask them to type a code into Microsoft's sign-in page because of an email.
  • Treat password-protected attachments from outside as suspicious, and make reporting them one click.

Phishing-resistant MFA is still worth having, but it doesn't help here, because the victim is signing in to the real Microsoft page on their own device. Blocking the flow does. For the wider kit economy behind SkyW4lker, see our guide to phishing-as-a-service.

How a managed SOC helps

  • Identity alerts investigated around the clock. A device code sign-in from a hosting provider at 2am needs a verdict before the morning. Our SOCs are staffed 24/7, and senior analyst sign-off is the default on the managed service.
  • Email and identity joined up. We correlate the lure in Defender for Office 365 with the sign-in in Entra ID, as the queries above do.
  • Hardening that sticks. Our identity threat detection and response service helps put Conditional Access controls like the device code block in place without locking out the systems that need it.

If you'd like to know who in your tenant has used device code flow this month, book a demo or talk to our team.

Threat ResearchSkyW4lkerDevice Code PhishingPhishing-as-a-ServiceMicrosoft 365Microsoft Entra IDConditional AccessDefender for Office 365Microsoft SentinelKQLThreat Hunting

Ready to see the agents work?

Book a demo of CYBERSHIELD AI against a real scenario.