JWT KID Header Injection
Ce contenu n’est pas encore disponible dans votre langue.
| Severity | High |
|---|---|
| Classifications | CWE-345: Insufficient Verification of Data Authenticity |
| Attack Pattern | |
| OWASP Category | OWASP API2:2023 Broken Authentication |
The kid (Key ID) JWT header field is intended to tell the server which key to use for signature verification. When this value is passed unsanitized to a database query or a file system lookup, attackers can inject a payload that causes the server to use an attacker-controlled key, effectively allowing them to forge arbitrary tokens.
JWTop tests four variants of this attack:
- SQL Injection — injects a SQL payload into
kid(e.g.' UNION SELECT 'secret' ...) so that the database returns a known value as the key. - Path Traversal — sets
kidto a filesystem path such as/dev/nullso the server reads an empty file as the key, which can be matched with an empty HMAC secret. - Command Injection — sets
kidto a shell metacharacter payload (e.g.; id,$(id)) targeting servers that shell out using thekidvalue to locate a key file. - LDAP Injection — sets
kidto an LDAP filter metacharacter payload (e.g.*)(uid=*) targeting servers that use thekidvalue in an LDAP lookup to resolve a signing key.
Example
Section titled “Example”Here is a valid JWT signed with HS256:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cSQL Injection variant
Section titled “SQL Injection variant”The attacker crafts a token with a kid header that injects into the key-lookup query and re-signs it with the value the query is made to return (secret):
{ "alg": "HS256", "typ": "JWT", "kid": "' UNION SELECT 'secret' FROM tokens WHERE '1'='1"}Path Traversal variant
Section titled “Path Traversal variant”The attacker sets kid to /dev/null and re-signs the token with an empty HMAC secret. If the server reads the signing key from the path named by kid, it receives zero bytes:
{ "alg": "HS256", "typ": "JWT", "kid": "/dev/null"}Command Injection variant
Section titled “Command Injection variant”The attacker sets kid to a shell metacharacter payload and re-signs the token with an empty HMAC secret. If the server shells out with the kid value to locate a key file (e.g. openssl ... -in keys/$kid.pem), the injected command runs on the server:
{ "alg": "HS256", "typ": "JWT", "kid": "; id"}LDAP Injection variant
Section titled “LDAP Injection variant”The attacker sets kid to an LDAP filter metacharacter payload and re-signs the token with an empty HMAC secret. If the server interpolates the kid value into an LDAP search filter to resolve a signing key (e.g. (&(objectClass=key)(kid=$kid))), the injected filter term can make the lookup match an unintended entry:
{ "alg": "HS256", "typ": "JWT", "kid": "*)(uid=*))(|(uid=*"}How to test?
Section titled “How to test?”If you want to test if your server is vulnerable to the “JWT KID Injection” vulnerability, you can use the crack command:
jwtop crack [token] --url [url]The
crackserver probe currently covers the SQL Injection and Path Traversal variants only. Command Injection and LDAP Injection are exploit-only — generate the token below and test it against your server manually.
To generate a token with a kid injection payload, use the exploit kidinjection command:
jwtop exploit kidinjection [token] --mode sqljwtop exploit kidinjection [token] --mode pathjwtop exploit kidinjection [token] --mode commandjwtop exploit kidinjection [token] --mode command --all # try every shell payload variantjwtop exploit kidinjection [token] --mode ldapjwtop exploit kidinjection [token] --mode ldap --all # try every LDAP payload variantjwtop exploit kidinjection [token] --mode raw --kid "' OR 1=1 --" --secret "mysecret"What is the impact?
Section titled “What is the impact?”A successful KID injection attack allows an attacker to forge a JWT that the server accepts as legitimate. This can lead to full authentication bypass, privilege escalation, or impersonation of any user in the system.
How to remediate?
Section titled “How to remediate?”- Validate the
kidvalue before using it — reject values containing SQL metacharacters, path separators, shell metacharacters, LDAP filter metacharacters, or characters outside a safe allowlist (e.g. alphanumeric and hyphens only). - Use parameterised queries when looking up keys by
kidin a database to prevent SQL injection. - Never read key material from user-controlled file paths — store keys in a secure key store and use
kidonly as an opaque identifier mapped server-side to a known key. - Never pass
kidto a shell command — if key lookup requires an external process, use an allowlist of key IDs and pass the resolved path as an argument, never build a shell string fromkid. - Escape LDAP filter metacharacters in the
kidvalue (or use a parameterised LDAP filter API) before it is interpolated into a search filter. - Hard-code or allowlist permitted
kidvalues where possible.