Hacking JWT (JSon Web Token)

Another day playing with JWT. I found another way to compromise JWT session during my pentest exercise.

During the web enumeration, I found that the application that I am trying to take over is using JWT session stored in the cookie. You can debug JWT and view the content of JWT token, I use jwt.io to view it. Lets capture using burp first

We can see that the token is signed using RS256 with the kid from specified URL (localhost:7070/privKey.key). The payload consist of username and email address with interesting flag admin_cap=0.

My assumption admin_cap is the flag that differentiate between normal user and administrator privilege. Lets play with the flag.

First we need to understand that this JWT token is sign with key specified in kid (key ID)

The kid (key ID) Header Parameter is a hint indicating which key was used to secure the JWS. This parameter allows originators to explicitly signal a change of key to recipients. The structure of the kid value is unspecified. Its value MUST be a case-sensitive string. Use of this Header Parameter is OPTIONAL.

To enable us to build new valid payload in JWT token is to compromise the sign key so that application will get good validation when it tries to check the payload integrity with given key.

We see that the kid is downloaded from specified URL that we can try to forward them to our own key.

Lets create a private and public key

─$ openssl genrsa -out priv.key 2048

The next is to start python http server to allow this key to be downloaded from the victim machine

$ python3 -m http.server 8900                                                                                                                                                                                                          
Serving HTTP on 0.0.0.0 port 8900 (http://0.0.0.0:8900/) ...

Build the new JWT token

You can use jwt.io to generate the new token, First we will redirect the key to our key by pointing the kid to our key hosted at “kid”: “http://10.10.16.3:8900/priv.key” and we change our role to become admin “admin_cap”: 1 and you have to sign the token with the priv key that you generated using openssl by copying the private key into the second text box under the VERIFY SIGNATURE

After the new token generated then you can edit the cookie in your browser and refresh it to take effect

After we refresh the web then we have administrator functionality which previouly was not there

Normal account

Admin Account

When we refresh our bworser, The application server tries to validate the JWT token passed to the server by using the key that we provided in in kid.

So the sign key was actually forged to use the compromissed one instead the legitimate one. So becarefull on setting up JWT that you need to ensure the key cannot be compromissed. in JWT sign key is the king, once this is compromissed then the auth token is in danger

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s