DEBULL — Microsoft Device-Code Phishing (Storm-2372-style Tradecraft)

Phishing-as-a-Service tooling that abuses the OAuth 2.0 Device Authorization Grant to take over M365 / Entra ID accounts — no password stolen, MFA bypassed.
Version
v0.3 · 2026-07-19
Threat Class
Identity / PhaaS / ATO
Primary Plane
Entra ID · M365
CQL Queries
10
Author
HuntPack
01

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.

Scope correction — DEBULL is not ARToken. Some secondary coverage conflates the two. They are distinct platforms reported in the same week: DEBULL (ZeroBEC) is a compact PHP panel whose deployment module is branded CloakGuard, with jQuery/Bootstrap UI and a single Composer dependency. ARToken (Cisco Talos) is a separate React-based panel, linked to the EvilTokens PhaaS platform, exposing 80+ API endpoints for device-code phishing, PRT persistence, BEC and SharePoint exfiltration, with AI-assisted BEC email triage. This pack hunts DEBULL as its primary target and carries ARToken/EvilTokens indicators separately and clearly labelled, because the underlying behaviour — device-code grant abuse via the Authentication Broker — is identical and the same detections cover both.

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.

02

Source Review & Web Hunter Notes

TierSourceKey FindingCarry Fwd
1ZeroBEC — 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
1Microsoft 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
1Cisco Talos — ARToken: Inside an EvilTokens affiliate panel targeting Microsoft 365Separate but behaviourally identical platform. React panel, 80+ endpoints, clientMode: "broker" for PRT acquisition, PRT lifecycle endpoints, Cloudflare Workers lure deployment, operator UUID.partial
2The Hacker News (2026-07-07)Corroborates ZeroBEC findings; adds ecosystem context (EvilTokens, Tycoon, Proofpoint's May 2026 dynamic-code-generation analysis, ATO jumping).partial
2DIAMATIX — Microsoft Device Code Flow Abuse Creates a New Risk for M365 AccountsMSP/MSSP-oriented restatement of the risk and defensive posture. No new atomic indicators.no
2Microsoft Learn — Conditional Access: block authentication flowsVendor documentation for the CA control that blocks the device-code flow. Hardening authority.yes
Provenance. The verbatim fetched text of all six sources is saved alongside this pack in 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 kopyala in 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).
03

Hunt Brief & Attack Chain

#StepTelemetryHunt Angle
1Collaboration-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; UrlClickEventsN1 — link clicks into lure paths; low-content external messages with a single link
2Victim 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 logsQ1, Q2 — DNS + connections to lure infrastructure
3Landing page calls the DEBULL broker endpoint (office_poll.php) with action: get_auth_broker_device_code, tenant_id: common.Proxy / web logs; Falcon DNSQ1 — broker domain resolution; proxy URI hunt for the broker script name
4Victim 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
5Landing 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 logsQ5 — 50199-then-success correlation (Microsoft-documented heuristic)
6Attacker-side session created from the DEBULL origin, authenticating as Microsoft Authentication Broker.Entra sign-in logsQ6, Q10 — broker sign-ins; first-time-seen source IP
7Broker 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
8Session 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 logsQ6 — same user, broker + OWA, distinct IPs in a short window
9Post-authentication tooling appears — a GraphSpy-Device object. Graph-driven mailbox enumeration and collection follow.Entra audit; M365 unified audit; Graph activity logsQ7, N4 — anomalous device display names; Graph enumeration bursts
10Objective: 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 logQ8, Q9, N5, N6

Hunt hypotheses (fidelity-ordered)

#HypothesisMITREConf
H1An endpoint resolved or connected to known DEBULL broker/lure infrastructure.T1566.002HIGH
H2A user account completed an OAuth device-code grant that no business process explains.T1528, T1621HIGH
H3A device-code sign-in shows the 50199 waiting/interrupted → success pattern within one correlation ID.T1528HIGH
H4A Microsoft Authentication Broker sign-in is followed within minutes by OfficeHome / Outlook access from a different IP for the same user.T1550.001HIGH
H5An Entra device object was registered close in time to a broker sign-in, or carries a tool-derived display name.T1098.005HIGH
H6A Microsoft Authentication Broker sign-in originated from a source IP never before seen for that user.T1550.001MED
H7A mailbox rule was created that forwards externally or auto-deletes, shortly after an anomalous sign-in.T1114.003, T1564.008MED
H8A single principal downloaded an anomalous volume of SharePoint/OneDrive files in a short window.T1530MED
H9An endpoint resolved a Cloudflare Workers subdomain matching document-lure naming, seen by very few hosts.T1566.002, T1583.006MED
04

