Runbook: JWT attacks¶
JSON Web Tokens carry their own claims and a signature that is supposed to make those claims tamper-evident. Most JWT findings come from a verifier that trusts something it has no reason to: an attacker-chosen algorithm, an attacker-supplied key, or a signature it never checks. This runbook is the deep-dive companion to the JWT phase in the authentication runbook, working through each verification flaw in turn.
Prerequisites¶
A valid token captured during the recon or authentication pass.
Burp Suite with the JWT Editor extension, or jwt_tool on the command line.
The token’s decoded header and payload, and the endpoint that reflects privilege (an admin panel or a
GET /my-accountstyle response works well as an oracle).
Phase 1: Find and decode tokens¶
Search proxy history for the eyJ prefix that marks a base64url-encoded JWT header:
"[= ]eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9._-]*"
Decode the header and payload. Note the alg, any kid, jku, or jwk header, and the
claims that carry identity (sub, role, is_admin, email). Confirm the token is
actually used for an access decision before spending time on it: a token that changes
nothing when removed is not worth attacking.
Phase 2: Missing or flawed signature verification¶
The cheapest wins come from a verifier that does not check the signature at all, or checks it only when present.
Send the token with the payload modified (for example
subset to an admin user) and the signature left intact. If access changes, the signature is not being verified.Set the
algheader tononeand strip the signature entirely (keep the trailing dot). A verifier that honoursnoneaccepts the unsigned token.
jwt_tool TOKEN -X a # alg:none variants
Phase 3: Weak signing key¶
When the token uses HMAC (HS256), the signature is only as strong as the secret. Brute force it offline against a wordlist:
hashcat -a 0 -m 16500 TOKEN /usr/share/wordlists/jwt.secrets.list
jwt_tool TOKEN -C -d /usr/share/wordlists/rockyou.txt
A recovered secret lets arbitrary tokens be forged. Re-sign a modified payload with it and replay.
Phase 4: Header injection (jwk, jku, kid)¶
These attacks make the verifier trust a key the attacker controls.
jwk: embed a self-generated public key in the token’s
jwkheader. A verifier that uses the embedded key rather than its own trusted key accepts a token signed with the matching private key.jku: point the
jkuheader at an attacker-hosted JWK Set. If the verifier fetches keys from that URL without restricting it to a trusted origin, it verifies against the attacker’s key. Thejkuvalue is also an SSRF probe in its own right.kid: the
kidheader selects which key to use. Where it feeds a file lookup, try path traversal to a predictable file (../../../../dev/nullyields an empty key, so an empty HMAC secret signs the token). Where it feeds a query, test for SQL injection returning a known value as the key.
Phase 5: Algorithm confusion (RS256 to HS256)¶
When tokens are signed with RSA (RS256) and the public key is obtainable, a verifier that does not pin the algorithm can be tricked into verifying an HS256 token using the RSA public key as the HMAC secret.
Obtain the public key. Many servers expose it at a standard JWK Set endpoint:
curl https://target.com/jwks.json
curl https://target.com/.well-known/jwks.json
Convert the JWK to PEM (the JWT Editor’s New RSA Key dialogue imports the JWK and exports PEM; jwt_tool can derive it too). Where no key is published, two captured tokens are enough to recover the modulus.
Forge the token: set
algtoHS256, modify the identity claim, and sign with HMAC using the PEM public key as the secret.
jwt_tool TOKEN -X k -pk public.pem
Replay against the privileged endpoint. Success confirms the server is verifying the attacker’s HS256 signature with its own public key.
Output¶
Which verification flaw applies (unverified signature, alg:none, weak key, header injection, algorithm confusion).
The forged token and the privileged action it enabled.
For jku and kid findings, any secondary SSRF or injection reached through the header.
Techniques¶
Counter moves¶
Runbook: JWT attacks is what this page works through. Pinning the algorithm, verifying signatures against a trusted key, and rejecting attacker-supplied key material are the counters. Defenders’ notes on this are under the surface designed to be accessible.