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)
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
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