JWT Security Vulnerabilities and Protection (Advanced Edition)

JWT Security Vulnerabilities and Protection (Advanced Edition)

1. Knowledge Point Description
JWT (JSON Web Token) is an open standard (RFC 7519) for authentication and authorization, consisting of three parts: Header, Payload, and Signature. Although JWT is widely used, improper implementation can lead to serious security vulnerabilities, such as signature bypass, key confusion, algorithm tampering, etc. This advanced edition will delve into common JWT vulnerability scenarios and protective measures.


2. Vulnerability Principles and Attack Scenarios
2.1 Algorithm Confusion Attack

  • Principle: The JWT header contains the alg field, which specifies the signature algorithm (e.g., HS256, RS256). If the server-side code relies on the client-provided alg value to verify the signature, an attacker may change the asymmetric algorithm (RS256) to a symmetric algorithm (HS256), thereby forging a signature using the public key.
  • Attack Steps:
    1. Obtain the service's public key (often publicly accessible).
    2. Modify the JWT header to {"alg":"HS256","typ":"JWT"} and the payload to malicious content (e.g., elevate privileges).
    3. Use the public key as the secret for HS256 to generate a signature.
    4. The server mistakenly uses the public key for HS256 verification, leading to signature bypass.

2.2 Key Leakage and Weak Keys

  • Weak keys (e.g., "secret", "password") are susceptible to brute-force attacks, or keys hardcoded in the source code may lead to leakage.
  • Tools (e.g., jwt_tool) can automate testing with common keys.

2.3 Unverified Signature

  • Developers might decode the JWT without verifying the signature, allowing arbitrary tampering with the payload.

3. Protective Measures
3.1 Enforce Algorithm Specification

  • In code, fix the algorithm used for verification and ignore the client-provided alg value.
    # Wrong example: relies on client alg  
    decoded = jwt.decode(token, key, algorithms=["HS256", "RS256"])  
    # Correct example: fixed algorithm  
    decoded = jwt.decode(token, key, algorithms=["RS256"])  # Only accept asymmetric algorithms  
    

3.2 Key Management

  • Symmetric algorithms (HS256) require strong random keys and should be rotated regularly.
  • For asymmetric algorithms (RS256), ensure the private key is kept strictly confidential, and the public key is only used for verification.

3.3 Verify Integrity and Expiry

  • After verifying the signature, check fields in the payload such as exp (expiration time) and iss (issuer).
  • Example:
    decoded = jwt.decode(
        token, 
        key, 
        algorithms=["RS256"],  
        options={"verify_exp": True, "verify_iss": True}
    )  
    

3.4 Avoid Sensitive Information Leakage

  • The JWT payload is only Base64 encoded by default, not encrypted. Sensitive data (e.g., passwords) should not be stored in the payload.

4. Practical Detection Process

  1. Collect JWT: Obtain a sample Token through the login function.
  2. Decode and Analyze: Use jwt.io to decode the header and payload, observing if the algorithm and parameters can be tampered with.
  3. Test Signature Bypass:
    • Modify alg to none (requires server support).
    • Attempt algorithm confusion (RS256→HS256).
    • Brute-force weak keys (common tools: hashcat, jwt_tool).
  4. Verify Server-side Logic: Tamper with exp or user ID to check if it affects permissions.

5. Summary
JWT security relies on strict algorithm verification, key management, and parameter validation. In development, you should:

  • Disable alg=none;
  • Fix the verification algorithm;
  • Rotate keys periodically;
  • Combine logging to monitor abnormal Token usage.

Through the above measures, risks in JWT implementation can be significantly reduced.