Consolidated IOC Table

Do not block 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.
TypeValueConfActionContext
domainfrenksv[.]sbsHIGHdetect / blockDEBULL device-code broker, Cloudflare-fronted campaign domain. Broker path office_poll.php.
domaindebull[.]appHIGHdetect / blockCanonical DEBULL backend vhost (recovered from the phpinfo Hostname:Port leak). Called directly by the Workers.dev lure.
domainpage-8-xls-vft-lvfsa.pefferarley83249[.]workers[.]devHIGHdetect / blockWorkers.dev Box/Excel-themed lure calling the same DEBULL broker. Demonstrates template reuse.
domaintrogir-rental[.]comMEDhunt onlyCompromised legitimate business site (Croatian rental company, years of indexed content). Malicious content isolated under /Team_Meets/. Do not block the apex — hunt the path.
domainvps3459922.trouble-free[.]netMEDhunt onlyVPS provider hostname of the DEBULL host. Shared hosting — blocking risks collateral.
ipv4162.35.167[.]138HIGHdetect / blockDEBULL panel origin and the Microsoft Authentication Broker session source seen in Entra telemetry. The strongest single pivot in the report.
ipv496.126.176[.]130HIGHdetect / blockAttacker session continuation egress (OfficeHome / One Outlook Web).
ipv449.12.61[.]13MEDhunt onlyFirst-stage compromised web host serving the lure. Shared/compromised infrastructure.
device nameGraphSpy-DeviceHIGHhunt / alertPost-authentication device object observed in the tenant. Query Entra device inventory and audit logs for this and similar tool-derived names.
uri fingerprintoffice_poll.phpHIGHhuntDEBULL broker script. Hunt in proxy/web-gateway URI logs regardless of hosting domain — this survives domain rotation.
uri fingerprintdeploy.php / deploy_ajax.phpMEDhuntCloakGuard deployment module and its AJAX API.
panel stringDEBULL Secure Mail System / DEBULL Admin Panel / Deploy Pages - CloakGuardHIGHhuntPanel titles for external-attack-surface and Shodan-style pivots.
sha256B96DE9AB…94B305MEDhuntDEBULL admin.css static fingerprint. Web-asset hash — not a Falcon-importable binary hash. See §10 note.
tokencec0d6e71b404597a8e486238f0cc69aMEDhuntCloudflare Web Analytics token embedded in the DEBULL panel — pivot for finding sibling infrastructure.
tokenc7173d6a700b02b111e51b703acd8c8eMEDhuntComposer content-hash of the DEBULL application.
domaindashboard-bl.pamconj[.]comMEDdetectARToken operator panel (Talos) — adjacent EvilTokens-linked platform, not DEBULL. Included because the behaviour is identical.
uuid84eb384d-cd3e-4c90-a283-c960ce557913MEDhuntARToken hard-coded operator UUID in the phishing kit. Adjacent platform.
Excluded on purpose. The PHPMailer source reference 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.
05

Affected Surface & Telemetry Matrix

SurfaceRequired telemetryPriorityGap risk if missing
Entra ID sign-in logs (interactive + non-interactive)Entra diagnostic settings → Falcon Next-Gen SIEM connector, or Sentinel SigninLogsCRITICALTotal 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 logsEntra diagnostic settings → NGSIEM / Sentinel AuditLogsCRITICALDevice 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 yearHIGHBEC objective activity — inbox rules, mail access, mass download — invisible.
Falcon DNS + network telemetry (managed endpoints)Falcon sensor, DnsRequest / NetworkConnectIP4MEDLoses 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 logsFull-URI logging forwarded to NGSIEMMEDLoses the domain-rotation-resistant office_poll.php path fingerprint.
Email gateway / message traceMessage trace + URL click telemetryMEDLoses the delivery-side pivot and the ability to scope who else received the lure.
Falcon Identity ProtectionIdentity Protection sensors on domain controllersLOWLimited relevance — this attack is cloud-native and does not touch on-prem AD authentication. Useful only for follow-on hybrid lateral movement.
Telemetry reality check. This threat is roughly 80% identity-plane and 20% endpoint. If your Entra sign-in and audit logs are not in Falcon Next-Gen SIEM, queries Q4–Q10 cannot run and this pack degrades to three low-yield endpoint queries plus the native KQL hunts in §7. Confirm ingestion before you start — see the validation gates in §11.
06

