Module 29 · Advanced JWT Attacks — Beyond Algorithm Confusion

Manish Garg
Manish Garg Associate of (ISC)² · RingSafe
May 14, 2026
3 min read
Read as

Last updated: May 18, 2026

100% Free
No signup. No paywall. No catch. One of our 10 most-requested practitioner modules — published in full so anyone can learn for free. We earn through consulting, not by gating knowledge.
See all 10 free modules →
Why this module exists. JWT attacks go beyond the classic algorithm-confusion (alg=none, alg=HS256 with public-key). Modern JWT attacks include key-confusion via JWK Set, JKU header injection, KID parameter injection, and weakness in JWE encrypted tokens. This module covers the advanced techniques.

Beyond alg=none and HS256 confusion

Module SC-4 covered the classic algorithm-confusion attacks. This module covers the advanced variants.

KID header injection

# JWT header
{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "../../../etc/passwd"
}
# Application uses kid to look up the signing key.
# If kid is unchecked, attacker can:
# - Path-traverse to read arbitrary files as keys.
# - SQL inject via kid (if backed by DB lookup).
# - Direct file inclusion in older PHP apps.

Defender: KID validated as opaque identifier; never used in file paths or unsanitised DB queries.

JKU and X5U header attacks

JWT supports specifying the location of the verification key via headers:

  • jku: URL to a JWK Set (JSON Web Key Set).
  • x5u: URL to an X.509 certificate chain.

If the application fetches the URL specified in the JWT header to validate the signature, the attacker can:

# Attacker hosts their own JWK Set at attacker.com/jwks.json
# Attacker crafts JWT with header { "alg": "RS256", "jku": "https://attacker.com/jwks.json" }
# Attacker signs the JWT with the corresponding private key.
# Application fetches the JKU URL, gets attacker's public key, verifies signature → accepts.

Defender: allowlist the JKU URL host; never trust the JWT-provided JKU.

JWK injection inside the JWT

The jwk header parameter embeds the entire JWK directly in the JWT:

# JWT header
{
  "alg": "RS256",
  "jwk": {
    "kty": "RSA",
    "n": "...attacker's RSA public key...",
    "e": "AQAB"
  }
}
# Application uses the embedded jwk for verification.
# Attacker signs with their private key; verification with embedded public key succeeds.

Defender: never trust embedded jwk; always use server-configured key set.

JWE — encrypted JWT

JWE (JSON Web Encryption) is the encrypted variant. Attack patterns:

  • Key wrap algorithm confusion: forcing RSA1_5 (susceptible to Bleichenbacher attacks) instead of RSA-OAEP.
  • Direct mode without authentication: encryption without integrity check; attacker tampers ciphertext.
  • Invalid curve attacks: for ECDH-based key agreement; attacker provides invalid curve point.

Defender: pin the key-wrap algorithm; require AEAD content encryption (A128GCM, A256GCM).

Critical-claim handling

JWT spec allows a “crit” header listing claims that processing must understand. If the JWT processor ignores crit, an attacker can include a “crit” entry that, when processed, would have failed validation.

Tools for JWT testing

  • jwt_tool (ticarpi): comprehensive JWT manipulation and attack toolkit.
  • JWT Heartbreaker (Burp extension): in-line JWT testing.
  • jwt.io: decoder + signer, useful for manual crafting.
  • jose-util: command-line JOSE / JWS / JWE manipulation.

The defender’s hardening checklist

  • Algorithm pinning: jwt.decode(token, key, algorithms=[expected_alg]).
  • Issuer (iss) and audience (aud) claim validation.
  • Expiry (exp) and not-before (nbf) checked.
  • KID validated as opaque identifier; mapped to a known key set.
  • JKU / x5u: only allowlisted hosts; ideally hardcoded.
  • JWK / X5C headers: ignored; never used as the verification key.
  • Crit header: processor understands all listed claims or fails validation.
  • Short-lived tokens (minutes to hours) + refresh-token rotation.
  • Revocation mechanism for high-stakes tokens.

Common failure modes

  • Application accepts whatever algorithm the JWT claims.
  • JKU header fetched without host validation.
  • KID used in unsanitised file path or DB query.
  • Embedded jwk trusted for verification.
  • Audience claim not validated; token issued for service A accepted by service B.

Key takeaways

  • Beyond alg=none: KID injection, JKU/X5U manipulation, embedded JWK.
  • JWE has its own attack surface: key-wrap algorithm, direct mode without auth, invalid curve.
  • Defender: pin everything — algorithm, key, issuer, audience, expiry.
  • Never trust JWT-provided URLs or keys for verification.
  • Tools: jwt_tool, JWT Heartbreaker, jwt.io.

Related engagement → How we ran a web app pentest for a leading Indian fintech

Need a real pentest?

Get a VAPT scoping call

Senior practitioner-led VAPT — not a checklist run by juniors. CVSS-scored findings, free retest, attestation letter. India's SMBs and SaaS teams.

Book VAPT scoping call Replies in 4 working hrs · India-only · Senior consultants