Nobody Broke In. Your Apps Signed Them In.

There was no break-in to detect. No password sprayed, no user phished, no MFA prompt fatigued into an approval. Starting November 1, an operator has been walking into Microsoft 365 and Azure environments the legitimate way: signing in as the organizations’ own app registrations, with their real secrets, and being welcomed as a trusted workload. The MXDR team tracking the campaign reports roughly 45 app registrations targeted across about 18 organizations, more than 33 authenticating successfully — and through those apps, 27 organizations reached, including the downstream clients those apps were built to serve. If your tenant runs on app registrations and client secrets — and every MSP tenant does — this is your threat model now.

What happened, in numbers

The targets were managed service providers, which is precisely why the blast radius is so wide. The victims span government, energy, food and agriculture, transportation, construction and engineering, legal, education, and nonprofits — most never touched directly, but reached through the MSP apps that manage them. Across about 25 tenants, the operator ran 29 single-wildcard Microsoft Graph searches, downloaded 81 files, and accessed roughly 2,279 mailbox items. No Microsoft vulnerability was involved at any point: the secrets were stolen, still valid, and accepted exactly as designed. And these numbers are a floor — they only cover organizations whose logs the tracking team can see.

Why workload identities are the soft target

User accounts have spent a decade getting harder: MFA, Conditional Access, risk policies, impossible-travel alerts. Service principals got none of that attention. Client secrets sit in config files, pipelines, and vaults for years, often with validity windows far longer than anyone remembers approving. And MFA does not apply to an app-only sign-in: no user to challenge, no prompt to approve, no baseline anyone watches. The app authenticates, the token is issued, and the audit log records a perfectly ordinary event.

Then there is the MSP multiplier. A multi-tenant app registration is a skeleton key by design: one app, consented across every client tenant it manages. Compromise one secret and you inherit the whole book of business. In this campaign, a single multi-tenant app swept 15 client tenants in loops of about ten seconds, with Partner Center and delegated-admin (GDAP) apps providing the roads between tenants. The trust architecture that makes MSP tooling efficient is the same one that made this campaign fast.

The attack chain, step by step

  1. Sign in as the app. Entry came through stolen client secrets — some apparently taken as current-and-expired pairs, suggesting a file store or live backend as the source. The operator also abused an Azure DevOps federated workload identity and replayed a real user’s Azure DevOps session token.
  2. Harvest the next credentials. For nearly every app, the operator requested an Azure Resource Manager token and then, within seconds, a Key Vault token. Minutes later, apps that had never authenticated before started signing in. In one case, a downloaded connector archive was turned around and its own app was signing in about two and a half minutes later.
  3. Search and collect. Single-wildcard Graph searches mapped the tenant, then bulk SharePoint downloads ran at about one file per second — aimed at credential and configuration material: password lists, private keys, VPN profiles, MFA and RMM API keys, backup credentials, firewall and RDP configurations.
  4. Reach downstream. Multi-tenant apps, GDAP relationships, and Partner Center tokens carried the operator into client tenants with no new intrusion.
  5. Adapt under pressure. Scripted clients drove 95% of sign-ins, in bursts of up to 24 sign-ins in 10 seconds with retry loops of about 11 seconds. When detections fired on November 3, the tooling switched from curl and Python user agents to spoofed browser ones, and later replayed stolen user refresh tokens — Conditional Access blocked every replay. Notably, the operator set up no persistence: no new consents, credentials, roles, or users.

What to hunt for

  • The operator’s IP. 199.19.77.84 accounts for 412 sign-in attempts in seven days — app sign-ins, downloads, and token replays. Check your logs for it today.
  • Distinctive user agents. task177-f2267/1.0 and sait-tenant-deep/37346 appear unique to this actor.
  • The secret-ID tell. Error AADSTS7000215 — a secret identifier presented without a credential type — followed within minutes by a successful sign-in for the same app from the same IP is the sound of someone testing a stolen secret before using it.
  • One IP, many tenants. A single source address authenticating as service principals across multiple unrelated organizations inside 24 hours is this campaign’s shape.
  • The token sequence. An ARM token immediately followed by a Key Vault token for the same app, then previously dormant apps authenticating within minutes, points at vault-driven credential harvesting.
  • Machine-speed collection. App-only SharePoint downloads at roughly one file per second, concentrated on credential- and config-named files, often right after a wildcard search.
  • Failures count too. Retry loops against disabled and rotated apps, and failed service-principal sign-ins from hosting-provider ranges, are invisible to detections keyed only on success.

What to hunt for: defender checklist for the workload identity campaign — the operator's IP 199.19.77.84, the user agents task177-f2267/1.0 and sait-tenant-deep/37346, error AADSTS7000215 followed by a successful sign-in, one IP across many tenants, the ARM-then-Key-Vault token sequence, machine-speed SharePoint downloads, and retry loops against disabled apps

What to do now

  • Inventory every app registration and secret. List all service principals, their credential types, and expiry dates. Anything with an over-age secret — or no owner who can explain it — goes to the top of the rotation list.
  • Rotate, then replace. Rotation alone is not enough; the operator keeps retrying old material and hunts for more. Move apps to federated credentials or certificates wherever supported, and treat long-lived client secrets as technical debt with a deadline.
  • Put Conditional Access on workload identities. CA is the control that blunted this campaign’s second act — every replayed user token died there. Create named locations for known-bad and hosting-provider ranges, block scripted workload sign-ins from them, and make sure policies cover service principals, not just users.
  • Turn on Key Vault diagnostic logging. The ARM-to-Key-Vault sequence is only visible if vault reads are logged. Alert specifically on a vault being read by an app that has never read it before.
  • Alert on the sequence, not the event. Single app sign-ins are noise. ARM token, then Key Vault token, then new apps authenticating, then bulk downloads is a story — build the correlation and page on it.
  • Mind the AI keys. Four AI-service tokens were issued at two of the MSPs, a classic LLMjacking setup. Prefer Entra authentication over API keys, rotate AI keys sitting in reachable vaults, and set quotas and spend alerts so a stolen key announces itself on the bill.
  • Audit your multi-tenant and GDAP surface. Know which apps can reach which client tenants, and prune consents nobody can justify. Every unnecessary tenant an app can touch is a tenant an attacker can touch with it.

The uncomfortable lesson is that nothing here failed. The secrets worked, the tokens were issued correctly, and the apps did what they were designed to do — for whoever held the credential. Defending users was the last decade’s project; defending the identities your workloads sign in with is this one’s. Start with the inventory: you cannot protect an app registration you forgot you had, and someone else may already have found it.

One thought on “Nobody Broke In. Your Apps Signed Them In.”

Comments

This site uses Akismet to reduce spam. Learn how your comment data is processed.