Payroll Pirates (Storm-2755) — Microsoft 365 AiTM Session Hijack HuntPack
Executive Summary
Arctic Wolf Labs and Microsoft (as Storm-2755) are tracking an active, widespread adversary-in-the-middle (AiTM) phishing campaign — publicly nicknamed "Payroll Pirates" — that has targeted hundreds of organizations across healthcare, education, manufacturing, government, and professional services in the US, Canada, and Europe since at least April 2026, with a large wave in July 2026. The attacker's objective is narrow and patient: use a voicemail-themed phishing lure to route victims through a multi-stage redirect chain into a real-time AiTM proxy that relays Microsoft's genuine login flow — capturing the authenticated session token even when MFA is satisfied — then use that stolen session to quietly enumerate payroll/HR/finance staff via Microsoft Graph, read mailbox content about invoices, payments, banking, and direct deposit, and in a smaller subset of cases stage payroll fraud by hiding relevant mail or manipulating HR platforms like Workday.
Because the exploit target is a live Microsoft 365 session rather than an endpoint, the highest-value defensive angle is identity telemetry, not endpoint EDR: Entra ID sign-in log anomalies (rare error codes, session/token replay across IPs, non-native user agents on the Outlook client), Microsoft Graph activity log ingestion (off by default in most tenants and the only visibility into the reconnaissance stage), and Exchange Online mailbox/audit telemetry (the specific ClientAppId/APIId pairing Arctic Wolf found in no legitimate Outlook traffic). Falcon endpoint sensors only see this attack chain if a managed device's browser resolves the phishing infrastructure directly — everything downstream of that click happens cloud-side.
Defender priority: password reset and MFA re-registration alone do not remediate this threat. The attacker already holds a live, previously-issued session/refresh token that survives both actions. The only action that ends attacker access is explicit session and refresh-token revocation, combined with review and removal of any OAuth application consent grants made during the compromise window (a persistence path that also survives password reset and MFA re-registration).
Source Review & Web Hunter Notes
Seven sources were fetched and saved verbatim to PayrollPirates-Storm2755-AiTM-Hunt-sources/ for provenance. Two additional sources (Microsoft's own Storm-2755 writeup and Security Risk Advisors' multi-engagement IR blog) were pulled in via follow-up web search because they contain primary attacker infrastructure, MITRE mapping, and hunting-query detail the five originally assigned sources only partially covered.
| Tier | Source | Key Finding | Carry Forward |
|---|---|---|---|
| 1 | Arctic Wolf Labs blog (01-arcticwolf.txt) | Named the cluster "Payroll Pirates," linked to Storm-2755; documented ClientAppId/APIId pairing, error 90014, 8-hour session refresh cadence, fingerprinting endpoint path | Yes |
| 1 | The Hacker News (02-thehackernews.txt) | Confirmed residential-proxy disguise technique, 6-stage redirect chain, browser-fingerprinting field list, restraint-strategy behavior | Yes |
| 2 | CyberPress (03-cyberpress.txt) | Confirmed subject-line format, redirector subdomain pattern (idp.), proxy subdomain patterns (mslogin/msonline/msauth), 7-day geolocation cookie | Yes |
| 1 | Cyber Security News (04-cybersecuritynews.txt) | Full atomic IOC table: redirector/proxy domains, HTTP header fingerprints, user agents, Graph endpoints, ASN — the primary IOC source for this pack | Yes |
| 2 | Canadian Cyber Security Journal (05-cybersecurityjournalca.txt) | Canadian regulatory framing (PIPEDA / OSFI B-13), confirms token-theft defeats standard MFA entirely, recommends CA location/ASN policy review | Partial (regulatory context, not technical) |
| 1 | Microsoft Security Blog — Storm-2755 (06-microsoft-security-blog.txt) | Direct actor attribution to Storm-2755; earlier April 2026 wave used domain bluegraintours[.]com, UA axios/1.7.9, error 50199, ~30-min token replay cadence, inbox rules hiding "direct deposit"/"bank" mail | Yes (behavioral corroboration; wave-specific IOCs kept separate) |
| 1 | Security Risk Advisors IR blog (07-sra-io.txt) | Full MITRE ATT&CK mapping, Graph API keyword-enumeration pattern with $top=999/$skiptoken, residential-ISP IP list, OAuth consent-grant persistence warning, 7 hunting-query descriptions | Yes |
Decision notes: the campaign clearly spans multiple infrastructure "waves" under the same actor cluster (Storm-2755 / Payroll Pirate) — domains and IPs rotate between the April 2026 Canadian wave (source 06) and the July–August 2026 wave (sources 01–05). This pack treats wave-specific atomic IOCs (domains, IPs, exact UAs) as hunt/enrich confidence rather than universal blocklist entries, and leans on the behavioral patterns that persist across waves (session/token replay cadence, Graph keyword enumeration, ClientAppId/APIId mail-access pairing, inbox-rule hiding of payroll keywords) for the highest-confidence detections.
Hunt Brief & Attack Chain
Attack chain
| Step | Behavior | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 | Voicemail-themed phishing email, Microsoft branding, fabricated caller ID/date/duration/reference number, subject "[Org] :ATTN: Review messages. Ref id: [random]" | Email gateway / M365 Defender for Office (out of Falcon scope) | Not covered by this pack — route to mail-gateway rules |
| 2 | Multi-stage redirect via Google Meet link-redirect, Google Ads click infrastructure, AWS S3, then idp.* redirector domain | Managed-endpoint DNS/browser network activity (if link opened on a Falcon-covered device) | Q9 — DNS to known redirector/proxy domains |
| 3 | AiTM proxy (mslogin.* / msonline.* / msauth.*) relays real Microsoft OAuth login in real time; browser-fingerprints and geolocates the victim before forwarding | Cloud-side only — invisible to endpoint EDR | No direct Falcon coverage; downstream artifacts only (Q2, Q4) |
| 4 | Attacker captures session/refresh token after victim completes sign-in + MFA; victim is forwarded to the real O365 site and sees no anomaly | Entra ID sign-in logs | Q2 (error 90014), Q4 (non-native UA) |
| 5 | Attacker replays the stolen token from rotating residential-proxy IPs, refreshing the session at a regular cadence (~30 min to ~8 hr depending on wave) | Entra ID sign-in logs (sessionId / non-interactive sign-ins) | Q3 (session across IPs), Q6 (refresh cadence) |
| 6 | Microsoft Graph enumeration for payroll/HR/finance/admin roles: bulk /v1.0/users?$top=999 then keyword $search with $skiptoken pagination | Microsoft Graph activity logs (not enabled by default) | Q5 |
| 7 | Mailbox collection of invoice/payment/banking/direct-deposit mail via the anomalous ClientAppId/APIId pairing | O365 Exchange Online mailbox audit (MailItemsAccessed) | Q1 |
| 8 | (Subset of cases) inbox rule created to move/hide messages matching direct-deposit/bank/payroll keywords, or mark them read and move to Deleted Items | O365 Management Activity / Exchange admin audit log | Q7 |
| 9 | (Possible persistence) OAuth application consent grant with broad delegated mail/directory scopes — survives password reset and MFA re-registration | Entra ID audit log | Q8 |
| 10 | Fraud follow-through: social-engineer HR/payroll staff or directly modify banking details in a connected HR/payroll platform (e.g., Workday) | HR/payroll SaaS audit log (out of Falcon scope; CASB/Defender for Cloud Apps recommended) | Not covered by this pack — see Hardening §12 |
Hunt hypotheses (ordered by fidelity)
- H1 (high): Exchange Online
MailItemsAccessedevents pairing a specific ClientAppId with an APIId that never appears on legitimate Outlook traffic indicate stolen-session mailbox collection. - H2 (high): A New/Set-InboxRule operation whose parameters combine a payroll/bank/direct-deposit keyword with a delete/move-to-Deleted-Items/mark-read action is fraud staging, not personal mail filtering.
- H3 (high): Entra sign-in error 90014 on the OfficeHome application is rare enough in most tenants that its appearance is a strong AiTM-relay artifact.
- H4 (high): A single Entra sign-in
sessionIdobserved from three or more distinct source IPs (or two or more countries) in a short window indicates token replay, not normal device roaming. - H5 (medium): Outlook-attributed sign-ins reporting a non-native browser/tooling user agent (Firefox 131/142, Python Requests, axios) indicate the AiTM kit or its session-maintenance automation, not the real Outlook client.
- H6 (medium): A high count of non-interactive sign-ins on one sessionId from three or more distinct IPs indicates automated session-maintenance beaconing rather than a single roaming user.
- H7 (medium): Bulk Microsoft Graph user enumeration (
$top=999) combined with payroll/HR/finance keyword$searchand$skiptokenpagination is reconnaissance, not routine directory sync. - H8 (medium): An OAuth consent grant or delegated permission addition carrying broad mail/directory scopes, occurring near an anomalous sign-in for the same user, indicates persistence staging.
Attack-chain steps 1, 3, and 10 have no Falcon-visible telemetry in this pack's scope (email gateway, cloud-side AiTM proxy internals, and HR/payroll platform audit are outside CrowdStrike's data model). These are carried forward as coverage gaps in §15 rather than papered over with an invented endpoint signal.
Consolidated IOC Table
| Type | Value | Confidence | Action | Context | Expiry |
|---|---|---|---|---|---|
| Redirector domain | idp.keyreniao.com | Medium | hunt | AiTM redirector, July–Aug 2026 wave | 2026-11-17 |
| Redirector domain | idp.korminel.com | Medium | hunt | AiTM redirector, July–Aug 2026 wave | 2026-11-17 |
| Redirector domain | idp.kualabemo.com | Medium | hunt | AiTM redirector, July–Aug 2026 wave | 2026-11-17 |
| Proxy domain | mslogin.milocaroline.com | Medium | hunt | AiTM authentication proxy | 2026-11-17 |
| Proxy domain | msonline.logicalineonline.com | Medium | hunt | AiTM authentication proxy | 2026-11-17 |
| Proxy domain | msauth.monlinelogicaline.com | Medium | hunt | AiTM authentication proxy | 2026-11-17 |
| Lookalike domain | office.ofrecie.com | Medium | hunt | Misspelled Office-themed lookalike | 2026-11-17 |
| Domain (earlier wave) | bluegraintours.com | Medium | enrich | April 2026 Storm-2755 wave, Canadian employees (Microsoft attribution) | 2026-11-17 |
| Fingerprint endpoint path | /st_58200519/class_identifier.php | High | hunt | Browser-fingerprinting endpoint on AiTM infrastructure | 2026-11-17 |
| Geolocation API domain | api.country.is | Low | enrich | Third-party geolocation service queried by the phishing kit; also has legitimate uses | 2026-09-17 |
| HTTP header | server: openresty/1.31.1.1 | Low | enrich | AiTM proxy / fingerprinting endpoint response header | 2026-09-17 |
| HTTP header | x-powered-by: PHP/8.2.32 | Low | enrich | Fingerprinting endpoint response header | 2026-09-17 |
| User-Agent | Firefox/131.0 (rv:131.0) reported as Outlook client | High | hunt | Session-maintenance / mail-collection automation | 2027-02-17 |
| User-Agent | Firefox/142.0 (rv:142.0) reported as Outlook client | High | hunt | Interactive account-takeover sequence UA (SRA) | 2027-02-17 |
| User-Agent | Python Requests | Medium | hunt | Recurring session-maintenance activity | 2027-02-17 |
| User-Agent | axios/1.18.1 | Medium | hunt | Microsoft Graph reconnaissance UA | 2027-02-17 |
| User-Agent (earlier wave) | axios/1.7.9 | Medium | enrich | April 2026 wave AiTM client UA (Microsoft) | 2027-02-17 |
| Mail-access ID pairing | ClientAppId: 5d661950-3475-41cd-a2c3-d671a3162bc1 + APIId: c999ed3e-27ae-4cb3-b3a2-46b056af63d3 | High | detect | Arctic Wolf reports zero legitimate Outlook traffic with this pairing | 2027-02-17 |
| Entra sign-in error | errorCode 90014 on appDisplayName=OfficeHome | High | hunt | Rare error, AiTM credential-relay artifact | 2027-02-17 |
| Entra sign-in error (earlier wave) | errorCode 50199 (Login:reprocess) immediately preceding successful auth | Medium | hunt | Token replay artifact, April 2026 wave (Microsoft) | 2027-02-17 |
| Graph endpoint pattern | graph.microsoft.com/v1.0/users?$top=999 + keyword $search + $skiptoken | High | hunt | Bulk payroll/HR/finance user enumeration | 2027-02-17 |
| ASN | AS27176, Datawagon LLC | Low | enrich | Hosting provider observed during interactive inbox-rule activity in one report; not itself malicious | 2026-11-17 |
| Behavioral cadence | Non-interactive session refresh every ~8h (Jul–Aug wave) or ~30min–3h (Apr wave), same sessionId, rotating IPs | High | hunt | Core token-replay behavioral signature — persists across waves | 2027-02-17 |
Residential-proxy source IPs reported by Security Risk Advisors (source 07) are treated as context, not blocklist entries — they are ephemeral proxy exit points, not stable attacker infrastructure, and are highly likely to belong to unrelated residential subscribers by the time this pack is read. They are not reproduced in §10's importable block for that reason; use the behavioral queries (Q3, Q6) instead of IP blocking.
Affected Surface & Telemetry Matrix
| Surface | Required Telemetry | Priority | Gap Risk |
|---|---|---|---|
| Entra ID sign-in (interactive + non-interactive) | azure_signinlogs ingested into Falcon Next-Gen SIEM | Critical | Low if already ingesting Entra logs; many tenants only ingest interactive sign-ins — confirm non-interactive category is included (needed for Q6) |
| Entra ID audit log (consent grants, role/permission changes) | azure_auditlogs | High | Low-Medium |
| Microsoft Graph activity log | Graph activity logging enabled at the tenant level and shipped to SIEM | High | High — not enabled by default in most Entra tenants. Without it, attack-chain step 6 (recon) is completely invisible. |
| Exchange Online mailbox audit (MailItemsAccessed, inbox rules) | O365 Management Activity API / Unified Audit Log ingested into Falcon Next-Gen SIEM | Critical | Medium — mailbox auditing must be enabled per-org and retained long enough to cover the investigation window |
| Managed-endpoint DNS/browser network activity | Falcon sensor DnsRequest on the device that opened the phishing link | Medium | High — only covers the initial click, only on Falcon-covered devices, and only while the specific redirector/proxy domain is current |
| Email gateway / M365 Defender for Office | Out of CrowdStrike's data model entirely | High (for delivery-stage prevention) | Not covered by this pack — route to mail-gateway/anti-phish rules |
| HR/payroll SaaS platform (e.g., Workday) | Platform-native audit log or CASB (Defender for Cloud Apps) | High (for fraud follow-through) | Not covered by this pack — see Hardening §12 recommendation to connect to a CASB |
ATT&CK Mapping
| Tactic | Technique | Name | Observed Behavior |
|---|---|---|---|
| Resource Development | T1608.006 | Stage Capabilities: SEO Poisoning | Malvertising/SEO poisoning used in an earlier wave to surface a lookalike domain for generic "Office 365" searches |
| Initial Access | T1566.002 | Phishing: Spearphishing Link | Voicemail-themed email with a link through a multi-stage redirect chain |
| Credential Access | T1557 | Adversary-in-the-Middle | Real-time proxy of the genuine Microsoft login flow |
| Credential Access | T1539 | Steal Web Session Cookie | Session/authorization material captured post-MFA at the AiTM proxy |
| Defense Evasion / Lateral Movement | T1550.004 | Use Alternate Authentication Material: Web Session Cookie | Stolen session replayed from rotating residential-proxy infrastructure |
| Persistence / Defense Evasion | T1078.004 | Valid Accounts: Cloud Accounts | Continued access as the legitimate user via the stolen session |
| Discovery | T1087.004 | Account Discovery: Cloud Account | Bulk + keyword Microsoft Graph user enumeration for payroll/HR/finance roles |
| Collection | T1114.002 | Email Collection: Remote Email Collection | MailItemsAccessed collection of invoice/payment/banking mail via anomalous client pairing |
| Defense Evasion | T1564.008 | Hide Artifacts: Email Hiding Rules | Inbox rules moving/hiding payroll- and bank-related mail in a subset of intrusions |
| Persistence | T1098.003 | Account Manipulation: Additional Cloud Roles | OAuth application consent grants with broad delegated scopes observed in related activity |
| Lateral Movement | T1534 | Internal Spearphishing | Compromised mailbox potentially used to pursue payroll requests internally (reported by SRA for the related cluster) |
| Impact | T1657 | Financial Theft | End objective — redirected salary/direct-deposit payments or fraudulent payment approval via compromised finance staff |
Native Audit-Log Hunts
Checks that don't require CQL — run directly in the Entra/M365/Purview admin surfaces. Useful both as a first-pass triage and as a way to validate that the CQL queries in §8 will have data to work with.
- Entra ID → Sign-in logs: filter Application =
OfficeHome, Status = Failure, Sign-in error code =90014. Cross-reference any hits against interactive sign-ins for the same user in the following 10 minutes. - Microsoft Defender XDR advanced hunting: the built-in "Suspicious Exchange Online Graph Reconnaissance Activity" alert (Defender-native, distinct from this pack's Q5) fires on the same bulk-enumeration pattern and is a good corroborating signal if your tenant has Defender XDR licensed.
- Microsoft Purview → Audit (Unified Audit Log) search: Activities =
New-InboxRule,Set-InboxRule. Manually review any rule whose parameters reference "direct deposit," "bank," "payroll," or "HR" combined with a delete/move/mark-read action. - Entra ID → Enterprise Applications → Consent and permissions → Admin consent requests / user consent audit: review any application consented to during a suspected compromise window, particularly grants of
Mail.Read,Mail.ReadWrite,full_access_as_app, orDirectory.Read.All. - Entra ID Identity Protection → Risky sign-ins / Risky users: cross-reference any user flagged here against Q1/Q3/Q7 hits — Identity Protection's own risk engine sometimes catches the anomalous device/location combination independently of this pack's queries.
- Exchange Online → Mailbox audit search: for any user suspected compromised, pull
MailItemsAccessedevents for the full suspected exposure window and manually confirm whether payroll/finance-relevant mail was opened.
CrowdStrike LogScale CQL Hunt Queries
This campaign is identity/cloud-native. Queries Q1–Q8 target SaaS/IdP repos (azure_signinlogs, azure_auditlogs, and O365/Graph activity logs). Entra sign-in/audit fields (Q3–Q8) match Microsoft's own lowerCamelCase schema (appDisplayName, ipAddress, etc.) and are documented in the canonical Falcon data model reference. O365 Management Activity / Exchange mailbox-audit fields (Q1–Q2) are parser-prefixed per tenant — how your Falcon NG-SIEM O365 connector names Operation, ClientAppId, etc. on ingest is tenant/parser-version dependent, so this pack renders them as lowercase snake_case placeholders (operation, client_app_id, ...). Validate each against one real sample event before deploying. Only Q9 targets native Falcon sensor telemetry.
Looks for: Exchange Online mailbox reads using the specific ClientAppId+APIId pairing Arctic Wolf found in zero legitimate Outlook traffic across its telemetry. FP: none observed by source reporting for this exact pairing; still baseline a full month of tenant traffic before alerting, since sensor/parser versions vary.
// HUNT: MailItemsAccessed via anomalous ClientAppId/APIId pairing (Payroll Pirates AiTM) // MITRE: T1114.002 (Email Collection: Remote Email Collection), T1078.004 (Valid Accounts: Cloud Accounts) // CONF: high // FP: low // COST: low // REQUIRES: O365 Management Activity API / Unified Audit Log (Exchange mailbox audit) ingested into Falcon Next-Gen SIEM // ⚠ Field names below are lowercase placeholders — validate in tenant: operation, client_app_id, api_id, mailbox_owner_upn, client_ip (O365 audit schema is parser-prefixed per tenant, not in this skill's canonical Falcon field table — confirm exact casing against a live sample event) // FALSE POSITIVES: none observed by source reporting for this exact pairing on legitimate Outlook traffic // TUNING: if a legitimate mail migration tool or connector is later found to share this pairing, exclude by mailbox_owner_upn allowlist rather than dropping the pairing entirely // LOOKBACK: 14d #repo = o365_management_activity | operation = "MailItemsAccessed" | client_app_id = "5d661950-3475-41cd-a2c3-d671a3162bc1" | api_id = "c999ed3e-27ae-4cb3-b3a2-46b056af63d3" | table([@timestamp, mailbox_owner_upn, client_ip, client_app_id, api_id, operation]) | sort(@timestamp, order=desc)
Looks for: a new or modified inbox rule whose parameters reference direct-deposit/payroll/bank keywords. FP: employees do create personal "bank statement" filters — review the destination folder and mark-as-read/delete action together, not the keyword alone.
// HUNT: New inbox rule created to hide or move payroll/bank/direct-deposit mail // MITRE: T1564.008 (Hide Artifacts: Email Hiding Rules) // CONF: high // FP: low // COST: low // REQUIRES: O365 Management Activity API / Exchange admin audit log // ⚠ Field names below are lowercase placeholders — validate in tenant: operation, parameters, user_id, client_ip (O365 audit schema is parser-prefixed per tenant, not in this skill's canonical Falcon field table) // FALSE POSITIVES: legitimate personal inbox rules that happen to reference "bank" (e.g. a bank-statement filter) — the fraud-staging pattern is the keyword PLUS a hide/delete action together // TUNING: narrow further to rules whose parameters combine a payroll/bank/direct-deposit keyword AND a DeleteMessage, MoveToFolder=DeletedItems, or MarkAsRead=true action — that combination is the pattern reported in source intel, not the keyword alone // LOOKBACK: 30d #repo = o365_management_activity | operation = /^(New-InboxRule|Set-InboxRule)$/ | parameters = /(direct deposit|payroll|\bbank\b)/i | table([@timestamp, user_id, operation, parameters, client_ip]) | sort(@timestamp, order=desc)
Looks for: the rare Entra sign-in failure code associated with the AiTM credential-relay artifact on the OfficeHome app. FP: error 90014 can occasionally occur on legitimate misconfigured client integrations — confirm baseline volume before alerting.
// HUNT: Entra sign-in failure errorCode 90014 on OfficeHome (AiTM proxy credential relay artifact) // MITRE: T1557 (Adversary-in-the-Middle), T1078.004 (Valid Accounts: Cloud Accounts) // CONF: high // FP: medium // COST: low // REQUIRES: azure_signinlogs (Entra ID sign-in logs) // ⚠ Field unverified — validate in tenant: errorCode (Entra sign-in schema field; appDisplayName is in this skill's canonical table, errorCode is not — confirm against a live sample event) // FALSE POSITIVES: rare legitimate client-integration misconfigurations can also raise 90014 // TUNING: exclude any appId/clientId already known to be a first-party provisioning or bulk-onboarding tool that legitimately omits a credential field // LOOKBACK: 7d #repo = azure_signinlogs | appDisplayName = "OfficeHome" | errorCode = "90014" | table([@timestamp, userPrincipalName, appDisplayName, errorCode, ipAddress, clientAppUsed]) | sort(@timestamp, order=desc)
Looks for: one Entra sessionId observed from more than 2 distinct source IPs — the core token-replay signature. FP: corporate VPN egress changes and mobile-carrier IP rotation can show a session spanning 2 IPs; the signal strengthens sharply above 3+ distinct IPs or 2+ countries.
// HUNT: Single sign-in session/token replayed from multiple source IPs (AiTM token theft) // MITRE: T1550.004 (Use Alternate Authentication Material: Web Session Cookie), T1078.004 // CONF: high // FP: medium // COST: medium // REQUIRES: azure_signinlogs with sessionId populated (Entra ID sign-in logs, interactive + non-interactive) // ⚠ Field unverified — validate in tenant: sessionId (Entra sign-in schema field; not in this skill's canonical field table — confirm against a live sample event) // FALSE POSITIVES: corporate VPN egress changes, mobile carrier IP rotation, and legitimate multi-device sync can show a session spanning 2 IPs // TUNING: raise the DistinctIPs threshold to 3+ and add a distinct-country check; exclude known corporate VPN egress ranges with cidr() as a separate top-level filter stage // LOOKBACK: 7d #repo = azure_signinlogs | sessionId = * | groupBy([sessionId, userPrincipalName], function=[count(as=SignIns), count(ipAddress, distinct=true, as=DistinctIPs), collect(ipAddress)], limit=20000) | DistinctIPs > 2 | sort(DistinctIPs, order=desc) | table([userPrincipalName, sessionId, SignIns, DistinctIPs, ipAddress])
Looks for: sign-ins attributed to the Outlook client but presenting a Firefox/Python-Requests/axios user agent — the AiTM kit or its automation, not the real client. FP: RPA/automation tools with legitimate Graph/EWS integrations can present non-native UAs.
// HUNT: Outlook sign-ins reporting non-native browser user-agent (AiTM kit / session-maintenance automation) // MITRE: T1557 (Adversary-in-the-Middle), T1078.004 (Valid Accounts: Cloud Accounts) // CONF: medium // FP: medium // COST: low // REQUIRES: azure_signinlogs (userAgent, clientAppUsed, appDisplayName) // ⚠ Field unverified — validate in tenant: userAgent (Entra sign-in schema field; clientAppUsed is in this skill's canonical table, userAgent is not — confirm against a live sample event) // FALSE POSITIVES: security scanners, RPA/automation tools with legitimate Graph/EWS integrations, some third-party mail clients // TUNING: exclude known service-account UPNs used for approved automation; require clientAppUsed to indicate Outlook/native client paired with the anomalous userAgent to reduce noise // LOOKBACK: 7d #repo = azure_signinlogs | appDisplayName = "Outlook" | userAgent = /(Firefox\/131\.0|Firefox\/142\.0|Firefox\/151\.0|Python Requests|axios\/)/i | table([@timestamp, userPrincipalName, appDisplayName, clientAppUsed, userAgent, ipAddress]) | sort(@timestamp, order=desc)
Looks for: one sessionId generating a high count of non-interactive sign-ins from 3+ distinct IPs — automated session-maintenance beaconing. FP: legitimate long-lived desktop/mobile Outlook clients also refresh tokens periodically, but typically from a stable IP; the signal is repeated refresh COMBINED WITH IP rotation, not refresh volume alone.
// HUNT: Recurring non-interactive token-refresh sign-ins from rotating source IPs (session-maintenance beaconing) // MITRE: T1550.004 (Use Alternate Authentication Material: Web Session Cookie), T1078.004 // CONF: medium // FP: medium // COST: medium // REQUIRES: azure_signinlogs (isInteractive, sessionId, ipAddress) — non-interactive sign-in category must be ingested // ⚠ Field unverified — validate in tenant: isInteractive, sessionId (Entra sign-in schema fields; not in this skill's canonical field table — confirm against a live sample event) // FALSE POSITIVES: a single roaming laptop moving between home/office/mobile networks can also show 2-3 distinct IPs on one session // TUNING: require DistinctIPs >= 3 and SignIns >= 6 over the lookback window to separate beaconing token replay from a single roaming device; raise thresholds further if the tenant has a large remote workforce // LOOKBACK: 7d #repo = azure_signinlogs | isInteractive = "false" | appDisplayName = /(Outlook|Office 365 Exchange Online|OfficeHome)/i | groupBy([sessionId, userPrincipalName], function=[count(as=SignIns), count(ipAddress, distinct=true, as=DistinctIPs)], limit=20000) | SignIns > 5 | DistinctIPs > 2 | sort(SignIns, order=desc) | table([userPrincipalName, sessionId, SignIns, DistinctIPs])
Looks for: bulk Graph user enumeration combined with payroll/HR/finance keyword search and pagination — the reconnaissance pattern SRA found nearly identical across every engagement. FP: legitimate HRIS/SCIM provisioning tools performing bulk directory sync can trigger the $top=999 pull alone; the combination with keyword search AND pagination is the discriminator.
// HUNT: Microsoft Graph bulk user enumeration with payroll/HR/finance keyword search and pagination // MITRE: T1087.004 (Account Discovery: Cloud Account) // CONF: medium // FP: low // COST: medium // REQUIRES: Microsoft Graph activity logs ingested into Falcon Next-Gen SIEM — NOT enabled by default in most Entra tenants; must be explicitly turned on (see Hardening §12) // ⚠ Field unverified — validate in tenant: repo name, requestUri, appId (Graph activity log schema; not in this skill's canonical field table — confirm against a live sample event) // FALSE POSITIVES: legitimate HR/IT provisioning tools performing bulk directory sync can trigger $top=999 pulls // TUNING: allowlist known SCIM/HRIS provisioning app IDs (e.g. Workday or HiBob connector service principals) that legitimately enumerate all users // LOOKBACK: 30d #repo = graph_activity_logs | requestUri = /\/v1\.0\/users/i | requestUri = /(payroll|human|resources|finance|admin)/i | requestUri = /\$skiptoken/i | table([@timestamp, userPrincipalName, appId, requestUri, userAgent, ipAddress]) | sort(@timestamp, order=desc)
Looks for: an OAuth application consent grant carrying broad mail/directory delegated scopes — the persistence path SRA flagged as surviving password reset and MFA re-registration. FP: legitimate first-time SSO app onboarding also generates consent-grant events; correlate with Q3/Q4/Q5 hits for the same user.
// HUNT: OAuth application consent grant with broad delegated mail/directory scopes (post-AiTM persistence) // MITRE: T1098.003 (Account Manipulation: Additional Cloud Roles), T1550.004 // CONF: medium // FP: medium // COST: low // REQUIRES: azure_auditlogs (Entra ID audit log) // ⚠ Field unverified — validate in tenant: activityDisplayName, initiatedBy ("targetResources.modifiedProperties.newValue" is documented in this skill's canonical field table; the other two are not — confirm against a live sample event) // FALSE POSITIVES: legitimate first-time SSO app onboarding also generates consent-grant audit events // TUNING: correlate consent-grant events against users flagged by Q3/Q4/Q5 in the same session window; exclude pre-approved enterprise app IDs from an admin-maintained allowlist // LOOKBACK: 30d #repo = azure_auditlogs | activityDisplayName = /^(Consent to application|Add app role assignment|Add delegated permission grant)$/ | "targetResources.modifiedProperties.newValue" = /(Mail\.Read|Mail\.ReadWrite|full_access_as_app|Directory\.Read\.All|offline_access)/i | table([@timestamp, initiatedBy, activityDisplayName, "targetResources.modifiedProperties.newValue"]) | sort(@timestamp, order=desc)
Looks for: the one attack-chain step this pack can observe with native Falcon sensor telemetry — a managed device resolving one of the reported redirector/proxy domains. FP: near zero for exact-match domains, but the domain list is wave-specific and rotates quickly, so treat any hit as high-confidence while accepting the query itself will age out.
// HUNT: Managed-endpoint DNS resolution of known Payroll Pirates AiTM redirector/proxy domains // MITRE: T1566.002 (Phishing: Spearphishing Link), T1557 (Adversary-in-the-Middle) // CONF: medium // FP: low // COST: low // REQUIRES: Falcon sensor DnsRequest telemetry on the clicking endpoint. This is the ONLY attack-chain step visible to endpoint EDR in this pack (see Coverage Map, §15) — it fires only if the phishing link is opened from a Falcon-covered device; it does not cover BYOD/mobile clicks, and the AiTM session theft plus all post-compromise cloud activity are invisible to endpoint EDR entirely. // FALSE POSITIVES: near zero for an exact domain match // TUNING: refresh this domain list from current threat intel before each hunt run; do not rely on this query alone given domain rotation — pair with Q1-Q8, which cover the cloud-side stages that persist regardless of infrastructure rotation // LOOKBACK: 7d #event_simpleName = DnsRequest | DomainName = /^(idp\.keyreniao\.com|idp\.korminel\.com|idp\.kualabemo\.com|mslogin\.milocaroline\.com|msonline\.logicalineonline\.com|msauth\.monlinelogicaline\.com|office\.ofrecie\.com|bluegraintours\.com)$/i | table([@timestamp, ComputerName, UserName, DomainName]) | sort(@timestamp, order=desc)
CrowdStrike Custom IOA Recommendations
Honesty note: a classic Falcon Custom IOA is a behavioral indicator evaluated by the endpoint sensor. It does not apply to SaaS/identity telemetry (Q1–Q8), which lives in Falcon Next-Gen SIEM, not on an endpoint. For those, the correct promotion path is a Scheduled Search / Correlation Rule in Next-Gen SIEM feeding an alert or Falcon Fusion SOAR workflow — not a Custom IOA. Q9 (endpoint DNS) is the one query in this pack eligible for genuine Custom IOA / Custom IOC treatment.
Promote to Scheduled Search / Correlation Rule (Next-Gen SIEM)
| Query | Name | Rationale | Deployment path |
|---|---|---|---|
| Q1 | HUNT: Payroll Pirates AiTM - MailItemsAccessed Anomalous Client Pairing | CONF high, FP low — flagship detection; the specific ClientAppId/APIId pairing reported as absent from all legitimate traffic | Next-Gen SIEM → Scheduled Search → run every 15 min, page SOC on any hit |
| Q2 | HUNT: Payroll Pirates AiTM - Inbox Rule Hiding Payroll Mail | CONF high, FP low — high-fidelity fraud-staging signal | Next-Gen SIEM → Scheduled Search → run every 15 min, page SOC on any hit |
| Q3 | HUNT: Payroll Pirates AiTM - OfficeHome Error 90014 | CONF high, but FP medium — run hourly and route to Tier-1 triage queue rather than paging | Next-Gen SIEM → Scheduled Search, correlate with Q5 same-user hits before escalating |
| Q4 | HUNT: Payroll Pirates AiTM - Session Replayed Across IPs | CONF high, but needs 30-day benign-baseline tuning (§11) before promoting to a paging alert | Investigate-only until FP tuned, then Scheduled Search |
Keep Investigate-only (tune before promoting)
- Q5, Q6, Q8 — CONF medium and FP medium; run as scheduled hunts with analyst review rather than auto-paging until each has a documented 30-day benign baseline (§11).
- Q7 — depends on Graph activity logs being enabled at all; treat as Investigate-only until that ingestion gap (§5) is closed org-wide.
Q9 — genuine Custom IOA / Custom IOC candidate
Because Q9 runs against native Falcon sensor DnsRequest telemetry, the reported redirector/proxy domains can additionally be loaded as Custom IOC domain-block/detect entries (Falcon → Endpoint security → IOC Management) for immediate coverage, independent of the Scheduled Search. Given the domain-rotation caveat in Q9's tuning note, treat this as a short-lived tactical block, not a durable detection — refresh or expire it alongside the domain list.
Flagship alert package (Q1)
Scheduled Search Name: HUNT: Payroll Pirates AiTM - MailItemsAccessed Anomalous Client Pairing
Subject: 🚨 HUNT ALERT 🚨 — Payroll Pirates AiTM Mailbox Collection Detected (Possible Business Email Compromise)
Body: An Exchange Online mailbox was accessed using a ClientAppId/APIId pairing that source threat-intel reporting found in zero legitimate Outlook traffic. This pairing is associated with the active Payroll Pirates / Storm-2755 AiTM campaign, which steals live M365 session tokens (bypassing MFA) and then reads payroll, invoice, and banking-related mail. This is a mailbox-read event, not a login event — the account's session was very likely already compromised by the time this fired. Check the mailbox owner's role first (payroll/HR/finance = high urgency), then immediately move to §14's Isolate phase — do not wait for a password-reset confirmation, since a stolen session survives that action.
Investigation checklist:
- Confirm the ClientAppId/APIId pairing exactly matches
5d661950-3475-41cd-a2c3-d671a3162bc1/c999ed3e-27ae-4cb3-b3a2-46b056af63d3in the raw event — not a partial match. - Check
mailbox_owner_upnagainst your HR/payroll/finance group membership — escalate immediately if it matches. - Pivot to Q3/Q4/Q5 for the same UPN over the prior 24 hours to confirm the anomalous sign-in that preceded the mailbox read.
- Pivot to Q2 for the same UPN to check whether a fraud-staging inbox rule was also created.
- Pivot to Q8 for the same UPN to check for an OAuth consent grant made during the same window.
- Begin §14 Isolate phase (session/token revocation) immediately — do not wait for full investigation to complete.
- Notify Payroll/HR to freeze any pending direct-deposit or banking-detail change tied to this user for the suspected exposure window.
Pivot queries
>> YOU NEED: mailbox_owner_upn (from the alert) >> FILL IN: mailbox_owner_upn="REPLACE_WITH_UPN"
// Host/user-scoped: all mailbox access for this UPN in the last 24h #repo = o365_management_activity | operation = "MailItemsAccessed" | mailbox_owner_upn = "REPLACE_WITH_UPN" | table([@timestamp, client_ip, client_app_id, api_id, operation]) | sort(@timestamp, order=desc) // Environment-wide: frequency of this exact pairing across all mailboxes #repo = o365_management_activity | operation = "MailItemsAccessed" | client_app_id = "5d661950-3475-41cd-a2c3-d671a3162bc1" | api_id = "c999ed3e-27ae-4cb3-b3a2-46b056af63d3" | groupBy([mailbox_owner_upn], function=count(as=Hits), limit=500) | sort(Hits, order=desc)
Machine-Readable IOC Appendix
type,value,action,severity,expiration,description,tags domain,idp.keyreniao.com,detect,medium,2026-11-17,Payroll Pirates AiTM redirector domain,campaign:PayrollPirates-Storm2755 domain,idp.korminel.com,detect,medium,2026-11-17,Payroll Pirates AiTM redirector domain,campaign:PayrollPirates-Storm2755 domain,idp.kualabemo.com,detect,medium,2026-11-17,Payroll Pirates AiTM redirector domain,campaign:PayrollPirates-Storm2755 domain,mslogin.milocaroline.com,detect,high,2026-11-17,Payroll Pirates AiTM authentication proxy,campaign:PayrollPirates-Storm2755 domain,msonline.logicalineonline.com,detect,high,2026-11-17,Payroll Pirates AiTM authentication proxy,campaign:PayrollPirates-Storm2755 domain,msauth.monlinelogicaline.com,detect,high,2026-11-17,Payroll Pirates AiTM authentication proxy,campaign:PayrollPirates-Storm2755 domain,office.ofrecie.com,detect,medium,2026-11-17,Payroll Pirates misspelled Office lookalike domain,campaign:PayrollPirates-Storm2755 domain,bluegraintours.com,hunt,medium,2026-11-17,Earlier Storm-2755 wave AiTM domain (Microsoft-attributed),campaign:PayrollPirates-Storm2755
MailItemsAccessed pairing: ClientAppId=5d661950-3475-41cd-a2c3-d671a3162bc1 + APIId=c999ed3e-27ae-4cb3-b3a2-46b056af63d3 Entra sign-in error 90014 on appDisplayName=OfficeHome Entra sign-in error 50199 (Login:reprocess) immediately preceding a successful sign-in (earlier wave) Single sessionId observed from 3+ distinct source IPs or 2+ countries Non-interactive sign-ins recurring on one sessionId every ~30min-8h from rotating IPs Microsoft Graph GET /v1.0/users?$top=999 followed by $search for payroll/hr/human/resources/finance/admin keywords with $skiptoken pagination New-InboxRule / Set-InboxRule parameters combining direct deposit|payroll|bank keywords with a delete/move-to-DeletedItems/mark-read action Subject line pattern: "[Organization] :ATTN: Review messages. Ref id: [random string]"
Firefox/131.0 (rv:131.0) reported as Outlook client Firefox/142.0 (rv:142.0) reported as Outlook client Python Requests (recurring session-maintenance activity) axios/1.18.1 (Microsoft Graph reconnaissance) axios/1.7.9 (earlier Storm-2755 wave AiTM client) server: openresty/1.31.1.1 (AiTM proxy / fingerprinting endpoint response header) x-powered-by: PHP/8.2.32 (fingerprinting endpoint response header) Fingerprinting endpoint path: /st_58200519/class_identifier.php
[ ] Microsoft Graph activity logging enabled and shipped to SIEM (off by default) [ ] Exchange Online mailbox auditing enabled tenant-wide, retention >= 90 days [ ] Conditional Access: phishing-resistant MFA (FIDO2/Windows Hello) enforced for payroll/HR/finance/admin roles [ ] Conditional Access: legacy authentication (IMAP/POP/SMTP AUTH) blocked tenant-wide [ ] Continuous Access Evaluation (CAE) in strict enforcement mode for Exchange Online / SharePoint [ ] Self-service OAuth application consent disabled (admin-consent workflow required) [ ] Sign-in frequency / session lifetime set to shortest tolerable value for high-risk roles [ ] HR/payroll platform (e.g. Workday) connected to a CASB or equivalent audit pipeline [ ] Break-glass account excluded from all above CA policies and tested
Detection Validation Gates
| Gate | Requirement | Status before deploying |
|---|---|---|
| Telemetry ready | Entra sign-in logs (interactive + non-interactive), Entra audit logs, O365 Management Activity/mailbox audit, and (for Q7) Graph activity logs must all be actively ingested into Falcon Next-Gen SIEM | Confirm per-repo with * | groupBy(#repo, limit=50) before relying on any query — Graph activity logs in particular are off by default |
| Benign baseline | Run each query over a known-clean 30-day window and confirm zero or near-zero hits | Required before promoting any query to a paging alert (§9) |
| Positive tests | AiTM cannot be safely replicated without violating defensive-only scope; validate query parsing and field mapping instead by confirming each field name against one real sample event per repo | A lab-controlled internal phish-simulation platform using a known test domain can validate Q9's DNS logic end-to-end without any offensive tooling |
| Promotion criteria | FP-low queries with a clean 30-day baseline → promote to Scheduled Search/Correlation Rule with SOC paging (§9). FP-medium queries stay Investigate-only until a documented exclusion set brings the baseline to near-zero | Re-evaluate quarterly — this campaign's infrastructure rotates and the underlying behavioral thresholds (IP counts, refresh cadence) may need retuning |
Hardening — Tiered & Deployable
- Enforce phishing-resistant MFA (FIDO2 security keys, Windows Hello for Business, or certificate-based auth) via Conditional Access authentication strength, at minimum for payroll/HR/finance/admin roles, ideally tenant-wide. MITRE M1032 (Multi-factor Authentication). CIS Entra ID Benchmark / Microsoft Secure Score — "phishing-resistant authentication methods required for privileged and finance-adjacent roles." Standard TOTP/push MFA does not stop this AiTM technique.
- Block legacy authentication (IMAP, POP, SMTP AUTH, older Exchange ActiveSync) tenant-wide via Conditional Access — these protocols have no MFA/CA enforcement path at all. MITRE M1032, M1042 (Disable or Remove Feature or Program). CIS Microsoft 365 Foundations Benchmark — "Ensure legacy authentication is blocked."
- Enable Continuous Access Evaluation (CAE) in strict enforcement mode and shorten sign-in frequency for Exchange Online/SharePoint, to shrink the usable lifetime of a stolen session token. MITRE M1036 (Account Use Policies). Microsoft Secure Score guidance.
- Purview audit search for recent New-InboxRule/Set-InboxRule activity matching payroll/bank/direct-deposit keywords, run immediately as a one-time sweep while the CQL detections (§8) are being validated. MITRE M1047 (Audit).
- Disable self-service OAuth application consent (require admin-consent workflow) — closes the persistence path that survives password reset and MFA re-registration. MITRE M1018 (User Account Management). CIS Entra ID Benchmark — "Ensure 'User consent for applications' is set to 'Do not allow user consent'."
- Enable Microsoft Graph activity logging and ship it to Falcon Next-Gen SIEM / a Security Datalake — without this, the entire reconnaissance stage (attack-chain step 6, Q7) is invisible. MITRE M1047 (Audit). Microsoft's own guidance on Graph Activity Log-based OAuth-abuse investigation.
- Conditional Access requiring a compliant or hybrid-joined device for access to Exchange Online/SharePoint from payroll, finance, and HR security groups. MITRE M1030 (Network Segmentation — cloud-access analog). CIS Microsoft 365 Foundations Benchmark.
- Connect the HR/payroll SaaS platform (e.g., Workday) to Defender for Cloud Apps or an equivalent CASB and alert on payment-election, bank-detail, and MFA-device-enrollment changes. MITRE M1047 (Audit).
- Conditional Access location/ASN and risk-based policies — build named-location baselines for normal business geography, and use Entra ID Protection sign-in-risk conditional access (block or step-up on High risk) to catch the residential-proxy pattern even as specific IPs rotate. MITRE M1030, M1032.
- Security awareness training specifically on voicemail-themed lures (fabricated caller ID/date/duration/reference number, "review your voicemail" framing), reinforced with a simulated phishing campaign using this exact lure template. MITRE M1017 (User Training).
- Formal incident-response runbook + tabletop exercise for AiTM session theft distinct from a standard credential-only BEC playbook, so first responders internalize that password reset alone does not remediate. MITRE M1056 (Pre-compromise).
Deployable Playbooks
Playbook A — Enforce phishing-resistant MFA + block legacy authentication
MITRE: T1557, T1078.004, T1550.004 → M1032, M1042 | Estimated deploy time: 2–4 hours plus a pilot ring | Prerequisites: Entra ID P1/P2 licensing, Microsoft Graph PowerShell SDK, Conditional Access administrator role, at least one break-glass account excluded and tested | Reboot required: No (tenant/cloud configuration only)
Step 1 — Require phishing-resistant MFA via Conditional Access authentication strength
What it does: Forces FIDO2/Windows Hello/certificate-based auth for sign-in, closing the gap that lets an AiTM proxy relay a TOTP or push approval. Why it works: Phishing-resistant methods are bound to the origin the user is actually talking to, so a proxy site cannot successfully complete the challenge on the attacker's behalf.
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess","Policy.Read.All"
$params = @{
displayName = "CA001-Require-PhishingResistantMFA-FinancePayrollHR"
state = "enabledForReportingButNotEnforced" # flip to "enabled" after pilot
conditions = @{
users = @{
includeGroups = @("REPLACE_WITH_PAYROLL_HR_FINANCE_GROUP_ID")
excludeUsers = @("REPLACE_WITH_BREAK_GLASS_ACCOUNT_OBJECT_ID")
}
applications = @{ includeApplications = @("All") }
}
grantControls = @{
operator = "AND"
authenticationStrength = @{ id = "00000000-0000-0000-0000-000000000004" } # built-in Phishing-resistant MFA strength
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params
Verify:
Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA001-Require-PhishingResistantMFA-FinancePayrollHR'" | Select-Object DisplayName, State
Rollback:
$policy = Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA001-Require-PhishingResistantMFA-FinancePayrollHR'"
Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -BodyParameter @{ state = "disabled" }
Compatibility note: pilot on the payroll/HR/finance group for 1–2 weeks in report-only mode before flipping to enabled, and confirm every pilot user has a registered FIDO2 key or Windows Hello for Business before enforcement — otherwise they lock themselves out.
Step 2 — Block legacy authentication tenant-wide
What it does: Denies sign-in for client types that cannot enforce Conditional Access or modern MFA at all. Why it works: Legacy protocols (IMAP/POP/SMTP AUTH/older ActiveSync) are a bypass lane around every control in Step 1 — closing it removes the attacker's fallback path.
$params = @{
displayName = "CA002-Block-LegacyAuthentication"
state = "enabledForReportingButNotEnforced"
conditions = @{
users = @{ includeUsers = @("All"); excludeUsers = @("REPLACE_WITH_BREAK_GLASS_ACCOUNT_OBJECT_ID") }
applications = @{ includeApplications = @("All") }
clientAppTypes = @("exchangeActiveSyncSupported", "other")
}
grantControls = @{ operator = "OR"; builtInControls = @("block") }
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params
Verify:
Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA002-Block-LegacyAuthentication'" | Select-Object DisplayName, State
Rollback:
$policy = Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA002-Block-LegacyAuthentication'"
Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -BodyParameter @{ state = "disabled" }
Compatibility note: audit legacy-auth sign-in volume for 7 days first (Entra sign-in logs, filter Client App = legacy) — some line-of-business scanners/printers/older scripts genuinely use IMAP/SMTP AUTH and need a scoped service-account exception before this goes tenant-wide.
Playbook B — Harden session controls and application consent
MITRE: T1550.004, T1098.003 → M1036, M1018 | Estimated deploy time: 1–2 hours | Prerequisites: Entra ID P2 licensing for CAE strict enforcement, Global Administrator or Authentication Policy Administrator role | Reboot required: No
Step 1 — Enforce strict Continuous Access Evaluation and shorten sign-in frequency
What it does: Forces near-real-time token revocation on risk signals and caps how long a replayed session stays useful. Why it works: Even if a token is stolen, CAE strict mode re-checks conditions continuously rather than trusting the token for its full lifetime, and a short sign-in frequency forces re-authentication (through the now phishing-resistant flow from Playbook A) on a tight cycle.
$params = @{
displayName = "CA003-StrictCAE-ShortSessionLifetime-ExchangeSharePoint"
state = "enabledForReportingButNotEnforced"
conditions = @{
users = @{ includeUsers = @("All"); excludeUsers = @("REPLACE_WITH_BREAK_GLASS_ACCOUNT_OBJECT_ID") }
applications = @{
includeApplications = @(
"00000002-0000-0ff1-ce00-000000000000", # Office 365 Exchange Online
"00000003-0000-0ff1-ce00-000000000000" # Office 365 SharePoint Online
)
}
}
sessionControls = @{
continuousAccessEvaluation = @{ mode = "strictEnforcement" }
signInFrequency = @{ value = 4; type = "hours"; isEnabled = $true; authenticationType = "primaryAndSecondaryAuthentication" }
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params
Verify:
Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA003-StrictCAE-ShortSessionLifetime-ExchangeSharePoint'" | Select-Object DisplayName, State
Rollback:
$policy = Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA003-StrictCAE-ShortSessionLifetime-ExchangeSharePoint'"
Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -BodyParameter @{ state = "disabled" }
Step 2 — Disable self-service OAuth application consent
What it does: Requires an administrator to approve any new application's delegated permissions rather than letting an already-compromised user grant them. Why it works: Closes the persistence path SRA documented — a consented app with broad mail/directory scopes survives password reset, session revocation, and MFA re-registration entirely, since it doesn't depend on the user's credentials at all.
Connect-MgGraph -Scopes "Policy.ReadWrite.Authorization"
# Primary control surface is the Entra Admin Center:
# Identity > Applications > Enterprise applications > Consent and permissions > User consent settings
# Set to "Do not allow user consent"
# Graph PowerShell equivalent (verify exact cmdlet/property names against your installed SDK version):
Update-MgPolicyAuthorizationPolicy -DefaultUserRolePermissions @{ PermissionGrantPoliciesAssigned = @() }
Verify:
(Get-MgPolicyAuthorizationPolicy).DefaultUserRolePermissions.PermissionGrantPoliciesAssigned # Expect: empty array (no self-service consent policies assigned)
Rollback:
Update-MgPolicyAuthorizationPolicy -DefaultUserRolePermissions @{ PermissionGrantPoliciesAssigned = @("ManagePermissionGrantsForSelf.microsoft-user-default-legacy") }
Compatibility note: disabling self-service consent will break any team's habit of clicking "Accept" on new SaaS integrations — pair this change with a published, fast admin-consent request process so it doesn't just push people toward workarounds.
Containment Runbook
| Phase | Actions | Owner | Evidence to preserve |
|---|---|---|---|
| Isolate (0–1 hr) | Revoke all refresh tokens and active sessions for the affected user via Entra Admin Center or Revoke-MgUserSignInSession — not password reset alone, which does not kill an already-issued token. Consider temporarily disabling the account if fraud risk is imminent. Notify Payroll/HR to freeze any pending direct-deposit or banking-detail change tied to the account. | IR lead / Identity admin | Sign-in logs, sessionId, timestamps of revocation actions |
| Eradicate (1–24 hr) | Reset credentials and re-register MFA methods (both required — session/token revocation is the critical action; credential reset alone is insufficient). Remove any malicious inbox rules found via Q2. Review and revoke any OAuth application consent grants added during the compromise window found via Q8 — this is a persistence path that survives the steps above. Add the observed AiTM redirector/proxy domains to the email gateway and secure web gateway blocklists. | Identity admin / Messaging admin | Removed inbox-rule definitions, revoked app-consent grant IDs, before/after MFA method registrations |
| Recover (24–72 hr) | Audit MailItemsAccessed for the full exposure window to scope exactly what was read. Audit the HR/payroll platform (e.g. Workday) for any direct-deposit/bank-detail changes during the window and revert unauthorized ones. Re-enable the account under enforced phishing-resistant MFA (Playbook A) and device-compliance Conditional Access. Assess breach-notification obligations if payroll/PII exposure is confirmed — Canadian organizations face PIPEDA and, for federally regulated financial institutions, OSFI B-13 reporting triggers. | IR lead / Payroll or HR / Legal-Compliance | MailItemsAccessed export, payroll/HRIS change log, notification decision record |
Do not close the incident on password reset alone. Confirm explicit session/refresh-token revocation succeeded (re-run Q4 for the user — the previously-flagged sessionId should stop generating new sign-ins) before considering the account clean.
Detection Coverage Map
| Technique | Behavior | CQL / IOA | Coverage |
|---|---|---|---|
| T1608.006 | SEO poisoning / malvertising initial staging | None — outside CrowdStrike's data model | GAP |
| T1566.002 | Voicemail-themed phishing link, multi-stage redirect | Q9 (DNS to known domains only) | Partial |
| T1557 / T1539 | AiTM proxy captures session token post-MFA | Q3, Q5 (downstream artifacts only — the proxy itself is cloud-side and invisible) | Partial |
| T1550.004 | Stolen session/token replayed from rotating proxies | Q4, Q6 | Good |
| T1078.004 | Continued access as the legitimate user | Q1, Q3, Q4, Q5, Q6 | Good |
| T1087.004 | Microsoft Graph payroll/HR/finance user enumeration | Q7 | Good (contingent on Graph activity logs being enabled — see §5 gap) |
| T1114.002 | MailItemsAccessed collection of invoice/payment/banking mail | Q1 | Good |
| T1564.008 | Inbox rule hiding payroll/bank mail | Q2 | Good |
| T1098.003 | OAuth consent grant persistence | Q8 | Partial (FP medium, needs tuning) |
| T1534 | Internal spearphishing via compromised mailbox | None dedicated — would surface as follow-on Q1/Q2 hits from the same mailbox | GAP |
| T1657 | Financial theft (redirected salary/direct-deposit) | None — HR/payroll platform audit is outside CrowdStrike's data model | GAP |
Overall: 6 of 11 mapped techniques have good CQL coverage, 3 have partial coverage from downstream artifacts, and 3 are structural gaps (email-gateway delivery stage, internal-spearphishing follow-through, and financial-platform impact) that sit entirely outside CrowdStrike's data model and require the mail-gateway, CASB, and HR-platform controls recommended in §12. All queries in §8 pass the validation gates in §11 before promotion to a paging alert; see §9 for the current promotion status of each.
Hunt Summary Ticket
TITLE: Payroll Pirates (Storm-2755) — M365 AiTM Session Hijack Targeting Payroll/Finance Mailboxes SEVERITY: HIGH (active, widespread, defeats standard MFA, direct financial-fraud follow-through) SCOPE: Microsoft 365 / Entra ID tenant-wide; specific priority on payroll, HR, finance, and admin mailboxes HYPOTHESIS: Voicemail-themed phishing routes victims through an AiTM proxy that steals a live, MFA-satisfied M365 session token. The attacker replays that token from rotating residential-proxy infrastructure to enumerate payroll/HR/finance staff via Microsoft Graph and read invoice/payment/banking mail, occasionally staging fraud via inbox rules or OAuth consent grants. QUERIES: Q1-Q9, see Section 8. Flagship: Q1 (MailItemsAccessed anomalous ClientAppId/APIId pairing, CONF high). DO FIRST: 1. Confirm telemetry readiness (Section 11) — Graph activity logs are OFF BY DEFAULT and block Q7 entirely. 2. Run Q1 and Q2 first (CONF high, FP low) over the last 30 days as a one-time sweep. 3. For any hit, pivot immediately to Q3/Q4/Q5/Q8 for the same user before beginning containment. FINDINGS: [populate at hunt time] GAPS: Email-gateway delivery stage, internal-spearphishing follow-through, and HR/payroll-platform impact are outside CrowdStrike's data model (Section 15) — coordinate with mail-gateway, CASB, and HRIS owners. ACTIONS: If any user confirmed compromised, begin Section 14 Isolate phase immediately. Password reset alone does NOT remediate — explicit session/refresh-token revocation is mandatory. OWNER: HuntPack / SOC on-call VERSION: v0.1 (Draft) — 2026-08-17