JWT Signature Bypass via unvalidated x5u parameter
Description
This vulnerability occurs when a JSON Web Token (JWT) implementation fails to properly validate the 'x5u' (X.509 URL) header parameter, which specifies a URL pointing to an X.509 certificate chain for signature verification. When this parameter is not validated, an attacker can reference their own malicious certificate hosted on an external server, allowing them to forge valid JWT signatures. This enables attackers to create arbitrary tokens with modified payloads, bypassing authentication and authorization controls. The vulnerability may also be exploited to trigger Server-Side Request Forgery (SSRF) attacks by forcing the application to retrieve certificates from attacker-controlled URLs.
Remediation
Implement strict validation of the 'x5u' parameter to prevent signature bypass attacks. Follow these remediation steps:
1. Implement URL Whitelisting: Create an allowlist of trusted domains and complete URLs that are permitted to host X.509 certificate files. Validate both the domain and the full path to prevent bypass attempts.
2. Disable HTTP Redirects: Configure the HTTP client used for certificate retrieval to reject redirects, preventing attackers from bypassing URL validation through redirect chains.
3. Validate Certificate Chain: After retrieving the certificate, verify it against a trusted Certificate Authority (CA) and ensure it matches expected certificate properties.
4. Consider Alternative Approaches: Where possible, use the 'x5c' parameter (embedded certificate chain) instead of 'x5u', or rely on pre-configured trusted certificates rather than dynamic URL-based retrieval.
Example validation implementation:
// Example in Node.js using jsonwebtoken library
const jwt = require('jsonwebtoken');
const https = require('https');
const ALLOWED_X5U_URLS = [
'https://trusted-domain.com/certs/public.pem'
];
function validateX5uUrl(x5uUrl) {
// Strict whitelist validation
if (!ALLOWED_X5U_URLS.includes(x5uUrl)) {
throw new Error('x5u URL not in allowlist');
}
return true;
}
function verifyToken(token) {
const decoded = jwt.decode(token, { complete: true });
if (decoded.header.x5u) {
// Validate x5u URL before retrieval
validateX5uUrl(decoded.header.x5u);
// Retrieve certificate with redirects disabled
const agent = new https.Agent({ maxRedirects: 0 });
// ... fetch and verify certificate
}
// Proceed with token verification
}
Ensure all JWT validation logic is reviewed and tested to confirm that signature verification cannot be bypassed through header manipulation.