Brute force JSON web token with python

JSON web token (JWT) is a standard defined for the use of secure transmission of information (https://jwt.io/introduction) between parties, using a JSON object. The information transmitted can be trusted since it is digitally signed by the server with a hashing algorithm and a key. JWT is signed using the HMAC algorithm together with a password or a public/private key using RSA. It is used when creating a session, for example, of a client on a web server.

The information contained in the token is related to the identity of the the session, initated from the client on the server (username, email, admin rights, etc). The token is signed by the server, with a private key, in order to prevent the client to modify it. The token is issued during the authentication process, and is submitted back to the server every time an action from the client is required, in order to insure that the client is requesting an action that he is authorized to perform.

The JWT is a string chain structured as shown on the Fig.1. It is base64 encoded and represents the structure header.claims.signature.

Fig. 1: Structure of a JSON web token (credit: WebGoat)

The decoded version of the JWT in Fig. 1 can be seen below.

The header contains the kind of token used and the algorithm used to compute the signature. The claim contains information related to the sesion that has been initiated (usename, user id, permission, mail, etc). The signature is computed based on the algorithm in the header, taking into account the header and the claims. It used to insure that nobody modifies the token in order to request an unauthorized action. A password/key is used to generate the signature. This adds a layer of security, since it makes the signature more difficult to reproduce. With a good key such as public/private keys with RSA, the signature would be extremely hard to bruteforce. However, with a simple keyword, not so much is required in order to break the key.

Bruteforcing the JSON web token.

JSON web tokens can easily be made using the pyjwt librairie in python.
You just need to install the module with pip install pyjwt.
The module allows you to create the JWT by parsing the JSON object representing the claims, a key and the algorithm you want to use.

The OrderedDict object is used to insure that the data stay in the same order in the JSON claims.
If we try to decode the token we obtained, we can check the value of the header and claims

As we just saw, the header and the claims inside the JWT are just the base64 encoded version of the JSON data, and are not affected by the key used to generate the token. The key only affects the creation of the signature. Furthermore, it is quite fast to generate one token. So, if the token has been generated with a poor key, it should be quite easy to guess that key.

Below is a small python script that I wrote for a challenge, where you needed to bruteforce the JWT, and create a new token with some specific parameters. I will here just show how to bruteforce the token, the rest is quite easy.

Basically, this scripts takes the token given by the server, and tries to reproduce it using different keys.

Here, the claims is set. To obtain it, you have to decoded the corresponding part from the JWT. It is then converted to the good JSON ordered format. Then a string with the token provided by the server is created. It will be used to be compared to all the tokens we will compute with different keys.

Opening a dictionary containing common password/keys. While looping over the passwords in the file, several things will happen. The strip method removes the \n character after each password. Then, a new token is computed (encoded_jwt). It will contain the header.claims.signature.
It will be compared directly to the token that we received from the server. If the token is the same, then we have found the key that the server uses to generate the token. This means that we can now generate token with the parameters that we want and get some administrator rights.

In order to prevent such attacks, a strong key is recommended for the generation of tokens, such as public/private key with RSA.

Leave a Reply

Your email address will not be published. Required fields are marked *

Solve : *
2 × 21 =