Detection

OAuth / workload-identity abuse detection

Four new detections shipped against OAuth and service-principal abuse: device-code phishing, credential-add persistence, vendor brand mimicry, and application-vs-delegated permission risk weighting.

Updated May 26, 2026 | 8 min

device_code_user_signin

Device-code OAuth flow used by user sign-in

Severity: HIGH · MITRE: T1528 + T1078.004

Why it matters: OAuth device authorization grant is designed for input-constrained devices and rarely originates from normal browser/desktop activity. Storm-2372 (Russian APT, Oct 2024) used it to phish access tokens — the victim is shown a legitimate-looking Microsoft device-code prompt and authorizes the attacker's session.

Fires when: A user (not a service principal) completes a successful sign-in with authenticationProtocol = "deviceCode".

Suppressed: None — device-code is rare enough that every instance is worth a look.

service_principal_credential_added

New credential added to existing service principal

Severity: HIGH / CRITICAL · MITRE: T1098.001

Why it matters: Storm-0558 / SolarWinds persistence pattern — attacker compromises an existing service account and adds a new client secret or certificate to maintain access. Diff-based detection fires regardless of whether Microsoft surfaced the change in directoryAudits.

Fires when: A new passwordCredential (secret) or keyCredential (certificate) appears on a service principal or application registration that already existed in the inventory.

Suppressed: Everything that existed before the connector detection baseline (a first sync into an established tenant is not 32 credential additions), entities younger than 7 days, a fingerprint first seen within an hour of its own inventory row, and both ITDR principals — the per-tenant connector app and the platform app.

unverified_publisher_brand_mimicry

Externally published application leads with a vendor brand it does not own

Severity: HIGH (CRITICAL only with linked posture findings) · MITRE: T1528

Why it matters: Consent-phishing pattern — an attacker publishes a multi-tenant app named Microsoft Outlook or DocuSign Login and asks a user to consent. Rewritten 2026-09-04: the rule previously read local application registrations, which by definition are apps the customer registered, so it could not see a consent-phished multi-tenant app at all while alerting on legitimate in-house integrations. It now reads service principals, where a consented foreign app actually appears.

Fires when: ALL FOUR must hold: the app is externally sourced (its owner organization proves a foreign tenant belonging to neither Microsoft nor the customer), the display name LEADS with the brand on a word boundary (impersonation leads with the brand; a legitimate integration names the service it integrates with, as in Crowdstrike NG SIEM MS Sharepoint Connector), it appeared after the connector baseline, and it holds high-risk permissions.

Suppressed: Microsoft first-party principals — recognised by owner organization, Microsoft-reserved appId ranges, publisher domain or verified publisher, so one missing field cannot expose them — plus in-house registrations and both ITDR principals. A missing owner organization means the app cannot be proven third-party, and suppresses rather than reading as suspicious.

permission_risk_split

Permission risk scoring split by application vs delegated

Severity: N/A — scoring change, not a new rule · MITRE: T1098.001 / T1078.004

Why it matters: The same Microsoft Graph scope carries different blast radius depending on grant type. Application "Mail.Read" lets a service principal read every mailbox tenant-wide non-interactively. Delegated "Mail.Read" only acts as the signed-in user, bounded by Conditional Access. The previous single marker set scored both equally.

Fires when: No new alert — but existing rules that look at "high-risk permissions" now use a stricter application-permission list (adds Mail.Read, Files.Read.All, User.Read.All, full_access_as_app). Findings on app-permission grants of those scopes will rank higher.

Suppressed: N/A.

Operator actions

  1. Open /alerts and filter by category (device_code_user_signin, service_principal_credential_added, unverified_publisher_brand_mimicry). New alerts carry MITRE chips that link out to attack.mitre.org.
  2. For device-code alerts: confirm with the user that they intentionally completed a device-code authorization. If unexpected, revoke active sessions + refresh tokens for the identity, and review consent grants on the targeted application.
  3. For credential-add alerts: confirm with the application owner that the secret addition was authorized. If unauthorized, revoke the credential, rotate all other secrets on the same identity, and review recent sign-in activity for that SP.
  4. For brand-mimicry alerts: the app is externally published and leads with a brand it does not own. Review its consent grants on /applications, confirm no user was phished into approving it, then revoke OAuth consent and disable it.
  5. For permission scoring shifts: existing alerts on workload identities may move up the priority board. No action required — the scoring update is mechanical.

Scope and limits

  • Device-code detection requires the beta /auditLogs/signIns endpoint (authenticationProtocol field is not yet in v1.0). Switched to beta on 2026-05-26 as a hotfix.
  • Credential-add detection persists per-keyId fingerprints. This page previously claimed the 7-day entity-age gate suppressed the first-scan burst. It did not: on the application-registration path the gate compared against the Microsoft registration date, so a years-old app carrying a brand-new fingerprint passed it, and connector 35 produced 32 false credential-add alerts on 2026-09-03. Connectors now record a detection baseline, and everything at or before it is treated as pre-existing state.
  • Brand-mimicry ships with a curated list of ~17 vendor brands in services/detection_evaluator.py:_VENDOR_BRAND_MARKERS. Matching is anchored to the start of the display name rather than a substring search — the old substring match alerted on Onboardingmailermaneeshemail because it contains gmail.
  • The brand rule precision is argued from its preconditions, not measured: on a healthy tenant it should fire zero times, so there is no true-positive rate to quote yet.
  • These four detections are Microsoft-only at launch. Okta does not expose authenticationProtocol the same way, and Okta application catalog ingestion is deferred (Phase D).