Skip to content

Other Features

DontPanicO edited this page Feb 6, 2021 · 6 revisions

Remove From

The tool give you the ability to delete certain part of the token. For example, if a token specify a jku in its header, and use it to verify the token, you can decide to remove it, to see if the token can be signed with a public key you found while testing your target. The syntax is very similar to the --payload one, since it's key:value based. The only difference is that you have to pass, as the key in the pair, the part of the token from where the tool have to remove (header or payload), and, as value, the key to remove. Let's do an example. Assuming we have a decoded token with the header:

  • {"alg": "hs256", "typ": "jwt", "kid": "0001"}

And the payload:

  • {"user": "test"}

If we want to delete the kid from the header, since we want to use a key we found, we will run:

jwtxpl <token> -a hs256 -p user:admin --remove-from header:kid --key /path/to/key

Note that there are no restrictions to what you can remove from the token, as long as this exists in the token. This means that you could break your own attack. For example if you are testing for a jku injection via HTTP header injection (see the example above), and you run with the command '--remove-from header:jku', this will remove the jku from the token and your attack won't work. Anyway the output of the token provides detailed information about header and payload, before and after they have been processed. So, look at those information to see if they are what you were expecting.

Add Into

The tool give you the ability to add new keys in the header or the payload using the --add-into option. Note that insert new keys in the payload using this option is useless, since --payload already add the key if it does not exists. So this options should be used to insert in the header. It work exactly as --remove-from, but since to insert a new key we need to give it a value, this option assigns to it a default one. This is done, cause of you have no reason to insert a key that you have no intention to use. For example, you don't want to insert the jku key in the header, if you won't launch a jku related attack. Assuming that we have a jwt with the header:

  • {"alg": "HS256", "typ": "jwt"}

And the payload:

  • {"user": "test"}

If we want to add the jku header, to try a jku header attack, we will run the following command:

jwtxpl <token> -a rs256 -p user:admin --add-into header:jku --jku-basic <yourURL>

As said before, be sure to insert only keys that you are going to use, since if we run the previous command, without the --jku-basic option, it will result in the following header:

  • {"alg": "RS256", "typ": "jwt", "jku": "default"}

The Manual Option

In some cases you may want to craft particular urls, that need to be inserted in the token without being modified by the tool. In such cases, you should pass this url to the jku or x5u option (depending on the attack you are going to run) and then specify the --manual one. The manual option is a bool flag that, if present, teel to the tool to not modify you input. When you want to use --manual?

  • When the url pointing to your malformed jwks file does not ends with '/.well-known/jwks.json'

  • When you need to use some trick that is not provided from the tool. For example in some cases you want to try a trick very common in SSRF, passing the server url as it is an user of your domain, e.g.

Assuming that we own a domain mydomain.com, and we are testing an application on application.com, if the application checks that the url in the jku/x5u header starts with http://application.com but it forgot to checks the final slash (http://application.com/), we should pass an url like this:

So we will run the command:

jwtxpl <token> -a rs256 -p foo:bar --jku-basic http://application.com@mydomain.com/.well-known/jwks.json --manual

Note that '/.well-known/jwks.json' has been manually appended in the command since when --manual is present, the tool won't automatically append it.

Access Subclaims

(use --complex-payload for version before 1.1)

We already seen the --payload option before, and we said that it also can access subclaims. The syntax is the same, anyway, in this case, we need more than one key in order to access the item, since it's not at the "first level". Not only that, but you may need to provide a list of values and not just one string. To do that you have to provide a set of keys, separated by a commas, as the key of the key:value pair and, a single value, if you need to provide a single one, or a set of values, comma separated, if you want the tool insert a list.

Let's do an example. Assume that we have this payload:

  • {'user': 'admin1', 'role': 'admin', 'cando': {'users': ['r', 'w'], 'admins': ['r']}}

Where 'r' stand for read and 'w' stands for write. We want to tamper with the token and give our user 'w' permission even on admins. First we have to find the "key path" to the value we want to access. With key path, we means the set of keys we need to access the item, in the rigth order. In this case, we want to access the item related to the key 'admins', that is a subclaim of 'cando'. So the key path will be: first cando, then admins. We have to pass those keys to the tool separated by ',' (cando,admins). Then we have to understand if we want to issue a single value or a list of ones. Notes that, even if the value of the related item is already a list (as in this case is), it will be overriden. So, since we want to pass a list, we have to pass its values as comma separated ones. Finally, the command will be:

jwtxpl <token> -alg hs256 -p cando,admins:r,w -k /path/to/key

Notes that if you want to give only write permission, since values are stored in lists, you have to pass the single value as a list anyway. To do that just pass the value and append a comma to it:

jwtxpl <token> --alg hs256 --payload cando,admins:w, -k /path/to/key

Doing that, the tool will know that your value is a list, even if you passed only one.

Another important thing to know, is that there is no limitations to the amount of keys you can pass. For example if the payload would be:

  • {'user': 'admin1', 'role': 'admin', 'actions': {'cando': {'users': ['r', 'w'], 'admins': ['r']}}}

You should write:

jwtxpl <token> --alg hs256 -p actions,cando,admins:r,w -k /path/to/key

Or, since lists are also indexable:

jwtxpl \<token\> --alg hs256 -p actions,cando,admins,0:w -k /path/to/key

This last command will override the value with index 0 of the list corresponding to the key admins.

And the payload will be changed succsessfully. This options is quite complicated, but it lets you canghe anything.

Handling Data Types in Payload Changes

The way the tool handle equivocal data types is explained in Get Started. I remaind you there, if you didn't read it yet. With equivocal data types we mean numeric strings that the tool can not determine if they have to be converted to integers, or just remain strings. By default the tool will convert them to integers, except if they are preceded by a "%" (read Get Started for more detailed information). So, assume we have the payload:

  • {'user': 'admin1', 'role': 'admin', 'actions': {'cando': {'users': ['0', '1'], 'admins': ['0']}}}

where '0' stands for read and '1' stands for write. You can notice that zeros and ones are strings. So in order to preserve the original data type, we need to tell the tool to not convert them to integers (preceding them with "%"). So the command will be:

- jwtxpl <token> -a hs256 --payload actions,cando,admins:%0,%1 -k /path/to/key