DEBULL — Microsoft Device-Code Phishing (Storm-2372-style Tradecraft)
Executive Summary
DEBULL is a reusable phishing-as-a-service (PhaaS) tooling layer that abuses Microsoft's legitimate OAuth 2.0 Device Authorization Grant (RFC 8628, the "device code" flow) to hijack Microsoft 365 and Entra ID accounts. ZeroBEC identified and blocked a campaign running from the last week of June 2026 into early July 2026. The Hacker News reported it on 2026-07-07.
Why it defeats conventional controls: there is no fake Microsoft login page and no adversary-in-the-middle proxy to fingerprint. A collaboration-themed lure (payment / shared-folder pretext) pushes the victim into the real Microsoft device-login experience at microsoft.com/devicelogin, while a backend broker generates and polls Microsoft Authentication Broker device-code tokens. The user authenticates on genuine Microsoft infrastructure and satisfies MFA legitimately — then unknowingly authorizes the attacker's session. No password is ever stolen, so credential-theft and AitM detections do not fire.
Why the Microsoft Authentication Broker client matters: Microsoft documented Storm-2372 shifting to this specific client ID because it returns a refresh token that can be exchanged for a device-registration token, letting the actor register an attacker-controlled device in Entra ID and obtain a Primary Refresh Token (PRT). That is persistence which survives a password reset — so password-reset-only response is insufficient.
Post-exploitation: after authentication in the observed case, a device object named GraphSpy-Device appeared in the tenant. ZeroBEC assesses with high probability that DEBULL uses GraphSpy or a GraphSpy-derived workflow for Microsoft Graph / Entra post-exploitation. The attacker session was created from the DEBULL origin and then continued from a second, separate attacker egress IP — geo-plausible US datacenter space chosen to avoid tripping obvious impossible-travel logic.
Bottom line for the hunt: this is an identity-plane threat. Endpoint EDR sees only the lure fetch (DNS/network to attacker infrastructure). Everything that matters — the device-code grant, the broker sign-in, the device registration, the PRT, the mailbox and SharePoint abuse — lives in Entra ID sign-in and audit logs and M365 unified audit logs. Hunt there first.
Source Review & Web Hunter Notes
| Tier | Source | Key Finding | Carry Fwd |
|---|---|---|---|
| 1 | ZeroBEC — DEBULL: Storm-2372-Style Microsoft Device-Code Phishing With GraphSpy Post-Exploitation (2026-07-04) | Primary technical writeup. Full attack chain, broker endpoint, panel exposure via phpinfo/Composer, CloakGuard deploy module, GraphSpy-Device artifact, complete IOC list. | yes |
| 1 | Microsoft Security Blog — Storm-2372 conducts device code phishing campaign (2025-02-13, updated 2025-02-14) | Authoritative background + mitigation. Documents the shift to the Microsoft Authentication Broker client ID for refresh-token → device-registration → PRT. Source of the 50199-then-success heuristic and the CA blocking guidance. | yes |
| 1 | Cisco Talos — ARToken: Inside an EvilTokens affiliate panel targeting Microsoft 365 | Separate but behaviourally identical platform. React panel, 80+ endpoints, clientMode: "broker" for PRT acquisition, PRT lifecycle endpoints, Cloudflare Workers lure deployment, operator UUID. | partial |
| 2 | The Hacker News (2026-07-07) | Corroborates ZeroBEC findings; adds ecosystem context (EvilTokens, Tycoon, Proofpoint's May 2026 dynamic-code-generation analysis, ATO jumping). | partial |
| 2 | DIAMATIX — Microsoft Device Code Flow Abuse Creates a New Risk for M365 Accounts | MSP/MSSP-oriented restatement of the risk and defensive posture. No new atomic indicators. | no |
| 2 | Microsoft Learn — Conditional Access: block authentication flows | Vendor documentation for the CA control that blocks the device-code flow. Hardening authority. | yes |
DEBULL-DeviceCodePhishing-Hunt-sources/. Every atomic indicator in §10's import CSV traces to at least one of those snapshots. Indicators that could not be traced were removed or converted to placeholders — see §11.Analyst notes & caveats
- Attribution is deliberately loose. ZeroBEC states this is Storm-2372-style tradecraft, not Storm-2372. DEBULL appears to be a reusable tooling layer possibly operated by several operators. Do not report this to leadership as "Russian state actor" — that overstates the source.
- Turkish-language developer markers (
Code'u otomatik kopyalain the lure page,SAYAÇ (expiration)in the panel header) are assessed by the source at only low-to-medium confidence as a code-lineage clue. They are not evidence of operator nationality. - Single-vendor primary source. The DEBULL-specific infrastructure detail rests on one vendor report (ZeroBEC) plus THN's restatement of it. The technique is corroborated independently by Microsoft, Talos, Sekoia and Proofpoint. Weight the technique detections higher than the atomic indicators.
- Indicator perishability is high. The CloakGuard module lets operators publish new lures to Cloudflare Workers and custom domains on demand while the backend broker stays stable. Treat the domain/IP list as short-lived and lead with the behavioural queries (Q3–Q10).
Hunt Brief & Attack Chain
| # | Step | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 | Collaboration-themed lure email (payment / shared-folder pretext) reaches the mailbox. Inherits legitimate mail-auth signals — DKIM pass, compauth pass, no attachment. | M365 / Exchange Online message trace; UrlClickEvents | N1 — link clicks into lure paths; low-content external messages with a single link |
| 2 | Victim opens the first-stage page on a compromised legitimate website, isolated under a /Team_Meets/ path. Fake "encrypted secure message" UI, no password field. | Falcon DNS / network telemetry; proxy logs | Q1, Q2 — DNS + connections to lure infrastructure |
| 3 | Landing page calls the DEBULL broker endpoint (office_poll.php) with action: get_auth_broker_device_code, tenant_id: common. | Proxy / web logs; Falcon DNS | Q1 — broker domain resolution; proxy URI hunt for the broker script name |
| 4 | Victim is pushed to the genuine Microsoft device-login page and enters the attacker-generated code. MFA is satisfied legitimately by the real user. | Entra sign-in logs (device-code protocol) | Q4 — all device-code grants; N2 |
| 5 | Landing page polls (poll_auth_broker_token) until the token is issued. Entra shows a 50199 waiting/interrupted event followed by success — the human pause while the code is read and typed. | Entra sign-in logs | Q5 — 50199-then-success correlation (Microsoft-documented heuristic) |
| 6 | Attacker-side session created from the DEBULL origin, authenticating as Microsoft Authentication Broker. | Entra sign-in logs | Q6, Q10 — broker sign-ins; first-time-seen source IP |
| 7 | Broker refresh token exchanged for a device-registration token; attacker-controlled device registered in Entra ID → Primary Refresh Token obtained. Persistence survives password reset. | Entra audit logs (Device Registration Service) | Q7, N3 — device registration close in time to a broker sign-in |
| 8 | Session continued from a second, different attacker egress IP against OfficeHome / One Outlook Web. Geo-plausible datacenter space defeats naive impossible-travel logic. | Entra sign-in logs | Q6 — same user, broker + OWA, distinct IPs in a short window |
| 9 | Post-authentication tooling appears — a GraphSpy-Device object. Graph-driven mailbox enumeration and collection follow. | Entra audit; M365 unified audit; Graph activity logs | Q7, N4 — anomalous device display names; Graph enumeration bursts |
| 10 | Objective: BEC and data theft — mailbox rule creation for forwarding/auto-delete (evidence suppression), mail collection, SharePoint / OneDrive mass download, and ATO-jumping to new victims from the trusted account. | M365 unified audit log | Q8, Q9, N5, N6 |
Hunt hypotheses (fidelity-ordered)
| # | Hypothesis | MITRE | Conf |
|---|---|---|---|
| H1 | An endpoint resolved or connected to known DEBULL broker/lure infrastructure. | T1566.002 | HIGH |
| H2 | A user account completed an OAuth device-code grant that no business process explains. | T1528, T1621 | HIGH |
| H3 | A device-code sign-in shows the 50199 waiting/interrupted → success pattern within one correlation ID. | T1528 | HIGH |
| H4 | A Microsoft Authentication Broker sign-in is followed within minutes by OfficeHome / Outlook access from a different IP for the same user. | T1550.001 | HIGH |
| H5 | An Entra device object was registered close in time to a broker sign-in, or carries a tool-derived display name. | T1098.005 | HIGH |
| H6 | A Microsoft Authentication Broker sign-in originated from a source IP never before seen for that user. | T1550.001 | MED |
| H7 | A mailbox rule was created that forwards externally or auto-deletes, shortly after an anomalous sign-in. | T1114.003, T1564.008 | MED |
| H8 | A single principal downloaded an anomalous volume of SharePoint/OneDrive files in a short window. | T1530 | MED |
| H9 | An endpoint resolved a Cloudflare Workers subdomain matching document-lure naming, seen by very few hosts. | T1566.002, T1583.006 | MED |
Consolidated IOC Table
microsoft.com/devicelogin or login.microsoftonline.com. These are legitimate Microsoft endpoints and are a required part of the flow — the abuse is that the real page is used. Blocking them breaks genuine authentication and does not stop the attack. Control the device-code flow with Conditional Access (§12), not with URL blocking.| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| domain | frenksv[.]sbs | HIGH | detect / block | DEBULL device-code broker, Cloudflare-fronted campaign domain. Broker path office_poll.php. |
| domain | debull[.]app | HIGH | detect / block | Canonical DEBULL backend vhost (recovered from the phpinfo Hostname:Port leak). Called directly by the Workers.dev lure. |
| domain | page-8-xls-vft-lvfsa.pefferarley83249[.]workers[.]dev | HIGH | detect / block | Workers.dev Box/Excel-themed lure calling the same DEBULL broker. Demonstrates template reuse. |
| domain | trogir-rental[.]com | MED | hunt only | Compromised legitimate business site (Croatian rental company, years of indexed content). Malicious content isolated under /Team_Meets/. Do not block the apex — hunt the path. |
| domain | vps3459922.trouble-free[.]net | MED | hunt only | VPS provider hostname of the DEBULL host. Shared hosting — blocking risks collateral. |
| ipv4 | 162.35.167[.]138 | HIGH | detect / block | DEBULL panel origin and the Microsoft Authentication Broker session source seen in Entra telemetry. The strongest single pivot in the report. |
| ipv4 | 96.126.176[.]130 | HIGH | detect / block | Attacker session continuation egress (OfficeHome / One Outlook Web). |
| ipv4 | 49.12.61[.]13 | MED | hunt only | First-stage compromised web host serving the lure. Shared/compromised infrastructure. |
| device name | GraphSpy-Device | HIGH | hunt / alert | Post-authentication device object observed in the tenant. Query Entra device inventory and audit logs for this and similar tool-derived names. |
| uri fingerprint | office_poll.php | HIGH | hunt | DEBULL broker script. Hunt in proxy/web-gateway URI logs regardless of hosting domain — this survives domain rotation. |
| uri fingerprint | deploy.php / deploy_ajax.php | MED | hunt | CloakGuard deployment module and its AJAX API. |
| panel string | DEBULL Secure Mail System / DEBULL Admin Panel / Deploy Pages - CloakGuard | HIGH | hunt | Panel titles for external-attack-surface and Shodan-style pivots. |
| sha256 | B96DE9AB…94B305 | MED | hunt | DEBULL admin.css static fingerprint. Web-asset hash — not a Falcon-importable binary hash. See §10 note. |
| token | cec0d6e71b404597a8e486238f0cc69a | MED | hunt | Cloudflare Web Analytics token embedded in the DEBULL panel — pivot for finding sibling infrastructure. |
| token | c7173d6a700b02b111e51b703acd8c8e | MED | hunt | Composer content-hash of the DEBULL application. |
| domain | dashboard-bl.pamconj[.]com | MED | detect | ARToken operator panel (Talos) — adjacent EvilTokens-linked platform, not DEBULL. Included because the behaviour is identical. |
| uuid | 84eb384d-cd3e-4c90-a283-c960ce557913 | MED | hunt | ARToken hard-coded operator UUID in the phishing kit. Adjacent platform. |
1bc1716a…46e15 appears in the DEBULL Composer metadata but is the legitimate upstream git ref of an open-source library used by millions of applications. It is not an indicator of compromise and must never be blocked. Likewise the Apache/PHP/OpenSSH version strings are environment facts, not IOCs.Affected Surface & Telemetry Matrix
| Surface | Required telemetry | Priority | Gap risk if missing |
|---|---|---|---|
| Entra ID sign-in logs (interactive + non-interactive) | Entra diagnostic settings → Falcon Next-Gen SIEM connector, or Sentinel SigninLogs | CRITICAL | Total blindness. The device-code grant, the broker sign-in, and the session handoff are only visible here. Without this the hunt cannot run. |
| Entra ID audit logs | Entra diagnostic settings → NGSIEM / Sentinel AuditLogs | CRITICAL | Device registration and PRT-enabling persistence go unseen; you would remediate the token and leave the attacker's device in place. |
| M365 unified audit log (Exchange + SharePoint) | UAL enabled with mailbox auditing; retention ≥ 1 year | HIGH | BEC objective activity — inbox rules, mail access, mass download — invisible. |
| Falcon DNS + network telemetry (managed endpoints) | Falcon sensor, DnsRequest / NetworkConnectIP4 | MED | Loses the lure-fetch pivot. Note this only covers managed endpoints — the victim may click on an unmanaged or personal device. |
| Web proxy / secure web gateway URI logs | Full-URI logging forwarded to NGSIEM | MED | Loses the domain-rotation-resistant office_poll.php path fingerprint. |
| Email gateway / message trace | Message trace + URL click telemetry | MED | Loses the delivery-side pivot and the ability to scope who else received the lure. |
| Falcon Identity Protection | Identity Protection sensors on domain controllers | LOW | Limited relevance — this attack is cloud-native and does not touch on-prem AD authentication. Useful only for follow-on hybrid lateral movement. |
ATT&CK Mapping
| Tactic | Technique | Name | Observed behaviour |
|---|---|---|---|
| Resource Development | T1583.006 | Acquire Infrastructure: Web Services | Lures published to Cloudflare Workers via the CloakGuard deploy module; Cloudflare-fronted campaign domains. |
| Resource Development | T1584.004 | Compromise Infrastructure: Server | First-stage lure hosted on a compromised legitimate business website under an isolated path. |
| Initial Access | T1566.002 | Phishing: Spearphishing Link | Collaboration / payment / shared-folder themed message with a single link and no attachment. |
| Credential Access | T1528 | Steal Application Access Token | Backend broker generates and polls a device code; victim's completion yields access + refresh tokens to the attacker. |
| Credential Access | T1621 | Multi-Factor Authentication Request Generation | The victim satisfies MFA legitimately on real Microsoft infrastructure, authorizing the attacker's session. |
| Defense Evasion | T1550.001 | Use Alternate Authentication Material: Application Access Token | Attacker replays the issued token from separate infrastructure; no password and no MFA prompt required. |
| Persistence | T1098.005 | Account Manipulation: Device Registration | Broker refresh token exchanged for device-registration token; attacker device registered in Entra ID to obtain a PRT. |
| Persistence | T1556.009 | Modify Authentication Process: Conditional Access Policies | PRT-backed persistence explicitly designed to survive password reset ("Persists across password changes" per the adjacent ARToken panel UI). |
| Discovery | T1087.003 | Account Discovery: Cloud Account | Microsoft Graph enumeration via GraphSpy or GraphSpy-derived tooling after token acquisition. |
| Collection | T1114.002 | Email Collection: Remote Email Collection | Mailbox access and mail harvesting through Graph / Outlook. |
| Collection | T1530 | Data from Cloud Storage | SharePoint / OneDrive access and bulk download. |
| Persistence | T1114.003 | Email Collection: Email Forwarding Rule | Inbox rule creation for forwarding and auto-deletion. |
| Defense Evasion | T1564.008 | Hide Artifacts: Email Hiding Rules | Auto-delete rules used to suppress evidence of BEC replies. |
| Lateral Movement | T1534 | Internal Spearphishing | ATO jumping — the compromised trusted account sends the next round of device-code lures internally and to partners. |
Native Audit-Log Hunts (Entra ID / M365 — KQL starters)
Run these in Microsoft Sentinel or Defender Advanced Hunting. They are the authoritative view of the device-code flow and should be run first, before the CQL in §8 — if your Entra logs are not yet in Falcon NGSIEM, these are your entire hunt.
N1 · Device-code URL clicks (Microsoft-published)
Microsoft's own detection query for possible device-code phishing: correlate clicks on the device-login URLs with a risky sign-in in a narrow window, then confirm the 50199-then-success pattern.
let suspiciousUserClicks = materialize(UrlClickEvents
| where ActionType in ("ClickAllowed", "UrlScanInProgress", "UrlErrorPage") or IsClickedThrough != "0"
| where UrlChain has_any ("microsoft.com/devicelogin", "login.microsoftonline.com/common/oauth2/deviceauth")
| extend AccountUpn = tolower(AccountUpn)
| project ClickTime = Timestamp, ActionType, UrlChain, NetworkMessageId, Url, AccountUpn);
let interestedUsersUpn = suspiciousUserClicks | where isnotempty(AccountUpn) | distinct AccountUpn;
let suspiciousSignIns = materialize(AADSignInEventsBeta
| where ErrorCode == 0
| where AccountUpn in~ (interestedUsersUpn)
| where RiskLevelDuringSignIn in (10, 50, 100)
| extend AccountUpn = tolower(AccountUpn)
| join kind=inner suspiciousUserClicks on AccountUpn
| where (Timestamp - ClickTime) between (-2min .. 7min)
| project Timestamp, ReportId, ClickTime, AccountUpn, RiskLevelDuringSignIn, SessionId, IPAddress, Url);
let interestedSessionUsers = suspiciousSignIns | where isnotempty(AccountUpn) | distinct AccountUpn;
let shortIntervalSignInAttemptUsers = materialize(AADSignInEventsBeta
| where AccountUpn in~ (interestedSessionUsers)
| where ErrorCode in (0, 50199)
| summarize ErrorCodes = make_set(ErrorCode) by AccountUpn, CorrelationId, SessionId
| where ErrorCodes has_all (0, 50199)
| distinct AccountUpn);
suspiciousSignIns
| where AccountUpn in (shortIntervalSignInAttemptUsers)
N2 · Broker sign-in followed by OWA from a different IP
The core DEBULL session-handoff signature: a Microsoft Authentication Broker sign-in, then OfficeHome / One Outlook Web for the same user from a different IP inside 15 minutes.
let window = 15m;
let mab = SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName =~ "Microsoft Authentication Broker"
| project MabTime=TimeGenerated, UserPrincipalName, MabIp=IPAddress,
MabLocation=Location, MabResult=ResultType, MabUserAgent=UserAgent;
let owa = SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName in ("OfficeHome", "One Outlook Web")
| where ResultType == 0
| project OwaTime=TimeGenerated, UserPrincipalName, OwaIp=IPAddress,
OwaLocation=Location, OwaApp=AppDisplayName, OwaUserAgent=UserAgent;
mab
| join kind=inner owa on UserPrincipalName
| where OwaTime between (MabTime .. MabTime + window)
| where MabIp != OwaIp
| project MabTime, OwaTime, UserPrincipalName, MabIp, OwaIp, MabLocation, OwaLocation,
MabResult, OwaApp, MabUserAgent, OwaUserAgent
| order by MabTime desc
N3 · Device registration artifacts (incl. tool-derived names)
AuditLogs
| where TimeGenerated > ago(30d)
| where TargetResources has_any ("GraphSpy-Device", "GraphSpy")
or OperationName has_any ("Register device", "Add device", "Add registered owner to device")
| project TimeGenerated, OperationName, Result, InitiatedBy, TargetResources
| order by TimeGenerated desc
N4 · Newly registered devices via Device Registration Service
CloudAppEvents | where AccountDisplayName == "Device Registration Service" | extend DeviceName = tostring(parse_json(tostring(RawEventData.ModifiedProperties))[1].NewValue) | extend UserPrincipalName = tostring(RawEventData.ObjectId) | project TimeGenerated, DeviceName, UserPrincipalName
N5 · Manual checklist — run these against the tenant
- Enumerate all Entra devices registered in the campaign window; validate each against your asset inventory. Anything unrecognised is an incident, not a finding.
- Review authentication-method changes: new FIDO2 keys, passkeys, Windows Hello for Business registrations, phone/authenticator additions.
- Review OAuth consent grants and service principals created or modified in the window.
- Review inbox rules across affected mailboxes — especially forwarding to external addresses and auto-delete rules.
- Review mailbox delegation, Send-As / Send-on-Behalf, and mail-forwarding settings.
- Scope the lure: search message trace for the lure themes and pull the full recipient list — device-code campaigns are broad, and ATO jumping means the next wave may come from a trusted internal or partner account.
CrowdStrike LogScale CQL Hunt Queries
appDisplayName, resultType, userPrincipalName, ipAddress, operationName, …). In most tenants these arrive parser-prefixed — for example azure.signinlogs.properties.appDisplayName — depending on your connector and parser. Each affected query is marked ⚠ validate in tenant. Run it once with a 1-hour window and head(10) to confirm the field shape before you rely on the results or promote anything to a scheduled search.Looks for: any managed endpoint resolving DEBULL broker, panel, or lure hostnames. Triage: a hit on frenksv.sbs, debull.app, or the workers.dev lure is high-fidelity. A hit on trogir-rental.com alone is weaker — that is a compromised legitimate business site and a user may have visited it innocently; confirm the /Team_Meets/ path in proxy logs.
// HUNT: DNS resolution of DEBULL broker / panel / lure infrastructure // MITRE: T1566.002, T1584.004 | CONF: high FP: low COST: low // REQUIRES: Falcon DNS telemetry (DnsRequest) on managed endpoints // FALSE POSITIVES: trogir-rental.com is a COMPROMISED LEGITIMATE site - a lookup is not // proof of phishing on its own; confirm the /Team_Meets/ path in proxy logs before escalating // TUNING: split the compromised-site domain into its own lower-severity hunt if it is noisy #event_simpleName=DnsRequest | DomainName=/^(frenksv\.sbs|debull\.app|page-8-xls-vft-lvfsa\.pefferarley83249\.workers\.dev|trogir-rental\.com|vps3459922\.trouble-free\.net)$/i | table([@timestamp, aid, ComputerName, UserName, DomainName, ContextBaseFileName], limit=200) | sort(@timestamp, order=desc)
Looks for: direct connections to the DEBULL panel origin and the attacker session-continuation egress. Note: 162.35.167.138 is the highest-value pivot in the whole report — it served the DEBULL panel and appeared in Entra as the Microsoft Authentication Broker session source. Any endpoint contact warrants immediate investigation.
// HUNT: endpoint connections to DEBULL origin / attacker egress infrastructure // MITRE: T1566.002, T1550.001 | CONF: high FP: low COST: low // REQUIRES: Falcon network telemetry (NetworkConnectIP4 / NetworkConnectIP6) // FALSE POSITIVES: minimal - attacker-controlled hosts. 49.12.61.13 is a compromised // shared web host, so treat that hit as hunt-grade rather than confirmed-malicious #event_simpleName=/NetworkConnectIP4|NetworkConnectIP6/ | in(RemoteAddressIP4, values=["162.35.167.138", "96.126.176.130", "49.12.61.13"]) | table([@timestamp, aid, ComputerName, UserName, ContextBaseFileName, LocalAddressIP4, RemoteAddressIP4, RemotePort], limit=200) | sort(@timestamp, order=desc)
Looks for: low-prevalence workers.dev subdomains whose names match document/collaboration lure themes. This is the domain-rotation-resistant version of Q1 — both DEBULL (CloakGuard) and the adjacent ARToken platform publish lures to Cloudflare Workers with themed subdomains (docviewer, onedrive, adobe2, Box/Excel). FP: Cloudflare Workers is heavily used legitimately; the Hosts ceiling is what makes this tractable.
// HUNT: rare workers.dev subdomains matching document/collaboration lure themes // MITRE: T1566.002, T1583.006 | CONF: medium FP: medium COST: medium // REQUIRES: Falcon DNS telemetry; 7-day window for the prevalence baseline // FALSE POSITIVES: legitimate Cloudflare Workers apps, internal dev/test deployments, // SaaS vendors that host on workers.dev // TUNING: allowlist your own and known-vendor workers.dev subdomains; raise the Hosts // ceiling in large estates; lower it to 2 for a high-precision first pass // LOOKBACK: 7d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). #event_simpleName=DnsRequest | DomainName=/\.workers\.dev$/i | DomainName=/(docviewer|onedrive|adobe|xls|excel|sheet|box|secure|doc|invoice|payment|team)/i | groupBy([DomainName], function=[count(as=Lookups), count(aid, distinct=true, as=Hosts)], limit=20000) | Hosts <= 5 | sort(Lookups, order=desc)
Looks for: every authentication that used the device-code protocol. This is the single highest-value query in the pack. In most enterprises the legitimate device-code population is small, static, and explainable — conference-room devices, a handful of CLI/automation workflows. Baseline it once, then every new user account in this result set is a candidate compromise. FP: az login --use-device-code, Connect-MgGraph --UseDeviceCode, smart TVs, and kiosk/signage devices.
// HUNT: all OAuth device-code grant authentications in Entra sign-in logs // MITRE: T1528, T1621, T1566.002 | CONF: high FP: medium COST: low // REQUIRES: Entra ID sign-in logs ingested into Falcon Next-Gen SIEM // FALSE POSITIVES: legitimate device-code use - az login --use-device-code, // Connect-MgGraph -UseDeviceCode, smart TVs, conference-room and signage devices // TUNING: baseline 30d, then exclude approved service accounts and known kiosk device IDs; // alert only on human user accounts, and treat any first-ever device-code use as high // ⚠ validate in tenant: Entra fields are parser-prefixed in many tenants, e.g. // azure.signinlogs.properties.appDisplayName - confirm shape with head(10) first // LOOKBACK: 14d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). | authenticationProtocol=/deviceCode/i | table([@timestamp, userPrincipalName, appDisplayName, appId, ipAddress, location, resultType, correlationId, userAgent], limit=200) | sort(@timestamp, order=desc)
Looks for: the Microsoft-documented device-code phishing fingerprint — an error 50199 (waiting / interrupted) event followed by a success under the same correlation ID. That pause is the human being reading the code out of the phishing page and typing it into the real Microsoft prompt. ZeroBEC observed exactly this pattern on the attacker-side broker session.
// HUNT: 50199 waiting/interrupted followed by success in one correlation ID // MITRE: T1528, T1621 | CONF: high FP: low COST: medium // REQUIRES: Entra ID sign-in logs in Falcon Next-Gen SIEM (incl. failure events) // FALSE POSITIVES: a genuine user who paused mid-authentication on a real device-code // flow; correlate with Q4 and confirm the app and source IP are expected // TUNING: join to Q4 output and keep only correlation IDs whose app is unexpected // ⚠ validate in tenant: confirm resultType is ingested as a string, not an integer; // if numeric, drop the quotes in the values list below // LOOKBACK: 14d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). | in(resultType, values=["0", "50199"]) | groupBy([userPrincipalName, correlationId, appDisplayName], function=[count(resultType, distinct=true, as=DistinctResults), count(as=Events), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen)], limit=200000) | DistinctResults >= 2 | sort(LastSeen, order=desc)
Looks for: the DEBULL session-handoff signature — the same user showing a Microsoft Authentication Broker sign-in and OfficeHome / One Outlook Web access from two or more distinct IPs. In the observed campaign the broker session came from the DEBULL origin and the mailbox access from a separate attacker egress. Why this beats impossible travel: the operator deliberately chose geo-plausible US datacenter egress, so distance-based logic stays silent — but the IP split across apps still shows.
// HUNT: Microsoft Authentication Broker + OfficeHome/Outlook from distinct IPs // MITRE: T1550.001, T1528 | CONF: high FP: medium COST: medium // REQUIRES: Entra ID sign-in logs in Falcon Next-Gen SIEM // FALSE POSITIVES: legitimate multi-device users, VPN/split-tunnel egress changes, // mobile carrier IP rotation, corporate proxy pools // TUNING: add your egress ranges to an allowlist and compare ASN rather than raw IP; // tighten by requiring FirstSeen and LastSeen within 15 minutes // ⚠ validate in tenant: confirm appDisplayName strings match your tenant exactly // LOOKBACK: 14d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). | appDisplayName=/^(Microsoft Authentication Broker|OfficeHome|One Outlook Web)$/i | resultType="0" | groupBy([userPrincipalName], function=[count(ipAddress, distinct=true, as=DistinctIps), count(appDisplayName, distinct=true, as=DistinctApps), collect([appDisplayName]), collect([ipAddress]), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen)], limit=200000) | DistinctApps >= 2 | DistinctIps >= 2 | sort(LastSeen, order=desc)
Looks for: device-registration operations in the Entra audit log — the step that converts a stolen refresh token into PRT-backed persistence that survives a password reset. Also matches tool-derived device display names such as GraphSpy-Device. This is the query that decides whether your remediation actually worked — if you revoked tokens but left a registered device, the attacker is still in.
// HUNT: Entra device registration + tool-derived device display names // MITRE: T1098.005, T1556.009 | CONF: high FP: medium COST: low // REQUIRES: Entra ID audit logs ingested into Falcon Next-Gen SIEM // FALSE POSITIVES: legitimate Autopilot / Intune enrolment and BYOD registration - // expect steady benign volume; the signal is the correlation with a device-code // sign-in (Q4/Q5) within minutes, or a device name absent from asset inventory // TUNING: exclude your enrolment service principals and known provisioning workflows; // join to Q4 output on userPrincipalName and keep registrations within 30 minutes // ⚠ validate in tenant: target device fields vary by connector - confirm which field // carries the device display name before relying on the name regex // LOOKBACK: 30d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). | operationName=/(Register device|Add device|Add registered owner to device|Add registered users to device)/i | table([@timestamp, operationName, result, initiatedBy, targetDeviceDisplayName, targetDeviceId, ipAddress, userPrincipalName], limit=200) | sort(@timestamp, order=desc)
Looks for: mailbox rule creation and modification in the M365 unified audit log. Both DEBULL's GraphSpy-derived workflow and the adjacent ARToken panel's BEC tooling create forwarding and auto-delete rules — the latter specifically to hide the attacker's replies from the real mailbox owner. Triage priority: any rule that deletes, or forwards to an external domain, created within hours of an anomalous sign-in.
// HUNT: inbox / transport rule creation and modification (BEC persistence) // MITRE: T1114.003, T1564.008 | CONF: medium FP: medium COST: low // REQUIRES: M365 unified audit log (Exchange) in Falcon Next-Gen SIEM; mailbox auditing on // FALSE POSITIVES: users legitimately create inbox rules constantly - volume is high // TUNING: keep only rules whose parameters contain ForwardTo / RedirectTo / DeleteMessage, // or that were created within 24h of a Q4/Q5/Q6 hit for the same principal // ⚠ validate in tenant: the rule-parameter field name varies by connector // LOOKBACK: 14d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). | operationName=/^(New-InboxRule|Set-InboxRule|UpdateInboxRules|New-TransportRule|Set-TransportRule|Set-Mailbox)$/i | table([@timestamp, userPrincipalName, operationName, clientIP, resultStatus, parameters], limit=200) | sort(@timestamp, order=desc)
Looks for: a single principal downloading an anomalous volume of files from SharePoint/OneDrive inside a one-hour bucket. SharePoint exfiltration is an explicit capability of the adjacent ARToken panel and a natural objective once Graph access is established. Tune the threshold to your estate — 200 files/hour is a starting point, not a universal value.
// HUNT: SharePoint / OneDrive mass download by a single principal // MITRE: T1530 | CONF: medium FP: medium COST: medium // REQUIRES: M365 unified audit log (SharePoint) in Falcon Next-Gen SIEM // FALSE POSITIVES: OneDrive sync clients on new devices, legitimate bulk migration, // eDiscovery exports, backup/DLP tooling, a user setting up a replacement laptop // TUNING: exclude sync/backup service accounts; raise or lower the Downloads floor to // match your baseline; prioritise principals that also appear in Q4/Q6 // ⚠ validate in tenant: confirm the client-IP and object-id field names for your connector // LOOKBACK: 14d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). | operationName=/^(FileDownloaded|FileSyncDownloadedFull)$/i | Bucket1h := @timestamp - (@timestamp % 3600000) | groupBy([userPrincipalName, clientIP, Bucket1h], function=[count(as=Downloads), count(objectId, distinct=true, as=DistinctFiles)], limit=200000) | Downloads >= 200 | sort(Downloads, order=desc)
Looks for: Microsoft Authentication Broker sign-ins from a source IP that is new for that user — first observed inside the last 7 days against a 30-day baseline. This is the ZeroBEC recommendation to detect geo-plausible datacenter access rather than only impossible travel: the DEBULL operator used New York / New Jersey egress specifically so the geography would look unremarkable. Enrich results with ASN and prioritise hosting/VPS providers.
// HUNT: first-time-seen source IP for Microsoft Authentication Broker sign-ins // MITRE: T1550.001, T1078.004 | CONF: medium FP: medium COST: medium // REQUIRES: Entra ID sign-in logs in Falcon Next-Gen SIEM; 30d retention for the baseline // FALSE POSITIVES: travel, new home/ISP addresses, VPN changes, carrier IP rotation, // and genuinely new device enrolments // TUNING: enrich ipAddress with ASN and keep only hosting/VPS/datacenter ASNs - that is // what separates this from ordinary user mobility; allowlist corporate egress ranges // ⚠ validate in tenant: confirm the broker app display name string matches exactly // LOOKBACK: 30d. Set the search window in Falcon; no in-query time filter (an expression on the right of a comparison is not valid in CQL filter context). | appDisplayName=/Microsoft Authentication Broker/i | resultType="0" | groupBy([userPrincipalName, ipAddress], function=[count(as=Events), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen)], limit=200000) | test(FirstSeen > now() - 604800000) | sort(FirstSeen, order=desc)
CrowdStrike Custom IOA Recommendations
What to build instead
| Control | Build | Priority |
|---|---|---|
| Falcon IOC Management | Import the §10 CSV — domain and IP indicators with the stated detect/hunt actions. This is the only part of this threat that fits the classic IOC model, and it is the most perishable part. | MED |
NGSIEM Scheduled Search — DETECT — Device-Code Grant by User Account | Q4, restricted to human user accounts after a 30-day baseline excludes approved kiosk/CLI use. Severity High. This is your primary alert. | CRITICAL |
NGSIEM Scheduled Search — DETECT — Device-Code 50199 Then Success | Q5. Severity High. Microsoft-documented signature, low FP. | HIGH |
NGSIEM Scheduled Search — DETECT — Broker Session Handoff (Split IP) | Q6 with a 15-minute constraint. Severity High. Catches the handoff that impossible-travel logic misses. | HIGH |
NGSIEM Scheduled Search — DETECT — Device Registration After Device-Code Sign-In | Q7 joined to Q4 on principal within 30 minutes. Severity Critical — this is PRT persistence being established. | CRITICAL |
| Entra ID Protection | Enable and enforce sign-in risk and user risk policies; enable Continuous Access Evaluation so token revocation takes effect in near-real-time rather than at token expiry. | CRITICAL |
Alert package — primary detection
SCHEDULED SEARCH: DETECT - Device-Code Grant by User Account (DEBULL / Storm-2372-style)
DESCRIPTION: Fires when a human user account completes an OAuth 2.0 device-code
authorization grant outside the approved baseline. Device-code phishing
bypasses MFA without stealing a password and yields attacker-controlled
session tokens.
SEVERITY: High
EMAIL SUBJECT: [HIGH] Detection: Device-Code Grant - possible M365 account takeover
BODY:
WHAT FIRED
User {userPrincipalName} completed an OAuth device-code authentication from
{ipAddress} ({location}) using app {appDisplayName} at {timestamp}.
WHY IT MATTERS
The device-code flow is designed for input-constrained devices. When a user
completes one on a normal workstation it usually means they were socially
engineered into entering an attacker-generated code on the genuine Microsoft
sign-in page. The attacker - not the user - receives the resulting tokens.
MFA was satisfied legitimately and provides no protection here.
IMMEDIATE ACTIONS
1. Contact the user out of band. Ask whether they entered a code from an email
or a document link. Do not send that question by email to the account itself.
2. If unexplained: revoke sessions and refresh tokens (revokeSignInSessions)
AND reset the password. Neither alone is sufficient.
3. Enumerate Entra devices registered for this user in the last 30 days and
remove any not in asset inventory - a registered device means PRT
persistence that survives the password reset.
4. Review inbox rules, forwarding, delegation, and authentication methods.
5. Check SharePoint/OneDrive download volume for this principal.
ESCALATE IF
A device was registered close in time, a PRT was issued, an inbox rule was
created, or mass download is observed - treat as a confirmed account takeover
and open an incident.
L1 triage checklist
- Confirm the sign-in really used the device-code protocol (re-run Q4 scoped to the principal).
- Check whether the account or device is on the approved device-code baseline — if yes, close as expected.
- Contact the user out of band (phone/Teams call, not email to the affected mailbox).
- Run Q5 for the correlation ID — does the 50199-then-success pattern appear?
- Run Q6 and Q10 — is there an IP split across apps, or a first-time-seen source IP?
- Run Q7 — was a device registered? This is the escalation trigger.
- Run Q8 and Q9 — inbox rules or mass download for this principal?
- Run Q1/Q2 scoped to the user's endpoints — did the lure fetch come from a managed device, and what else did that host touch?
- Scope the campaign: message-trace the lure theme to find every other recipient.
Machine-Readable IOC Appendix
DEBULL-DeviceCodePhishing-Hunt-sources/. Nothing here is inferred or reconstructed. Where an indicator is known to exist but its value was not published, it ships as a labelled REPLACE_WITH_ placeholder rather than a guess.type,value,action,severity,expiration,description,tags domain,frenksv.sbs,detect,critical,2026-10-19,DEBULL device-code broker domain (Cloudflare-fronted),campaign:DEBULL domain,debull.app,detect,critical,2026-10-19,DEBULL canonical backend vhost,campaign:DEBULL domain,page-8-xls-vft-lvfsa.pefferarley83249.workers.dev,detect,high,2026-10-19,Workers.dev Box/Excel lure calling DEBULL broker,campaign:DEBULL domain,trogir-rental.com,hunt,medium,2026-10-19,COMPROMISED LEGITIMATE SITE - first-stage lure under /Team_Meets/ - hunt only do not block apex,campaign:DEBULL domain,vps3459922.trouble-free.net,hunt,low,2026-10-19,DEBULL VPS provider hostname - shared hosting - hunt only,campaign:DEBULL ipv4,162.35.167.138,detect,critical,2026-10-19,DEBULL panel origin and Microsoft Authentication Broker session source,campaign:DEBULL ipv4,96.126.176.130,detect,high,2026-10-19,Attacker session continuation egress (OfficeHome/One Outlook Web),campaign:DEBULL ipv4,49.12.61.13,hunt,medium,2026-10-19,Compromised first-stage web host - shared infrastructure - hunt only,campaign:DEBULL domain,dashboard-bl.pamconj.com,detect,high,2026-10-19,ARToken PhaaS operator panel - EvilTokens-linked ADJACENT platform not DEBULL,campaign:ARToken domain,REPLACE_WITH_NEW_DEBULL_BROKER_DOMAIN,detect,high,2026-10-19,CloakGuard publishes new lure domains on demand - add newly observed broker hosts here,campaign:DEBULL # # NON-IMPORTABLE PIVOTS (web-side fingerprints - not Falcon binary hashes): # DEBULL admin.css SHA256: # B96DE9AB78411A112BDCC308163BCD7F88C215FF57BCB58282345C316794B305 # DEBULL Cloudflare Web Analytics token: cec0d6e71b404597a8e486238f0cc69a # DEBULL Composer content-hash: c7173d6a700b02b111e51b703acd8c8e # ARToken hard-coded operator UUID (adjacent platform): # 84eb384d-cd3e-4c90-a283-c960ce557913 # # DELIBERATELY NOT AN IOC: # microsoft.com/devicelogin and login.microsoftonline.com are LEGITIMATE Microsoft # endpoints required by the flow. Never block them. Control the flow with # Conditional Access instead (see section 12). # PHPMailer git ref 1bc1716a507a65e039d4ac9d9adebbbd0d346e15 is a benign # open-source library reference found in DEBULL's Composer metadata - not an IOC.
# Run in Sentinel / Defender Advanced Hunting / Falcon NGSIEM N1 All device-code protocol authentications in the last 30 days - baseline then alert N2 Microsoft Authentication Broker sign-ins - source IP, ASN, user agent N3 Entra device registrations - validate EVERY device against asset inventory N4 Device display names matching tool artifacts (GraphSpy-Device or similar) N5 Authentication method changes - FIDO2, passkeys, Windows Hello for Business N6 OAuth consent grants and new/modified service principals N7 Inbox rules - external forwarding and auto-delete N8 Mailbox delegation, Send-As, Send-on-Behalf, forwarding settings N9 SharePoint/OneDrive download volume per principal per hour N10 Message-trace the lure theme to scope every recipient (ATO jumping) # Verify Entra sign-in AND audit logs are ingested, UAL + mailbox auditing on, # retention >= 1 year, and Continuous Access Evaluation enabled
# These survive infrastructure rotation - prefer them over the domain/IP list.
B1 Device-code grant completed by a human user account outside the approved baseline
B2 Entra error 50199 (waiting/interrupted) followed by success in one correlation ID
B3 Microsoft Authentication Broker sign-in, then OfficeHome/One Outlook Web for the
same user from a DIFFERENT IP within 15 minutes
B4 Entra device registration within 30 minutes of a device-code sign-in
B5 Broker sign-in from a hosting/VPS/datacenter ASN that is new for that user
(geo-plausible datacenter access - NOT impossible travel)
B6 Inbox rule with ForwardTo/RedirectTo/DeleteMessage created within 24h of B1-B3
B7 Graph enumeration burst immediately after a device-code token issuance
B8 Low-prevalence workers.dev subdomain with a document/collaboration lure theme
B9 Web-gateway URI containing office_poll.php, deploy.php, or deploy_ajax.php
regardless of hosting domain
B10 Panel title strings: "DEBULL - Login", "DEBULL Secure Mail System",
"DEBULL Admin Panel", "Deploy Pages - CloakGuard", "ARToken Panel"
{
"pack": "DEBULL-DeviceCodePhishing-Hunt",
"version": "0.1",
"generated": "2026-07-19",
"threat": "DEBULL device-code phishing (Storm-2372-style tradecraft)",
"attack_class": "identity / PhaaS / account takeover",
"attribution": "unattributed tooling layer - NOT confirmed Storm-2372",
"adjacent_platforms": ["ARToken", "EvilTokens", "Tycoon"],
"post_exploitation": "GraphSpy or GraphSpy-derived workflow",
"indicators": {
"domains_block": ["frenksv.sbs", "debull.app",
"page-8-xls-vft-lvfsa.pefferarley83249.workers.dev"],
"domains_hunt_only": ["trogir-rental.com", "vps3459922.trouble-free.net"],
"ipv4_block": ["162.35.167.138", "96.126.176.130"],
"ipv4_hunt_only": ["49.12.61.13"],
"artoken_adjacent": {
"domain": "dashboard-bl.pamconj.com",
"operator_uuid": "84eb384d-cd3e-4c90-a283-c960ce557913"
},
"web_fingerprints": {
"admin_css_sha256":
"B96DE9AB78411A112BDCC308163BCD7F88C215FF57BCB58282345C316794B305",
"cloudflare_analytics_token": "cec0d6e71b404597a8e486238f0cc69a",
"composer_content_hash": "c7173d6a700b02b111e51b703acd8c8e"
},
"uri_fingerprints": ["office_poll.php", "deploy.php", "deploy_ajax.php"],
"device_artifact": "GraphSpy-Device",
"never_block": ["microsoft.com/devicelogin", "login.microsoftonline.com"]
},
"mitre": ["T1566.002", "T1528", "T1621", "T1550.001", "T1098.005",
"T1556.009", "T1114.002", "T1114.003", "T1564.008",
"T1530", "T1087.003", "T1534", "T1583.006", "T1584.004"]
}
Detection Validation Gates
Gate 1 — Telemetry is actually present
Before trusting any empty result, prove the data exists. An empty Q4 means either "no device-code phishing" or "no Entra logs" — those are very different answers.
1. Confirm Entra sign-in logs are ingested: run Q4 with no filters and head(10) 2. Confirm Entra audit logs are ingested: run Q7 with no filters and head(10) 3. Confirm M365 UAL is ingested: run Q8 with no filters and head(10) 4. Confirm Falcon DNS telemetry: #event_simpleName=DnsRequest | head(10) 5. If any of 1-3 return nothing, STOP - fix ingestion before reporting "no findings"
Gate 2 — Field shape matches your parser
Q4–Q10 use Microsoft Entra schema field names. Your connector may prefix them.
For each of Q4-Q10, run once with a 1-hour window and head(10). If fields come back empty or missing, inspect a raw event and prefix accordingly, e.g. appDisplayName -> azure.signinlogs.properties.appDisplayName resultType -> azure.signinlogs.properties.resultType Fix the query, re-run, and only then promote to a scheduled search.
Gate 3 — Positive control
Prove the detection fires before you rely on it. This is a safe, authorized self-test against your own tenant.
With change approval, from an admin workstation and a TEST account:
1. Initiate a legitimate device-code sign-in you control
(e.g. Azure CLI or Microsoft Graph PowerShell device-code login).
2. Confirm the event appears in Q4 within the expected ingestion latency.
3. Confirm the correlation ID shows in Q5 if you deliberately pause before
entering the code.
4. Document ingestion lag - it determines how fast your alert can respond.
5. Remove the test account's tokens afterwards (revokeSignInSessions).
NOTE: this validates DETECTION only. Do not build or host a phishing lure to test.
Gate 4 — Baseline before alerting
Run Q4 over 30 days and classify EVERY result: - approved service account / automation -> allowlist - conference room / kiosk / signage -> allowlist by device ID - developer CLI workflow -> allowlist by account + app, review quarterly - anything else -> investigate now, then alert on it going forward An unbaselined Q4 will be too noisy to action. A baselined Q4 is near-zero-FP.
Gate 5 — IOC provenance (applied to this pack)
| Indicator | Disposition | Reason |
|---|---|---|
| Microsoft Authentication Broker client ID (GUID) | Omitted from CSV; queries match on appDisplayName instead | The GUID is referenced by Microsoft's reporting but its literal value does not appear in any snapshot fetched for this pack. Rather than reproduce a GUID from memory, the queries match the app display name — which is sourced — and analysts should confirm the client ID in their own tenant. |
| New/rotating DEBULL broker domains | REPLACE_WITH_NEW_DEBULL_BROKER_DOMAIN placeholder | CloakGuard publishes new lure domains on demand. The placeholder marks where to add newly observed hosts rather than inventing plausible-looking ones. |
trogir-rental.com, 49.12.61.13, vps3459922.trouble-free.net | Downgraded to hunt-only | Compromised legitimate site and shared hosting infrastructure. Blocking causes collateral damage to uninvolved third parties. |
microsoft.com/devicelogin | Explicitly excluded | Legitimate Microsoft endpoint central to the flow. Blocking breaks real authentication and does not stop the attack. |
PHPMailer git ref 1bc1716a… | Excluded | Benign open-source library reference present in DEBULL's Composer metadata. Not an indicator of compromise. |
| ARToken indicators | Included, separately labelled | Different platform (Talos / EvilTokens-linked), identical behaviour. Kept distinct so nobody reports ARToken infrastructure as DEBULL. |
Hardening — Tiered & Deployable
1 · Block the OAuth device-code flow via Conditional Access CRITICAL
MITRE M1042 (Disable or Remove Feature) · Microsoft Entra Conditional Access "authentication flows" condition. Create a policy targeting All users / All resources, condition = Authentication flows → Device code flow, grant = Block.
- Pilot first: run Q4 over 30 days to find genuine device-code use before enforcing. Exclude only what you can justify.
- Break-glass: exclude emergency-access accounts from all CA policies as standard practice.
- If a business case genuinely requires device-code (rare — some conference-room and IoT provisioning), scope an exception to those specific accounts or devices, not tenant-wide.
2 · Restrict who can register devices in Entra ID CRITICAL
MITRE M1018 (User Account Management). Microsoft explicitly recommends enrolment restrictions as mitigation for the broker/PRT variant. Limit device registration to specific groups and require MFA to register — this severs the refresh-token → device-registration → PRT persistence chain even if a token is stolen.
3 · Enable Continuous Access Evaluation HIGH
Without CAE, revoking a session waits for token expiry — up to an hour of continued attacker access after you thought you had contained it. With CAE, revocation is near-real-time.
4 · Turn on sign-in risk and user risk policies HIGH
MITRE M1032. Microsoft's guidance for this exact campaign: a sign-in risk policy that blocks or forces MFA on medium/high risk, plus a user-risk policy forcing secure password change. Combined with CAE, high-risk users have access revoked automatically.
5 · Phishing-resistant MFA for privileged and high-risk roles
MITRE M1032. FIDO2 / passkeys / certificate-based authentication. Note the nuance: device-code phishing does not defeat the MFA method — the user authenticates legitimately — so phishing-resistant MFA is not a direct counter here. Its value is that combined with token-protection and device-compliance CA policies it constrains where the resulting token can be used.
6 · Conditional Access token protection / device compliance for critical apps
Bind Exchange Online and SharePoint access to compliant or hybrid-joined devices. A token replayed from attacker VPS infrastructure then fails the device condition even though the token itself is valid.
7 · Alert on device registration events
Operationalise Q7 as a scheduled search. Every Entra device registration should be reconcilable to your asset inventory. This is the control that catches PRT persistence.
8 · Restrict external mail forwarding tenant-wide
MITRE M1042. Disable automatic external forwarding in the Exchange Online outbound spam filter policy and alert on inbox rules that forward externally or auto-delete — the BEC objective of this attack chain.
9 · Block legacy authentication
Microsoft guidance for this campaign. Legacy protocols cannot enforce MFA or CA conditions properly and provide an alternate path for stolen credentials.
10 · User awareness targeted at this specific pattern
MITRE M1017. The teachable rule is narrow and memorable: "Microsoft will never send you a code by email or chat for you to type into a login page. If a message gives you a code to enter, it is an attack." Generic phishing training does not cover this — users are trained to trust the real Microsoft page, and the real Microsoft page is exactly what they are shown.
11 · Full identity-log pipeline into the SIEM
Entra sign-in (interactive + non-interactive + service principal), Entra audit, M365 unified audit, and Graph activity logs into Falcon Next-Gen SIEM with ≥ 1 year retention. Without this, none of §8's identity queries can run.
12 · Baseline and govern the legitimate device-code population
Maintain a documented, reviewed allowlist of accounts and devices permitted to use device-code flow. Review quarterly. An ungoverned exception list slowly recreates the vulnerability.
13 · Application governance and OAuth consent control
Restrict user consent to verified publishers with low-impact permissions; enable the admin-consent workflow; review existing consent grants and service principals.
14 · Automated token-revocation response
Build a playbook that, on a confirmed device-code detection, calls revokeSignInSessions, forces password reset, disables the account pending triage, and enumerates registered devices — response speed is what limits damage when the tokens are already valid.
Deployable Playbooks
Playbook A — Find every legitimate device-code user before you block (run this first)
# Microsoft Graph PowerShell - 30-day device-code baseline
Connect-MgGraph -Scopes "AuditLog.Read.All","Directory.Read.All"
$since = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")
Get-MgAuditLogSignIn -Filter "createdDateTime ge $since" -All |
Where-Object { $_.AuthenticationProtocol -eq "deviceCode" } |
Select-Object CreatedDateTime, UserPrincipalName, AppDisplayName, AppId,
@{n="IP";e={$_.IpAddress}},
@{n="City";e={$_.Location.City}},
@{n="Country";e={$_.Location.CountryOrRegion}},
@{n="Result";e={$_.Status.ErrorCode}} |
Sort-Object UserPrincipalName |
Export-Csv .\devicecode-baseline-30d.csv -NoTypeInformation
# Classify EVERY row before enforcing the CA policy in Playbook B.
Playbook B — Conditional Access policy: block device-code flow
# Entra admin center - Protection > Conditional Access > New policy # # Name: BLOCK - OAuth 2.0 Device Code Flow # Users: All users # EXCLUDE: break-glass emergency access accounts # EXCLUDE: approved device-code accounts from Playbook A (if any) # Target: All resources (formerly "All cloud apps") # Conditions: Authentication flows -> Device code flow = Selected # Grant: Block access # Enable: Report-only FIRST -> review impact -> then On # # Validate after enabling: # 1. Re-run Playbook A weekly - the result set should shrink to your allowlist only. # 2. Attempt a device-code login with a non-excluded test account: expect a block. # 3. Confirm break-glass accounts still authenticate.
Playbook C — Restrict device registration and enforce MFA to register
# Entra admin center - Identity > Devices > Device settings
#
# Users may join devices to Microsoft Entra: Selected (scoped group)
# Users may register their devices with Microsoft Entra: Selected (scoped group)
# Require Multifactor Authentication to register or
# join devices with Microsoft Entra: Yes
# Maximum number of devices per user: set a sane cap
#
# Then audit current registrations against asset inventory:
Connect-MgGraph -Scopes "Device.Read.All","AuditLog.Read.All"
Get-MgDevice -All |
Select-Object DisplayName, DeviceId, OperatingSystem, TrustType,
ApproximateLastSignInDateTime, RegistrationDateTime |
Sort-Object RegistrationDateTime -Descending |
Export-Csv .\entra-devices.csv -NoTypeInformation
# Anything registered in the campaign window that is NOT in asset inventory
# is an incident. Tool-derived names (e.g. GraphSpy-Device) are confirmed bad.
Playbook D — Restrict external auto-forwarding (BEC objective)
# Exchange Online PowerShell
Connect-ExchangeOnline
# Block automatic external forwarding tenant-wide
Set-HostedOutboundSpamFilterPolicy -Identity Default -AutoForwardingMode Off
# Audit existing inbox rules that forward externally or delete
foreach ($mbx in Get-Mailbox -ResultSize Unlimited) {
Get-InboxRule -Mailbox $mbx.UserPrincipalName -ErrorAction SilentlyContinue |
Where-Object { $_.ForwardTo -or $_.RedirectTo -or $_.ForwardAsAttachmentTo -or $_.DeleteMessage } |
Select-Object @{n="Mailbox";e={$mbx.UserPrincipalName}},
Name, Enabled, ForwardTo, RedirectTo, DeleteMessage
} | Export-Csv .\suspicious-inbox-rules.csv -NoTypeInformation
Playbook E — Verify identity logging is flowing to the SIEM
# Entra admin center - Identity > Monitoring & health > Diagnostic settings # Ensure these categories are exported to your SIEM connector / Event Hub: # SignInLogs # NonInteractiveUserSignInLogs <-- token replay shows up here # ServicePrincipalSignInLogs # AuditLogs <-- device registration lives here # RiskyUsers / UserRiskEvents # # Microsoft 365 - enable unified audit log and mailbox auditing: Connect-ExchangeOnline Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true Get-OrganizationConfig | Select-Object AuditDisabled # expect False # # Then re-run Gate 1 in section 11 to confirm the data actually lands in Falcon.
Containment Runbook
Phase 1 — Isolate (first 30 minutes)
- Contact the user out of band. Phone call or in person — not email or Teams to the compromised identity, which the attacker may be reading in real time.
- Revoke sessions and refresh tokens:
Revoke-MgUserSignInSession -UserId <upn>(GraphrevokeSignInSessions). - Reset the password and require change at next sign-in.
- Enumerate and remove attacker devices: list every device registered to the user; delete any not in asset inventory. This is the step most responders miss.
- Disable the account if the blast radius is unclear — you can re-enable after triage.
- Confirm CAE is active so revocation takes effect immediately rather than at token expiry.
Phase 2 — Eradicate (first 4 hours)
- Remove malicious inbox rules, forwarding, delegation, Send-As and Send-on-Behalf grants.
- Review and remove attacker-added authentication methods — FIDO2 keys, passkeys, Windows Hello for Business registrations, authenticator app registrations, phone numbers.
- Review OAuth consent grants and service principals created or modified during the window; revoke anything unexplained.
- Block the confirmed-malicious §10 indicators at the proxy/firewall and import the CSV into Falcon IOC Management.
- Scope the campaign. Message-trace the lure to every recipient. Run Q4 tenant-wide for the window — device-code campaigns target many users at once, and ATO jumping means the next wave arrives from a trusted internal or partner account.
- Run Q7 tenant-wide, not just for the known victim — check whether any other device registrations occurred in the window.
Phase 3 — Recover & harden (24–72 hours)
- Deploy the Conditional Access device-code block (§13 Playbook B). If this incident does not justify it, nothing will.
- Restrict device registration and require MFA to register (§13 Playbook C).
- Enable sign-in risk and user risk policies; confirm CAE is on.
- Promote Q4, Q5, Q6 and Q7 to scheduled searches with alerting.
- Assess data exposure: what mail, files, and SharePoint content were accessible during the token's validity window? Drive breach-notification decisions from that, not from assumption.
- Targeted user education on the specific pattern — "a code sent to you to type in is always an attack."
- Lessons learned: how long between token issuance and detection? That interval is the metric to improve.
Detection Coverage Map
| Attack chain step | Coverage | Detection | Notes |
|---|---|---|---|
| 1 · Lure email delivery | PARTIAL | N1, message trace | The message inherited legitimate mail-auth signals (DKIM/SPF/DMARC pass, compauth pass) and carried no attachment. Gateway detection is unreliable by design — this is why it reached the inbox. |
| 2 · Compromised first-stage site | GOOD | Q1, Q2 | Managed endpoints only. Covered while the indicators are fresh. |
| 3 · Broker device-code generation | PARTIAL | Q1, B9 (proxy URI) | Server-to-server call from the lure page. Endpoint sees the domain; the broker call itself is only visible in full-URI proxy logs. |
| 4 · Victim enters code at Microsoft | GOOD | Q4, N1 | Fully visible in Entra sign-in logs — if they are ingested. This is the detection centre of gravity. |
| 5 · Token polling / 50199 pattern | GOOD | Q5, N1 | Microsoft-documented signature, low FP. |
| 6 · Attacker broker session created | GOOD | Q6, Q10, N2 | Strong coverage including the geo-plausible-datacenter case that impossible travel misses. |
| 7 · Device registration → PRT | GOOD | Q7, N3, N4 | Requires Entra audit logs specifically — a commonly missed ingestion category. |
| 8 · Session continuation from 2nd IP | GOOD | Q6, N2 | The IP-split-across-apps signature. |
| 9 · Graph enumeration / GraphSpy | PARTIAL | Q7 (device name), N5 | GAP: granular Graph API call telemetry is not consistently available. Detection relies on the device artifact and downstream effects rather than the enumeration itself. |
| 10 · Mailbox rules / BEC | GOOD | Q8, N5 | Requires mailbox auditing enabled. |
| 11 · SharePoint/OneDrive exfil | PARTIAL | Q9 | Threshold-based; a low-and-slow actor under the per-hour floor evades it. Tune to your baseline. |
| 12 · ATO jumping to new victims | PARTIAL | N10, Q4 tenant-wide | Depends on treating every device-code grant tenant-wide as in scope, not just the known victim. |
Known gaps — state these explicitly when reporting
- Unmanaged and personal devices. Q1–Q3 only see Falcon-managed endpoints. A user clicking the lure on a phone or home computer produces no endpoint telemetry — but the identity-plane queries (Q4–Q10) still catch it. This is precisely why the identity queries are the primary detection and the endpoint queries are supporting.
- No Entra log ingestion = no detection. If Entra sign-in and audit logs are not in Falcon NGSIEM, this pack degrades to three endpoint queries against perishable indicators. Fix ingestion before concluding "no findings."
- Graph API call-level telemetry is not consistently available, so post-authentication enumeration is inferred from artifacts and effects rather than observed directly.
- Indicator perishability. The CloakGuard deployment module publishes new lures to Cloudflare Workers and custom domains on demand. The §10 domain/IP list will decay quickly — the behavioural signatures (B1–B10) are the durable coverage.
- Single-vendor infrastructure sourcing. DEBULL-specific infrastructure detail rests on one vendor report. The technique is independently corroborated; the atomic indicators are not.
- Falcon Identity Protection contributes little here. This is a cloud-native identity attack that never touches on-prem AD authentication. Do not expect Identity Protection detections to fire.
Hunt Summary Ticket
TITLE: Hunt - DEBULL device-code phishing (Storm-2372-style M365/Entra ID ATO)
VERSION: v0.3 - 2026-07-19
SEVERITY: High (MFA-bypassing account takeover; PRT persistence survives password reset)
SCOPE: Entra ID / M365 identity control plane; Exchange Online; SharePoint/OneDrive;
Falcon-managed endpoints (lure-fetch visibility only)
HYPOTHESIS: Collaboration-themed lure -> compromised first-stage site -> DEBULL broker
generates a Microsoft Authentication Broker device code -> victim completes
auth on GENUINE Microsoft infrastructure (MFA satisfied, no password stolen)
-> attacker receives tokens -> device registered in Entra for PRT persistence
-> GraphSpy-derived post-exploitation -> mailbox rules, BEC, SharePoint exfil.
QUERIES RUN: Native N1 device-code URL clicks (Microsoft) | N2 broker-then-OWA split IP |
N3 device registration artifacts | N4 Device Registration Service | N5 checklist
CQL Q1 DNS to DEBULL infra | Q2 network to DEBULL IPs | Q3 rare workers.dev lures
Q4 ALL device-code grants | Q5 50199-then-success | Q6 broker+OWA split IP
Q7 device registration / PRT | Q8 inbox rules | Q9 SharePoint mass download
Q10 first-time-seen broker source IP
DO FIRST: Q4. Baseline 30 days, then treat every unexplained device-code grant by a
human user account as a candidate account takeover. Everything else is
corroboration. If Q4 returns nothing, verify ingestion before believing it.
FINDINGS: <pending analyst execution>
GAPS: Unmanaged/personal devices (no endpoint telemetry); Graph API call-level
telemetry unavailable; SharePoint threshold evadable low-and-slow; atomic
indicators highly perishable (CloakGuard rotates lures on demand);
DEBULL infrastructure detail from a single vendor report.
ACTIONS: 1. Verify Entra sign-in + audit log ingestion (Gate 1, section 11)
2. Baseline device-code use (Playbook A) then BLOCK the flow in
Conditional Access (Playbook B) - this is the fix, not a mitigation
3. Restrict device registration + require MFA to register (Playbook C)
4. Enable CAE and sign-in/user risk policies
5. Promote Q4/Q5/Q6/Q7 to scheduled searches
6. Import section 10 CSV to Falcon IOC Management (short shelf life)
REMEDIATION: Revoke tokens AND reset password AND remove attacker-registered devices.
Any two of the three leaves the actor with access.
AUTHOR: HuntPack
Changelog
table() calls now carry an explicit row limit: the default is 200 and truncation is silent, so a capped result was indistinguishable from a complete one. Atomic-IOC sweeps (filters over 5+ hashes or C2 IPs) use limit=max so a wide infection is never silently under-scoped; behavioural hunts use limit=200, where exceeding the cap indicates the query needs tuning. Where present, event names that do not exist in the Falcon data model were corrected (e.g. ServiceInstalled is a Sysmon concept, not a Falcon event; ElfFileWritten is ELFFileWritten) — such queries could never return a row. No detection logic, fields, or IOCs changed.@timestamp >= (now() - N) timeframe line from every query: an expression on the right of a comparison is not valid in CQL filter context, so Falcon rejected the query at line 1 and no hunt would run. The lookback is now a // LOOKBACK comment; set the window with Falcon's time picker, which is what the rest of the library does. No detection logic, fields, or IOCs changed.trogir-rental.com, 49.12.61.13 and the VPS hostname downgraded to hunt-only to prevent collateral blocking of a compromised legitimate site and shared hosting.References
- ZeroBEC — DEBULL: Storm-2372-Style Microsoft Device-Code Phishing With GraphSpy Post-Exploitation, 2026-07-04. zerobec.com — primary technical source. Snapshot:
01-zerobec.txt - The Hacker News — DEBULL Tooling Abuses Microsoft Device-Code Flow to Target M365 Accounts, 2026-07-07. thehackernews.com. Snapshot:
02-thn.txt - DIAMATIX — Microsoft Device Code Flow Abuse Creates a New Risk for M365 Accounts. diamatix.com. Snapshot:
03-diamatix.txt - Cisco Talos — ARToken: Inside an EvilTokens affiliate panel targeting Microsoft 365. blog.talosintelligence.com — adjacent platform. Snapshot:
04-talos-artoken.txt - Microsoft Security Blog — Storm-2372 conducts device code phishing campaign, 2025-02-13 (updated 2025-02-14). microsoft.com — background & mitigation authority. Snapshot:
05-microsoft-storm2372.txt - Microsoft Learn — Conditional Access: Block authentication flows. learn.microsoft.com — hardening authority. Snapshot:
06-ms-ca-block-devicecode.txt - MITRE ATT&CK — T1528 Steal Application Access Token; T1550.001 Application Access Token; T1098.005 Device Registration; T1621 MFA Request Generation. attack.mitre.org
- IETF RFC 8628 — OAuth 2.0 Device Authorization Grant — the legitimate specification being abused. datatracker.ietf.org
Generated 2026-07-19 · HuntPack v0.2 · Defensive content only — hunt, detection, and hardening guidance. Source snapshots retained in DEBULL-DeviceCodePhishing-Hunt-sources/ for indicator provenance verification.