Back to Strix

Authentication / JWT / OIDC

strix/skills/vulnerabilities/authentication_jwt.md

1.0.28.1 KB
Original Source

Authentication / JWT / OIDC

JWT/OIDC failures often enable token forgery, token confusion, cross-service acceptance, and durable account takeover. Do not trust headers, claims, or token opacity without strict validation bound to issuer, audience, key, and context.

Attack Surface

  • Web/mobile/API authentication using JWT (JWS/JWE) and OIDC/OAuth2
  • Access vs ID tokens, refresh tokens, device/PKCE/Backchannel flows
  • First-party and microservices verification, gateways, and JWKS distribution

Reconnaissance

Endpoints

  • Well-known: /.well-known/openid-configuration, /oauth2/.well-known/openid-configuration
  • Keys: /jwks.json, rotating key endpoints, tenant-specific JWKS
  • Auth: /authorize, /token, /introspect, /revoke, /logout, device code endpoints
  • App: /login, /callback, /refresh, /me, /session, /impersonate

Token Features

  • Headers: {"alg":"RS256","kid":"...","typ":"JWT","jku":"...","x5u":"...","jwk":{...}}
  • Claims: {"iss":"...","aud":"...","azp":"...","sub":"user","scope":"...","exp":...,"nbf":...,"iat":...}
  • Formats: JWS (signed), JWE (encrypted). Note unencoded payload option ("b64":false) and critical headers ("crit")

Key Vulnerabilities

Signature Verification

  • RS256→HS256 confusion: change alg to HS256 and use the RSA public key as HMAC secret if algorithm is not pinned
  • "none" algorithm acceptance: set "alg":"none" and drop the signature if libraries accept it
  • ECDSA malleability/misuse: weak verification settings accepting non-canonical signatures

Header Manipulation

  • kid injection: path traversal ../../../../keys/prod.key, SQL/command/template injection in key lookup, or pointing to world-readable files
  • jku/x5u abuse: host attacker-controlled JWKS/X509 chain; if not pinned/whitelisted, server fetches and trusts attacker keys
  • jwk header injection: embed attacker JWK in header; some libraries prefer inline JWK over server-configured keys
  • SSRF via remote key fetch: exploit JWKS URL fetching to reach internal hosts

Key and Cache Issues

  • JWKS caching TTL and key rollover: accept obsolete keys; race rotation windows; missing kid pinning → accept any matching kty/alg
  • Mixed environments: same secrets across dev/stage/prod; key reuse across tenants or services
  • Fallbacks: verification succeeds when kid not found by trying all keys or no keys (implementation bugs)

Claims Validation Gaps

  • iss/aud/azp not enforced: cross-service token reuse; accept tokens from any issuer or wrong audience
  • scope/roles fully trusted from token: server does not re-derive authorization; privilege inflation via claim edits when signature checks are weak
  • exp/nbf/iat not enforced or large clock skew tolerance; accept long-expired or not-yet-valid tokens
  • typ/cty not enforced: accept ID token where access token required (token confusion)

Token Confusion and OIDC

  • Access vs ID token swap: use ID token against APIs when they only verify signature but not audience/typ
  • OIDC mix-up: redirect_uri and client mix-ups causing tokens for Client A to be redeemed at Client B
  • PKCE downgrades: missing S256 requirement; accept plain or absent code_verifier
  • State/nonce weaknesses: predictable or missing → CSRF/logical interception of login
  • Device/Backchannel flows: codes and tokens accepted by unintended clients or services

Refresh and Session

  • Refresh token rotation not enforced: reuse old refresh token indefinitely; no reuse detection
  • Long-lived JWTs with no revocation: persistent access post-logout
  • Session fixation: bind new tokens to attacker-controlled session identifiers or cookies

Transport and Storage

  • Token in localStorage/sessionStorage: susceptible to XSS exfiltration; cookie vs header trade-offs with SameSite/CSRF
  • Insecure CORS: wildcard origins with credentialed requests expose tokens and protected responses
  • TLS and cookie flags: missing Secure/HttpOnly; lack of mTLS or DPoP/"cnf" binding permits replay from another device

