8.2 KiB
name, description
| name | description |
|---|---|
| oauth | OAuth 2.0 and OIDC flow security testing covering redirect manipulation, token leakage, PKCE bypass, and client misconfiguration |
OAuth 2.0 / OIDC
OAuth and OIDC failures often enable account takeover, token theft, and cross-client token confusion. Treat every redirect, client identifier, and token exchange as an authorization boundary — not a convenience layer.
Attack Surface
Flows
- Authorization code (with/without PKCE)
- Implicit (legacy), hybrid, device authorization, client credentials
- Refresh token rotation, token introspection, revocation
Endpoints
/authorize,/token,/userinfo,/introspect,/revoke,/logout/.well-known/openid-configuration,/jwks.json- Dynamic client registration (if enabled)
Token Types
- Authorization codes, access tokens, refresh tokens, ID tokens
- Opaque vs JWT formats; reference tokens vs self-contained JWTs
Client Types
- Public clients (SPAs, mobile) vs confidential (server-side)
- Multiple redirect URIs, wildcard/pattern matching, custom URI schemes
Reconnaissance
Discovery
GET /.well-known/openid-configuration
GET /oauth2/.well-known/openid-configuration
GET /.well-known/oauth-authorization-server
Extract: authorization_endpoint, token_endpoint, registration_endpoint, supported response_types, code_challenge_methods_supported, grant_types_supported.
Client Enumeration
- Inspect JS bundles, mobile APK/IPA configs, GitHub repos for
client_id, redirect URIs, scopes - Check error messages for client validation hints ("invalid redirect_uri", "unregistered client")
Key Vulnerabilities
Redirect URI Manipulation
Open Redirect Chains
- Register or guess permissive redirect patterns:
https://app.com/callback, path-prefix only, subdomain wildcards - Test: append paths, fragments, query injection,
@tricks, encoded slashes, backslash variants
https://app.com/callback.evil.com
https://app.com/callback%2f..%2f@evil.com
https://app.com/callback?next=https://evil.com
com.app://callback (mobile custom scheme)
Redirect URI Validation Bypasses
- Trailing slash, case, port, scheme downgrade (
httpvshttps) - Path normalization differentials between IdP validator and consuming app
redirect_uriparameter pollution (first vs last wins)- Wildcard subdomain acceptance:
*.app.com→ registerattacker.app.comor find dangling subdomain
Authorization Code Issues
Code Leakage
- Codes in URL fragments, Referer headers, browser history, server logs, analytics
- Code replay before expiry; missing one-time-use enforcement
- Code sent to wrong redirect_uri if binding is weak
Code Injection / Mix-Up
- Attacker initiates flow, victim completes login, code delivered to attacker's redirect
- Mix-up attack: swap
client_idbetween authorize and token steps - Missing
redirect_uribinding at token endpoint
State and Nonce
- Missing, predictable, or reusable
state→ CSRF on OAuth login (session fixation, account linking) - Missing
noncein OIDC → ID token injection/replay statenot bound to client session or PKCE verifier
PKCE Bypass
code_challenge_methoddowngrade: acceptplaininstead ofS256- Missing PKCE requirement on public clients
code_verifiernot validated or compared case-insensitively with weak matching- Authorization code issued without challenge, token endpoint accepts any verifier
Client Authentication
Public Client Abuse
- Token endpoint accepts requests without
client_secretfor confidential clients client_idonly authentication on token/introspection endpoints- Dynamic registration with attacker-controlled redirect URIs
Secret Leakage
- Hardcoded secrets in mobile apps, SPAs, or public repos
client_secretaccepted in query string or logged in access logs
Scope and Token Issues
- Scope escalation: request
admin/offline_access/openid profile emailbeyond app need; server grants all requested scopes - Refresh token not rotated or reuse not detected → persistent access
- Access token accepted across services (missing audience/resource binding)
- Token introspection returns
active:truewithout proper auth on introspection endpoint
OpenID Connect Specific
- ID token accepted as access token at resource servers (token confusion)
acr,amr,auth_timenot validated for step-up requirements- Userinfo endpoint returns PII without matching access token scope
subcollision across issuers ifissnot validated
Advanced Techniques
Referer Leakage
- Embed authorized redirect as subresource on attacker page; harvest
codefrom Referer if policy allows
Device Flow Abuse
- Poll
device_codeendpoint with guessed codes; slow rate limits only - User approves attacker-initiated device login
Account Linking
- OAuth login links attacker's IdP identity to victim's local account without re-auth
- Email collision: same email from different IdP providers
Testing Methodology
- Map flows — Identify all grant types, clients, and redirect URIs in use
- Redirect matrix — For each client, fuzz redirect_uri validation with encoding and parser tricks
- CSRF — Initiate OAuth without
state; swap sessions mid-flow - PKCE — Replay codes with wrong/missing verifier; downgrade challenge method
- Token exchange — Swap codes/tokens between clients; test cross-audience acceptance
- Mobile/deep links — Custom schemes, intent filters, universal links hijacking
Validation
- Demonstrate stolen authorization code or token via redirect manipulation or Referer leak
- Show account takeover or access to victim resources with attacker's OAuth session
- Prove CSRF: victim completes login into attacker's linked session without consent UI bypass where applicable
- Document exact validation gap (redirect binding, PKCE, state, audience)
- Provide full authorize → callback → token request chain with before/after evidence
False Positives
- Redirect URI rejected consistently across all bypass attempts
- Public client correctly requires PKCE S256 with strict verifier validation
state/nonceenforced and bound; CSRF test fails as expected- Token audience/issuer correctly validated at resource server
- Custom scheme redirects require app ownership proof (verified Android/iOS app links)
Impact
- Full account takeover via stolen authorization codes or tokens
- Persistent access through refresh token theft
- Cross-tenant or cross-client data access via token confusion
- PII exposure from userinfo or ID token claim leakage
Pro Tips
- Always capture the full redirect chain including intermediate 302 locations
- Compare authorize-step and token-step parameter binding (
redirect_uri,client_id, PKCE) - Test both web and mobile clients — validation rules often differ
- Check logout/revocation — tokens may remain valid after "logout"
- Chain with open redirect or XSS on the legitimate redirect_uri to exfiltrate codes
Tooling
The sandbox ships jwt_tool (already cloned at /home/pentester/tools/jwt_tool) plus curl — enough for the token side of OAuth/OIDC.
- jwt_tool (ticarpi) — inspect and tamper ID tokens / JWT access tokens:
alg:none,HS256/RS256key confusion,kidinjection, claim editing (sub,aud,iss,exp):python3 /home/pentester/tools/jwt_tool/jwt_tool.py <ID_TOKEN> # decode/inspect python3 /home/pentester/tools/jwt_tool/jwt_tool.py <ID_TOKEN> -X a # alg:none python3 /home/pentester/tools/jwt_tool/jwt_tool.py <ID_TOKEN> -X k -pk pub.pem # RS256->HS256 confusion - curl — drive the authorize → callback → token chain by hand so you control every parameter (
redirect_uri,client_id,state, PKCEcode_challenge/code_verifier) and can test the binding/downgrade cases above.
Humans often use Burp's EsPReSSO (RUB-NDS) SSO extension for flow visualization; it is GUI-only, so prefer manual curl + jwt_tool in-sandbox.
Summary
OAuth security hinges on strict redirect URI binding, unguessable state/nonce, PKCE for public clients, and consistent token audience validation. Any gap in the authorize-to-token chain is a potential account takeover.