JSTGTECH
← Back to blog

Storm-0558: When a Stolen Signing Key Forges Any Token

3 min read

Most breach write-ups end with a stolen password or a missed patch. Storm-0558 is different, and more instructive for anyone who runs an identity provider or validates tokens: the attackers never logged in. They forged the proof of login. In mid-2023 a China-based actor that Microsoft tracks as Storm-0558 used an acquired signing key to mint authentication tokens and read mailboxes at roughly 25 organizations, including US government agencies.

What happened

Per Microsoft’s own account and its later root-cause post, the actor obtained an inactive signing key for Microsoft’s consumer accounts (MSA). Using it, they forged tokens that Exchange Online accepted as if they were issued for enterprise Azure AD users. They then called the Outlook Web Access API directly, with no password and no MFA prompt.

Two failures had to line up:

  • Key custody. Microsoft’s investigation concluded the key most likely leaked via a 2021 crash dump that should have been scrubbed of key material but wasn’t, and that ended up in a debugging environment. An engineer’s corporate account was later compromised. Microsoft said it could not confirm that path with certainty because of missing logs.
  • Validation flaw. A library issue meant Exchange Online accepted tokens signed with the consumer key for enterprise identities. A key that should never have been trusted for that audience was.

The US Cyber Safety Review Board later called the intrusion preventable and criticized Microsoft’s security culture and its public statements about the root cause.

How it was caught

Not by the vendor. A customer noticed. The State Department detected anomalous mail access using the MailItemsAccessed audit event, which at the time was only available at a premium licensing tier. The intrusion had run for about a month by then. The lesson transfers directly: the logs that catch a forged-identity attack are often the ones locked behind the expensive plan. Microsoft has since expanded access to that logging.

Blast radius

A signing key is a root of trust. Compromising it is not “one account” or “one tenant”; it is every identity the verifier will accept for that key. The attacker only needed to know a target’s identity, not touch it. Because the tokens were valid, nothing downstream of the validator could tell the difference. That includes SIEM rules keyed on failed logins, impossible travel, or MFA challenges, none of which fire when no authentication happens.

What this means for AWS and cloud builders

You probably don’t run Exchange, but the pattern applies to anything that signs or verifies tokens:

  • Your own JWT/OIDC issuers. If you mint tokens for internal services, the signing key deserves the same protection as a root credential. Keep it in a KMS or HSM-backed service where it cannot be exported, rather than a file or environment variable that can land in a crash dump or backup.
  • OIDC trust to AWS. IAM roles trusted via an OIDC provider (GitHub Actions, EKS IRSA) rely on the issuer’s signing keys. Constrain trust policies with sub and aud conditions so a forged or misdirected token still has to match a specific subject. See my GitHub Actions OIDC tutorial for the condition keys.
  • Audience and issuer checks. The Microsoft bug was a verifier trusting a key for the wrong population. Validate iss, aud, and key-to-tenant binding explicitly; “signature is valid” alone is not enough.

Remediation checklist

  1. Inventory signing keys. List every system that issues tokens, SAML assertions, or signed URLs, and where each private key lives.
  2. Move keys to non-exportable storage (KMS asymmetric keys, HSM) and restrict kms:Sign to the issuing service role.
  3. Rotate on a schedule, and practice emergency rotation. Retire old keys fully; an “inactive” key that still validates is a liability, which is exactly what happened here.
  4. Scrub diagnostics. Treat crash dumps, core files, and debug snapshots as secret-bearing. Restrict where they are stored and who can open them.
  5. Turn on the high-fidelity audit logs now, including object and mailbox access events, and alert on access with no matching sign-in event.
  6. Detect authentication without a login. Correlate API calls with a preceding interactive or token-exchange event. Access with no origin is the signature of forged credentials.

Takeaway

Storm-0558 shows that identity security is only as strong as the least-guarded signing key and the least-careful validation check. Assume a key will leak someday, then design so the leak is detectable, bounded to a narrow audience, and fast to rotate.

Related posts