Understanding JWT Security Risks and How to Test Them
This article explains the structure of JSON Web Tokens, outlines common attack vectors such as algorithm confusion, weak keys, replay, and header injection, and provides practical mitigation strategies and a testing checklist with recommended security tools.
1. Introduction to JWT
JSON Web Token (JWT) is a compact, JSON‑based open standard (RFC 7519) for securely transmitting information between parties. A JWT consists of three parts: Header, Payload, and Signature.
Header
Defines token type and signing algorithm, e.g. {"alg":"HS256","typ":"JWT"}.
Payload
Contains claims such as user identity and permissions.
Signature
Verifies token integrity and authenticity.
Example JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cJWTs are widely used for authentication and authorization. Servers validate JWTs by verifying the signature.
2. JWT Attack Surfaces
2.1 Algorithm Confusion ("none") Attack
Attackers modify the Header to change the algorithm from a secure one (e.g., HS256) to "none", allowing token forgery.
Original Header: {"alg":"HS256","typ":"JWT"} Modified Header: {"alg":"none","typ":"JWT"} Resulting token can be forged without signature verification.
Mitigation: Strictly validate the alg field and disallow insecure algorithms; explicitly specify allowed algorithms such as HS256 or HS512.
payload = jwt.decode(token, self.secret, algorithms=["HS256","HS512"])
userId = payload['userId']2.2 Weak Keys
Using weak or poorly managed symmetric keys enables brute‑force attacks to generate forged JWTs.
Mitigation: Use strong asymmetric algorithms (e.g., RS256) and high‑entropy keys.
payload = jwt.decode(token, self.secret, algorithms="RS256")2.3 Replay Attack
Attackers capture a valid JWT and reuse it within its lifetime.
Mitigation: Set short exp values and optionally include a nonce; track token usage on the server.
lifetime = datetime.datetime.now() + datetime.timedelta(minutes=5)
payload = {'username': username, 'admin': 0, 'exp': lifetime}
access_token = jwt.encode(payload, self.secret, algorithm="HS256")2.4 Token Leakage
Transmitting JWT over insecure channels (e.g., HTTP) enables interception.
Mitigation: Always use HTTPS and avoid placing JWTs in URLs.
2.5 Header Parameter Injection
Manipulating header parameters such as jwk, jku, or kid can allow attackers to supply their own keys and forge signatures.
Mitigation: Server must whitelist allowed public keys and validate jwk / jku / kid values.
3. Business‑Level JWT Risks
3.1 Sensitive Information Disclosure
Payload is only Base64‑encoded; storing confidential data exposes it.
Mitigation: Store only identifiers in the payload or encrypt the payload.
3.2 Improper Authorization Logic
Mixing token types without strict checks can lead to privilege escalation.
Mitigation: Include role claims and verify them server‑side; use separate keys for different roles.
3.3 Cross‑Service Token Relay
Without audience restrictions, a token issued for one service may be accepted by another.
Mitigation: Validate the aud claim per service and use distinct keys.
3.4 Injection and Privilege Escalation
Crafted JWTs with malicious payloads can bypass checks.
Mitigation: Strictly validate signature, algorithm, and payload content.
4. JWT Testing Checklist
Comprehensive testing steps include locating JWTs, identifying test endpoints, replaying requests, and verifying known vulnerabilities such as the "none" algorithm, RSA key confusion, JWKS injection, and null signature issues.
Additional checks: weak keys, expiration handling, audience validation, and injection vectors.
5. Useful Tools
JWT.io – online decoder and debugger.
JWT Tool – generation and attack utilities.
jwtcrack – dictionary attack against HS256/384/512.
CyberChef – online JWT encoding/decoding.
Burp Suite plugins such as sign‑saboteur for token manipulation.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