ATT&CK Mapping

TacticTechniqueNameObserved behaviour
Resource DevelopmentT1583.006Acquire Infrastructure: Web ServicesLures published to Cloudflare Workers via the CloakGuard deploy module; Cloudflare-fronted campaign domains.
Resource DevelopmentT1584.004Compromise Infrastructure: ServerFirst-stage lure hosted on a compromised legitimate business website under an isolated path.
Initial AccessT1566.002Phishing: Spearphishing LinkCollaboration / payment / shared-folder themed message with a single link and no attachment.
Credential AccessT1528Steal Application Access TokenBackend broker generates and polls a device code; victim's completion yields access + refresh tokens to the attacker.
Credential AccessT1621Multi-Factor Authentication Request GenerationThe victim satisfies MFA legitimately on real Microsoft infrastructure, authorizing the attacker's session.
Defense EvasionT1550.001Use Alternate Authentication Material: Application Access TokenAttacker replays the issued token from separate infrastructure; no password and no MFA prompt required.
PersistenceT1098.005Account Manipulation: Device RegistrationBroker refresh token exchanged for device-registration token; attacker device registered in Entra ID to obtain a PRT.
PersistenceT1556.009Modify Authentication Process: Conditional Access PoliciesPRT-backed persistence explicitly designed to survive password reset ("Persists across password changes" per the adjacent ARToken panel UI).
DiscoveryT1087.003Account Discovery: Cloud AccountMicrosoft Graph enumeration via GraphSpy or GraphSpy-derived tooling after token acquisition.
CollectionT1114.002Email Collection: Remote Email CollectionMailbox access and mail harvesting through Graph / Outlook.
CollectionT1530Data from Cloud StorageSharePoint / OneDrive access and bulk download.
PersistenceT1114.003Email Collection: Email Forwarding RuleInbox rule creation for forwarding and auto-deletion.
Defense EvasionT1564.008Hide Artifacts: Email Hiding RulesAuto-delete rules used to suppress evidence of BEC replies.
Lateral MovementT1534Internal SpearphishingATO jumping — the compromised trusted account sends the next round of device-code lures internally and to partners.
07

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.
08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.
Read before running Q4–Q10. Q1–Q3 use native Falcon endpoint telemetry and stable data-model field names. Q4–Q10 run against Entra ID / M365 logs ingested into Falcon Next-Gen SIEM and use the Microsoft Entra sign-in / audit schema field names (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.
Q1 · DNS resolution of DEBULL broker & lure infrastructure
CONF HIGHFP LOWCOST LOW

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)
Q2 · Network connections to DEBULL origin & attacker egress IPs
CONF HIGHFP LOWCOST LOW

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)
Q3 · Rare Cloudflare Workers document-lure subdomains (behavioural)
CONF MEDFP MEDCOST MED

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)
Q4 · OAuth device-code grant authentications (the core signal)
CONF HIGHFP MEDCOST LOWNGSIEM

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)
Q5 · 50199 waiting/interrupted → success within one correlation ID
CONF HIGHFP LOWCOST MEDNGSIEM

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)
Q6 · Broker sign-in + OfficeHome/Outlook from distinct IPs (session handoff)
CONF HIGHFP MEDCOST MEDNGSIEM

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)
Q7 · Entra device registration — PRT persistence & tool-derived device names
CONF HIGHFP MEDCOST LOWNGSIEM

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)
Q8 · Inbox rule creation — BEC persistence & evidence suppression
CONF MEDFP MEDCOST LOWNGSIEM

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)
Q9 · SharePoint / OneDrive mass download (exfiltration)
CONF MEDFP MEDCOST MEDNGSIEM

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)
Q10 · First-time-seen source IP for Authentication Broker sign-ins
CONF MEDFP MEDCOST MEDNGSIEM

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)
09

