JWT attacks
A JWT carries signed claims between parties; it’s heavily used for sessions and API authorization. Flaws appear when signature verification is weak or incorrect: the attacker then forges or tampers the token and becomes another user or an admin.
Threat model
Section titled “Threat model”Identity forgery (change sub/user), privilege escalation (set role: admin),
authentication bypass, and persistence if tokens don’t expire or aren’t revoked.
Anatomy
Section titled “Anatomy”Three Base64URL parts separated by dots: header.payload.signature.
- header: algorithm (
alg) and sometimeskid,jku,x5u,jwk. - payload: claims (
sub,role,exp,iss,aud…). - signature: HMAC (HS256) or asymmetric signature (RS256/ES256).
Security depends entirely on correctly verifying the signature and the expected
alg.
Red Team
Section titled “Red Team”Discovery
Section titled “Discovery”Find JWTs (cookies, Authorization: Bearer, bodies), decode header and payload
(Base64URL) and identify alg, kid, jku and the claims that decide access.
Attacks (by hand)
Section titled “Attacks (by hand)”# 1) alg=none (app accepts unsigned tokens)header: {"alg":"none","typ":"JWT"} -> altered payload -> empty signature
# 2) HS/RS confusion (RS256 -> HS256)# If it verifies HS256 using the PUBLIC KEY as the HMAC secret:# sign the token with the RSA public key (which is public) as the HS256 secret.
# 3) Weak HMAC secret (HS256) -> crack offlinehashcat -m 16500 token.jwt wordlist.txt # 16500 = JWT# secret cracked -> sign arbitrary tokens
# 4) kid injection# kid -> path traversal (point to /dev/null or a known file) or SQLi
# 5) jku / x5u -> SSRF to your JWKS# point jku at your server with your public key -> sign with your private key
# 6) jwk header injection# embed your own public key in the header and sign with your private keyAlways check whether the app verifies the signature (alter a claim without touching
the signature; if you get through, it doesn’t verify) and whether it honors exp.
Tooling
Section titled “Tooling”jwt_tool (automates all of these), hashcat (HMAC secret), jwt.io (decode/inspect).
Impact and chaining
Section titled “Impact and chaining”ATO, admin access, access to other users’ APIs (combined with IDOR), persistence.
Blue Team
Section titled “Blue Team”Detection
Section titled “Detection”- Tokens with
alg: none, unexpectedalg, orjku/x5upointing to external domains. - Spikes of verification errors; tokens with
expin the past being accepted.
Telemetry and sources
Section titled “Telemetry and sources”Verifier/IdP logs, WAF/API gateway, and token-validation metrics.
Hardening
Section titled “Hardening”- Always verify the signature and pin the expected algorithm (allow-list;
don’t let the token choose). Reject
none. - Strong HMAC secret (random, long) or well-managed asymmetric keys.
- Validate
iss,aud,exp,nbf; don’t trustkid/jku/x5uwithout an origin allow-list. - Short expiry + revocable refresh tokens; don’t store secrets in the payload (it’s signed, not encrypted: it’s readable).
Response
Section titled “Response”Rotate the signing key/secret (invalidates all tokens), review access, and fix the verification.
CVEs and real-world cases
Section titled “CVEs and real-world cases”alg:none/ algorithm-confusion vulnerability — numerous JWT libraries (across languages) suffered it around 2015 and it has resurfaced in later implementations; it’s JWT’s historic flaw.- Weak default HMAC secrets in apps/templates → forgery after cracking.
Per-library CVEs in NVD (https://nvd.nist.gov/vuln/search) and GitHub Advisories (https://github.com/advisories).
Testing checklist
Section titled “Testing checklist”- Is the signature verified? (alter a claim without touching the signature).
-
alg:noneand HS/RS confusion tested. - HS256 secret cracking attempted (hashcat).
-
kid,jku,x5u,jwktested (injection/SSRF). -
exp/iss/audvalidation checked.