One bearer token, replayed from a residential proxy
How attackers abuse OAuth 2.0 at scale via consent phishing, device code flow, and service principal credentials - and why endpoint EDR sees none of it.
OAuth 2.0 is an authorization framework, defined in RFC 6749. It is not authentication, though most deployments treat it as both. The output of every flow is a bearer token. Whoever presents a valid bearer token is the authorized principal - as far as the resource server is concerned. No password check at the API boundary. No second factor on replay. The token is the access. That is the design. That is the class attackers work at scale.
The mechanism is delegated authorization. A client application requests scopes. The user authenticates to the authorization server and consents to those scopes. The authorization server issues an access token and, when offline_access is requested, a refresh token. The resource server validates the token signature and claims, then serves data. The trust boundary sits at the token, not the caller. A resource server does not know or care where the token came from. Replayed from a residential proxy in another country, it is honored until expiry or explicit revocation. Access tokens live for roughly an hour by default in Entra ID. Refresh tokens tied to offline_access persist far longer, and rotation is optional configuration that is routinely left off.
The secrets holding this together fail in predictable places. Confidential clients authenticate to the token endpoint with a client_id and client_secret. Public clients - single-page apps, mobile - cannot hold a secret, so PKCE (RFC 7636) is meant to bind the authorization request to the token exchange. Where PKCE is absent on a public client, an intercepted authorization code is redeemable by anyone who holds it. Where redirect_uri validation uses wildcards or tolerates an open redirect on the registered domain, the code is exfiltrated to an attacker-controlled endpoint mid-flow. These are configuration failures in the client registration, not memory-corruption bugs. There is no crash. There is no patch. There is a token in the wrong hands.
The scope model widens the blast radius on its own. OAuth scopes are coarse. Mail.Read grants every message in a mailbox, not a folder. Directory.Read.All exposes the entire tenant directory. Files.Read.All reaches every SharePoint and OneDrive document the user can see. A single consent to a broadly-scoped delegated permission hands the application the union of the user’s access, and applications routinely request more than they use, because narrower scopes mean more consent prompts and more friction. Where administrators have enabled user consent for verified publishers, a well-formed request from an app with a spoofed or purchased publisher identity clears with no admin in the loop. The consent decision is delegated to the least-equipped party in the tenant.
The highest-yield path requires no bug at all. Illicit consent grant, MITRE T1566 into T1528. The attacker registers a multi-tenant OAuth application. They craft a consent URL requesting scopes such as Mail.Read, Files.Read.All, and offline_access. The victim receives the link, authenticates to the genuine Microsoft or Google login page - real domain, valid TLS, MFA satisfied by the legitimate user - and clicks accept. The authorization server issues a refresh token to the attacker’s application. No credential was stolen. No MFA was bypassed. The victim performed the authentication, and the grant persists after the victim’s next password reset. The attacker’s app reads the mailbox through Microsoft Graph until an administrator revokes the grant.
Device code phishing is the variant that scaled through 2025. The device authorization grant, RFC 8628, exists for input-constrained devices. The attacker initiates the device code flow and relays the resulting user_code and verification URL to the target, framed as a login prompt. The target enters the code on the legitimate microsoft.com verification page and completes MFA. The attacker polls the token endpoint and receives an access token and refresh token bound to the target’s identity. Microsoft attributed an active campaign using this exact technique to Storm-2372 in February 2025, a Russia-aligned actor hitting government, NGO, and telecom accounts. The flow is the payload. The token issuance is legitimate at every step, which is why it survives contact with MFA.
The persistence path lives on the application side. T1098.001, adding credentials to an existing service principal. An attacker with a foothold in the tenant adds a new client secret or certificate to an enterprise application that already holds broad permissions. The application then authenticates as itself, with app-only permissions such as full_access_as_app to Exchange Online, and its access survives every user password reset in the tenant. This is the Midnight Blizzard intrusion Microsoft disclosed in January 2024. Entry was a password spray, T1110.003, against a legacy non-production test tenant account with no MFA. From there the actor located an OAuth application with elevated Exchange access, created additional malicious OAuth applications, granted them full_access_as_app, and exfiltrated corporate and executive mailboxes. The initial account was low value. The OAuth grant was the objective.
Tokens are also stolen downstream, after issuance. In April 2022, attackers used OAuth tokens issued to Heroku and Travis CI integrations to clone private repositories across dozens of organizations, including npm. T1550.001, application access token. The tokens were valid, scoped, and trusted. The compromise was the integration, not the identity provider. In October 2023, Okta’s support case system was accessed and session tokens were lifted from HAR files that customers had uploaded for troubleshooting. T1539, steal web session cookie. A HAR capture of an authenticated session contains the bearer material verbatim. Replayed, it reconstitutes the session with no login and no prompt.
There is a code-level failure class as well, separate from configuration. CVE-2021-22573, Google OAuth Client Library for Java before 1.31.5, CVSS 8.7. The IDTokenVerifier did not verify the cryptographic signature on the token. A forged ID token carrying attacker-chosen claims - issuer, audience, subject - was accepted as valid. Any service that used the library to gate identity would treat the forged assertion as a genuine login. The fix landed in 1.31.5, a clean dependency bump. Unlike consent abuse, this one has a patch boundary and a version delta a defender can pin to.
In telemetry, the identity plane carries the signal, and most SOCs are not watching it. In Entra ID, consent generates audit events - “Consent to application,” “Add delegated permission grant,” “Add OAuth2PermissionGrant.” Credential addition to an app generates “Update application - Certificates and secrets management” and “Add service principal credentials” in the unified audit log. Application sign-ins are recorded in the service principal sign-in log, a separate stream from the interactive user sign-in log that analysts default to. Okta writes app.oauth2 grant and token issuance events to its System Log. The events exist. The gap is that they are not correlated, and the app-only sign-in stream is frequently unmonitored entirely.
What does not fire is more instructive. There is no failed authentication, because authentication succeeded. There is no impossible-travel alert when the token is replayed through a residential proxy in the victim’s own region. There is no MFA prompt, because MFA was satisfied at consent. Endpoint telemetry sees nothing - no Sysmon Event ID 1 process creation, no binary on disk, no C2 beacon on the host. The action occurs entirely between the identity provider and the resource server, over TLS to graph.microsoft.com or an equivalent API endpoint, indistinguishable at the network layer from sanctioned traffic. EDR is blind because there is no endpoint in the path. The exploitation is API calls carrying a valid token.
A working detection keys on the grant, not the sign-in. New service principal credential additions, correlated against a baseline of expected app registrations. First-seen application IDs consenting to high-value scopes. Refresh token redemption from an ASN or client that has never appeared for that identity. The sudden appearance of app-only Graph reads spanning many mailboxes from a single service principal. These are audit-log and sign-in-log correlations, not endpoint rules, because the endpoint is not in the path. The detection work shifts from EDR to identity provider logs, and the teams that own those logs are often not the teams running the SOC.
The residual exposure is structural. CVE-2021-22573 has a fix in 1.31.5, and signature-verification bugs like it close when the dependency is bumped. Consent phishing, device code phishing, and service principal credential addition have no patch, because nothing is broken in the protocol - it is executing as specified. Post-remediation, the exposure that remains is the token itself. Refresh tokens already issued stay valid until explicitly revoked. Revocation is not automatic on password reset for application tokens, and a reset that feels like remediation leaves the attacker’s grant untouched. access not constrained at runtime evaluation shortens the replay window where it is enabled, and it is not enabled everywhere. The token outlives the credential that authorized it. Anyone hunting OAuth abuse hunts grants and service principal credentials, not passwords.
See also: NordVPN for tunneled traffic when operating outside controlled networks.
#ad Contains an affiliate link.
Keep Reading
session-hijackingVectra lifted bearer tokens off Teams disk
Why Microsoft Teams session tokens leak between workspace and consumer accounts, how bearer-token replay bypasses MFA, and what fires - and doesn't - in telemetry.
linux-securitydd writes raw sectors below the filesystem
Why the Unix dd command is a real security primitive: raw block writes below the filesystem, wiper TTPs, exfiltration, and the telemetry gap defenders miss.
linux-securityhtop is a reconnaissance surface
How htop and top expose Linux resource contention - OOM-killer steering, D-state telemetry gaps, niced miners, and PID exhaustion mapped to MITRE T1562 and T1499.
Stay in the loop
New writing delivered when it's ready. No schedule, no spam.