CrowdStrike Custom IOA Recommendations

Custom IOAs do not apply to this threat. Falcon Custom IOAs operate on endpoint process, file, network, and registry behaviour. DEBULL executes no code on the victim endpoint — the entire attack chain runs through the browser, genuine Microsoft infrastructure, and the Entra/M365 control plane. There is no process tree to pattern-match. Anyone who hands you a "Custom IOA for device-code phishing" has misunderstood the attack.

What to build instead

ControlBuildPriority
Falcon IOC ManagementImport 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 AccountQ4, 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 SuccessQ5. 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-InQ7 joined to Q4 on principal within 30 minutes. Severity Critical — this is PRT persistence being established.CRITICAL
Entra ID ProtectionEnable 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

  1. Confirm the sign-in really used the device-code protocol (re-run Q4 scoped to the principal).
  2. Check whether the account or device is on the approved device-code baseline — if yes, close as expected.
  3. Contact the user out of band (phone/Teams call, not email to the affected mailbox).
  4. Run Q5 for the correlation ID — does the 50199-then-success pattern appear?
  5. Run Q6 and Q10 — is there an IP split across apps, or a first-time-seen source IP?
  6. Run Q7 — was a device registered? This is the escalation trigger.
  7. Run Q8 and Q9 — inbox rules or mass download for this principal?
  8. 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?
  9. Scope the campaign: message-trace the lure theme to find every other recipient.
10

Machine-Readable IOC Appendix

Every atomic indicator below is traceable to a saved source snapshot in 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.
Falcon IOC Management CSVbulk import
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.
Entra / M365 Hunt Checklistidentity control plane
# 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
Behavioural Signaturesrotation-resistant
# 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"
JSON — machine-readableautomation
{
  "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"]
}
11

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)

IndicatorDispositionReason
Microsoft Authentication Broker client ID (GUID)Omitted from CSV; queries match on appDisplayName insteadThe 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 domainsREPLACE_WITH_NEW_DEBULL_BROKER_DOMAIN placeholderCloakGuard 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.netDowngraded to hunt-onlyCompromised legitimate site and shared hosting infrastructure. Blocking causes collateral damage to uninvolved third parties.
microsoft.com/deviceloginExplicitly excludedLegitimate Microsoft endpoint central to the flow. Blocking breaks real authentication and does not stop the attack.
PHPMailer git ref 1bc1716a…ExcludedBenign open-source library reference present in DEBULL's Composer metadata. Not an indicator of compromise.
ARToken indicatorsIncluded, separately labelledDifferent platform (Talos / EvilTokens-linked), identical behaviour. Kept distinct so nobody reports ARToken infrastructure as DEBULL.
12

Hardening — Tiered & Deployable

The single highest-value control: block the device-code flow in Conditional Access. Microsoft's own guidance is to block device-code flow wherever possible. Most organisations have no legitimate need for it. This one policy eliminates the entire attack class — not just DEBULL, but ARToken, EvilTokens, Tycoon, and Storm-2372 itself.
Immediate — deploy this week

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.

Near term — 1 to 4 weeks

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.

Strategic — 1 to 3 months

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.

⚠ Best-practice, no formal benchmark: controls 7, 12, and 14 are threat-driven operational practices derived from Microsoft's Storm-2372 guidance and the ZeroBEC campaign analysis rather than a CIS/DISA benchmark line item. They are included because they directly counter observed behaviour — review before deploying rather than dropping them.
13

Deployable Playbooks

Run all of these against a test tenant or pilot group first. Blocking device-code flow tenant-wide without baselining will break legitimate conference-room, IoT, and CLI workflows.

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.
14

Containment Runbook

A password reset alone does not contain this attack. If the actor registered a device and obtained a Primary Refresh Token, that persistence explicitly survives a password change. You must revoke tokens and reset the password and remove the attacker's registered device. Do all three, in that order, or you have not contained anything.

Phase 1 — Isolate (first 30 minutes)

  1. 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.
  2. Revoke sessions and refresh tokens: Revoke-MgUserSignInSession -UserId <upn> (Graph revokeSignInSessions).
  3. Reset the password and require change at next sign-in.
  4. 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.
  5. Disable the account if the blast radius is unclear — you can re-enable after triage.
  6. Confirm CAE is active so revocation takes effect immediately rather than at token expiry.

