01 / 13

What attacks are possible against JWT implementations?

When a backend blindly trusts incoming tokens without rigorous validation, it opens the door to critical security bypasses, account takeovers, and privilege escalation.

Potential risks and attacks are:
  1. 1

    The none Algorithm Attack

  2. 2

    Key ID (kid) Header Injections

  3. 3

    Attacker-Controlled Key Headers (jku and x5c)

  4. 4

    Weak HMAC Secrets (Brute-Forcing)

  5. 5

    Decoding vs. Verifying: A surprising number of implementation bugs stem from developers accidentally using a library's decode() method instead of its verify() method. decode() merely unfolds the Base64 string so you can read the JSON; it does not cryptographically check if the token was tampered with.

  6. 6

    Token Replay and Lack of Revocation

The none Algorithm Attack: The JWT specification allows an alg header of "none", which indicates that the token is unsigned. If a backend library doesn’t explicitly block this, an attacker can decode a valid token, change their role to "admin", change the header to {"alg": "none"}, strip the signature completely (leaving the trailing dot), and send it back. Structure of a "None" Exploit: Header.Payload. (Note the missing final signature block).

Algorithm Confusion (RS256 vs. HS256): The attacker obtains the server's public key (which is often exposed publicly at standard endpoints like /.well-known/jwks.json).

They modify the JWT payload (e.g., changing user_id to target another account).

They change the JWT header from {"alg": "RS256"} to {"alg": "HS256"} (switching from asymmetric to symmetric).

They sign the malicious token using the public key as the HMAC secret key.

If the backend server is vulnerable, it reads "HS256", looks up its local verification key (the public key), and uses it as a symmetric secret to verify the signature. The math aligns perfectly, and the forged token is accepted.

Key ID (kid) Header Injections: The kid (Key ID) parameter in a JWT header tells the server which specific key to fetch from its database or filesystem to verify the signature. If the server does not sanitize this parameter before processing it, several injection attacks become possible.

Attacker-Controlled Key Headers (jku and x5c): The JWT specification includes headers meant to streamline public key distribution, but they are dangerous if trusted implicitly

Weak HMAC Secrets (Brute-Forcing): When using symmetric signing (HS256), the strength of the token depends entirely on the complexity of the secret string. If a developer uses a weak or predictable secret (like "secret", "password", or the name of the application), an attacker can take a valid intercepted JWT and run an offline brute-force attack using tools like Hashcat or jwt2john. Because JWT validation happens completely offline, an attacker can test millions of keys per second without triggering any server-side rate limits or alerts. Once the secret is found, they can sign any payload they want.

Token Replay and Lack of Revocation Because JWTs are stateless, once a token is issued, it remains valid until its expiration (exp) claim passes. This opens up vulnerabilities around session control