Skip to content
andrea tedeschi edited this page Mar 11, 2021 · 8 revisions

The JWK Claim

JWTs allow to include the key using the JWK claim. JWK is a json data structure that represents a cryptographic key. The jwtXploiter allows you to generate a JWK claim to insert in the token using the --generate-jwk option. In this case alg will be forced to be RS256, and a key pair will be generated. The private key will be used to sign the token while the public key will be inserted in the token header in a JWK format. If the server will trust the JWK, you will have completely control on the token.

jwtxpl <token> -a rs256 -p <key>:<value> --generate-jwk

The jku Claim

As we said before, when talking about the kid, developers may need to use more than one key in order to sign/verify tokens. With JWK this can be acheived with JWKS, a set of JWK stored into an array. JWKS can be stored in files, and such files can be linked in the token header using the jku claim. If the server will trust your url, you can serve your JWKS file and link it to the token specifying its url in the jku header. Using the --jku-basic option, you can pass your url to the jwtxpl. By default, the tool will append the string '/.well-known/jwks.json' to your url. This can be avoided but we will discuss it later. So you need to make a directory named .well-known/ on your server, in order to store the JWKS file returned by the tool. So, assuming that we have created the .well-known/ directory, under the webroot, and that our url is http://myurl.com, the command syntax will be:

jwtxpl <token> -a rs256 -p <key>:<value> --jku-basic http://myurl.com -k /path/to/private.pem

Launching this command will return a JWKS file named jwks.json, in the current directory. Move this file on your server, under the .well-known/ directory, before submitting the token. Remember to remove the jwks.json file when you're done.

N.B. In those examples, I'm always changing something in the token payload using the -p/--payload option. This is not necessary, in order to prove that the server is vulnerable. Also, I'm passing a private key with -k/--key, that has to be considered a good pratice, but it's not mandatory anyway, since the tool generates new pairs when no key has been passed.

Keys serialization

  • (new in version 1.1)

Since version 1.1, the tool provide an option for dump keys to files. If you have no keys to pass, the tool will generates them, as said before. This is very resource-consuming, so you should use --dump-key to store the generated key in a PEM file, to use next times via -k/--key. The option is just a bool flag, you can not pass any argument to it (e.g. no filename).

jku Header and Common Vulnerabilites

Server trusting your url it's not so common, but it happen that the server trusts urls that include or start with their domain. For example, assuming that our target domain is target.com, the server will trust the jku if it starts with 'http://target.com/'. In such cases, if we find open redirects or HTTP headers injections, we can tamper with them, in order to make the jku pointing to our jwks file.

jku and Open Redirects

Assuming that we are testing an application at 'http://app.com', that we can reach our server at 'http://myurl.com', and that we have already created the .well-known/ directory under the web root (you can create it wherever you want as long as is reachable via http), we found an open redirects on the server at 'http://app.com/foo?redirect=bar&any=thing'. In order to correctly exploit that, the tool must know 3 things:

  • The url vulnerable to open redirect
  • Our url ('.well-known/jwks.json' is automatically appended)
  • Which parameter of the query string is the vulnerable one

The server vulnerable url, and our ones have to be simply passed as comma separated values while, to let the tool know where it have to inject, we use the 'HERE' keyword. We have to replace the value of the vulnerable parameter with this keyword, in our case redirect=bar will become redirect=HERE. So we can run the command:

jwtxpl <token> -a rs256 --jku-redirect http://app.com/foo?redirect=HERE&any=thing,http://myurl.com -k /path/to/private.pem

As for the previous attack, the tool will return a jwks.json file in the current working directory. You have to host this file at http://myurl.com/.well-known/jwks.json before submitting the token.

jku and HTTP Header Injection

Case you find an HTTP header injection on the server you are testing, the attack is very similar to the previous one, but it does not require you to host any file, since it inject the JWKS in the response body. So, this time, you have not to pass your url to the tool, but only the target url vulnerable to the header injection. This is done using the --jku-inbody option and, as --jku-redirect does, it requires the use of the HERE keyword. However, this time the HERE keyword has not to replace the value of the vulnerable parameter, but it has to be appended to it. Assuming that we are testing 'http://app.com' and that we find the url 'http://app.com/baz?foo=bar&any=thing' be vulnerable to HTTP header injection, via the 'foo' parameter, we will run the command:

jwtxpl <token> -a rs256 --jku-inbody http://app.com/baz?foo=barHERE&any=thing -k /path/to/private.pem

This time you can immediately submit the generated token, since you have not to host any file.

Pay Attention To

You need to keep in mind two things when you perform those attacks. First the fact that the HERE keyword must be placed in different ways, depending on the attack:

  • In jku redirect attacks the keyword must replace the original value of the redirect (redirect_uri, next or whatever) parameter, because the tool has to craft an url redirecting to your server.

  • In jku via HTTP header injection attacks, the keyword must be appended to the original value that's vulnerable to HTTP header injection. This is due, since we need to mantain the integrity of the url, we just want to add values instead of replacing them.

Then you must pay attention to the server url validation. In previous examples we assumed that the server was checking that the url specified in the jku header, comes from application.com, so we can just append whatever we want. In real life you could face situations where the server checks that the url comes from application.com/.well-known or any path pointing to the .well-known directory. In such cases you should try to use directory traversal:

jwtxpl <token> -a rs256 -p key:value --jku-inbody https://application.com/thing/.well-known/../../any?foo=barHERE

The x5u Claim

JWKS can also contains x509 certificates, specified in the x5c subclaim. Those JWKS files can be linked using the x5u claim. From the attacker prospective, using the jwtxpl, it does not change that much. You have --x5u-basic and --x5u-inbody options, that require the same syntax of the jku's ones. You can go deeper in the x5u claim reading online resources and looking at the jwtXploiter source code, in order to understand what it does.

jwtxpl <token> -a rs256 --x5u-basic http://myurl.com
jwtxpl <token> -a rs256 --x5u-inbody http://app.com/baz?foo=barHERE&any=thing

N.B. At the time of writing, x5u attacks will generates new keys when requests the cert. The use of existing keys for sign certificate requests will be implemented soon.

Veirfy a token agains a JWKS file

(new in version 1.1)

If you have a token, and a jwks file, you may want to know find which key in the file is used to verify the token. This can be easly done with the -F/--find-key-from-jwks option, that accept as argument the path to the jwks file. If the file contain the key that can verify the token, the tool will display it in its JWK format.

jwtxpl <token> -F /path/to/jwks