Advanced Techniques

Microservices and Gateways

  • Audience mismatch: internal services verify signature but ignore aud → accept tokens for other services
  • Header trust: edge or gateway injects X-User-Id; backend trusts it over token claims
  • Asynchronous consumers: workers process messages with bearer tokens but skip verification on replay

JWS Edge Cases

  • Unencoded payload (b64=false) with crit header: libraries mishandle verification paths
  • Nested JWT (JWT-in-JWT) verification order errors; outer token accepted while inner claims ignored

Special Contexts

Mobile

  • Deep-link/redirect handling bugs leak codes/tokens; insecure WebView bridges exposing tokens
  • Token storage in plaintext files/SQLite/Keychain/SharedPrefs; backup/adb accessible

SSO Federation

  • Misconfigured trust between multiple IdPs/SPs, mixed metadata, or stale keys lead to acceptance of foreign tokens

Chaining Attacks

  • XSS → token theft → replay across services with weak audience checks
  • SSRF → fetch private JWKS → sign tokens accepted by internal services
  • Host header poisoning → OIDC redirect_uri poisoning → code capture
  • IDOR in sessions/impersonation endpoints → mint tokens for other users

Testing Methodology

  1. Inventory issuers/consumers - Identity providers, API gateways, services, mobile/web clients
  2. Capture tokens - Access and ID tokens for multiple roles; note header, claims, signature
  3. Map verification endpoints - /.well-known, /jwks.json
  4. Build matrix - Token Type × Audience × Service; attempt cross-use
  5. Mutate components - Headers (alg, kid, jku/x5u/jwk), claims (iss/aud/azp/sub/exp), signatures
  6. Verify enforcement - What is actually checked vs assumed

Validation

  1. Show forged or cross-context token acceptance (wrong alg, wrong audience/issuer, or attacker-signed JWKS)
  2. Demonstrate access token vs ID token confusion at an API
  3. Prove refresh token reuse without rotation detection or revocation
  4. Confirm header abuse (kid/jku/x5u/jwk) leading to key selection under attacker control
  5. Provide owner vs non-owner evidence with identical requests differing only in token context

False Positives

  • Token rejected due to strict audience/issuer enforcement
  • Key pinning with JWKS whitelist and TLS validation
  • Short-lived tokens with rotation and revocation on logout
  • ID token not accepted by APIs that require access tokens

Impact

  • Account takeover and durable session persistence
  • Privilege escalation via claim manipulation or cross-service acceptance
  • Cross-tenant or cross-application data access
  • Token minting by attacker-controlled keys or endpoints

Pro Tips

  1. Pin verification to issuer and audience; log and diff claim sets across services
  2. Attempt RS256→HS256 and "none" first only if algorithm pinning is unclear; otherwise focus on header key control (kid/jku/x5u/jwk)
  3. Test token reuse across all services; many backends only check signature, not audience/typ
  4. Exploit JWKS caching and rotation races; try retired keys and missing kid fallbacks
  5. Exercise OIDC flows with PKCE/state/nonce variants and mixed clients; look for mix-up
  6. Try DPoP/mTLS absence to replay tokens from different devices
  7. Treat refresh as its own surface: rotation, reuse detection, and audience scoping
  8. Validate every acceptance path: gateway, service, worker, WebSocket, and gRPC
  9. Favor minimal PoCs that clearly show cross-context acceptance and durable access
  10. When in doubt, assume verification differs per stack (mobile vs web vs gateway) and test each

Tooling

  • jwt_tool -t <url> -rh "Authorization: Bearer <token>" -M at runs the full attack matrix (alg=none, RS→HS confusion, kid injection, claim edits) and reports which mutations the server still accepts.
  • jwt_tool <token> -C -d <wordlist> brute-forces HMAC secrets when an HS-family signature is in use.
  • Use jwt_tool to mint a token under a key you control once you find an acceptance path (kid/jku/x5u/jwk), then replay via repeat_request.

Summary

Verification must bind the token to the correct issuer, audience, key, and client context on every acceptance path. Any missing binding enables forgery or confusion.