first commit
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
---
|
||||
name: authentication-jwt
|
||||
description: JWT and OIDC security testing covering token forgery, algorithm confusion, and claim manipulation
|
||||
---
|
||||
|
||||
# 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.
|
||||
Reference in New Issue
Block a user