JWT Signature Bypass via unvalidated x5c parameter
Description
The application accepts JSON Web Tokens (JWTs) that include the 'x5c' header parameter, which specifies an X.509 certificate chain for signature verification. When the application fails to properly validate this certificate chain, attackers can supply their own malicious certificates and corresponding private keys to sign forged tokens. This allows attackers to create valid-looking JWTs with arbitrary claims and payloads, completely bypassing the authentication and integrity protection that JWTs are designed to provide.
Remediation
Implement one of the following remediation approaches:
Option 1 (Recommended): Disable x5c parameter support
Remove support for the 'x5c' header parameter entirely and use a pre-configured trusted key or certificate for JWT signature verification. This eliminates the attack vector by preventing clients from specifying their own certificates.
Option 2: Implement strict certificate chain validation
If x5c support is required, implement comprehensive validation including:
• Verify the complete certificate chain up to a trusted root CA
• Check certificate validity periods and revocation status (CRL/OCSP)
• Validate that the certificate is authorized for JWT signing
• Pin expected certificate attributes (subject, issuer, key usage)
Example secure implementation (Python with PyJWT):
import jwt
from cryptography import x509
from cryptography.hazmat.backends import default_backend
# Option 1: Use pre-configured trusted key
trusted_public_key = load_trusted_public_key()
decoded = jwt.decode(token, trusted_public_key, algorithms=['RS256'])
# Option 2: Validate x5c if required
def validate_x5c_chain(x5c_certs, trusted_roots):
# Parse certificates
certs = [x509.load_der_x509_certificate(cert, default_backend())
for cert in x5c_certs]
# Verify chain to trusted root
if not verify_chain_to_trusted_root(certs, trusted_roots):
raise ValueError('Certificate chain validation failed')
# Verify certificate is not revoked
if is_certificate_revoked(certs[0]):
raise ValueError('Certificate has been revoked')
return certs[0].public_key()
Conduct a thorough security audit of all JWT validation logic to ensure signatures are properly verified before trusting token contents.