Phase 2 — Eradicate (first 4 hours)

  1. Remove malicious inbox rules, forwarding, delegation, Send-As and Send-on-Behalf grants.
  2. Review and remove attacker-added authentication methods — FIDO2 keys, passkeys, Windows Hello for Business registrations, authenticator app registrations, phone numbers.
  3. Review OAuth consent grants and service principals created or modified during the window; revoke anything unexplained.
  4. Block the confirmed-malicious §10 indicators at the proxy/firewall and import the CSV into Falcon IOC Management.
  5. 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.
  6. 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)

  1. Deploy the Conditional Access device-code block (§13 Playbook B). If this incident does not justify it, nothing will.
  2. Restrict device registration and require MFA to register (§13 Playbook C).
  3. Enable sign-in risk and user risk policies; confirm CAE is on.
  4. Promote Q4, Q5, Q6 and Q7 to scheduled searches with alerting.
  5. 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.
  6. Targeted user education on the specific pattern — "a code sent to you to type in is always an attack."
  7. Lessons learned: how long between token issuance and detection? That interval is the metric to improve.
15

Detection Coverage Map

Attack chain stepCoverageDetectionNotes
1 · Lure email deliveryPARTIALN1, message traceThe 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 siteGOODQ1, Q2Managed endpoints only. Covered while the indicators are fresh.
3 · Broker device-code generationPARTIALQ1, 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 MicrosoftGOODQ4, N1Fully visible in Entra sign-in logs — if they are ingested. This is the detection centre of gravity.
5 · Token polling / 50199 patternGOODQ5, N1Microsoft-documented signature, low FP.
6 · Attacker broker session createdGOODQ6, Q10, N2Strong coverage including the geo-plausible-datacenter case that impossible travel misses.
7 · Device registration → PRTGOODQ7, N3, N4Requires Entra audit logs specifically — a commonly missed ingestion category.
8 · Session continuation from 2nd IPGOODQ6, N2The IP-split-across-apps signature.
9 · Graph enumeration / GraphSpyPARTIALQ7 (device name), N5GAP: 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 / BECGOODQ8, N5Requires mailbox auditing enabled.
11 · SharePoint/OneDrive exfilPARTIALQ9Threshold-based; a low-and-slow actor under the per-hour floor evades it. Tune to your baseline.
12 · ATO jumping to new victimsPARTIALN10, Q4 tenant-wideDepends 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.
16

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
17

Changelog

v0.32026-07-24CQL correctness pass. All 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.
v0.22026-07-24CQL fix. Removed the in-query @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.
v0.12026-07-19Initial pack. Six sources snapshotted and cited. 10 CQL queries (3 endpoint, 7 Entra/M365 NGSIEM), 5 native KQL/checklist hunts, 14 ATT&CK techniques, 14 tiered hardening controls, 5 deployable playbooks, 3-phase containment runbook. Corrected the widespread conflation of DEBULL with the separately-reported ARToken/EvilTokens panel — ARToken indicators are carried but labelled distinctly. Microsoft Authentication Broker client-ID GUID omitted from the import CSV (not present in any fetched source); queries match on app display name instead. 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.
18

References

  1. 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
  2. The Hacker News — DEBULL Tooling Abuses Microsoft Device-Code Flow to Target M365 Accounts, 2026-07-07. thehackernews.com. Snapshot: 02-thn.txt
  3. DIAMATIX — Microsoft Device Code Flow Abuse Creates a New Risk for M365 Accounts. diamatix.com. Snapshot: 03-diamatix.txt
  4. Cisco Talos — ARToken: Inside an EvilTokens affiliate panel targeting Microsoft 365. blog.talosintelligence.com — adjacent platform. Snapshot: 04-talos-artoken.txt
  5. 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
  6. Microsoft Learn — Conditional Access: Block authentication flows. learn.microsoft.com — hardening authority. Snapshot: 06-ms-ca-block-devicecode.txt
  7. MITRE ATT&CK — T1528 Steal Application Access Token; T1550.001 Application Access Token; T1098.005 Device Registration; T1621 MFA Request Generation. attack.mitre.org
  8. 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.