# Exploiting JWT - Lack of Signature Verification

 **TL;DR**  
Here goes the short PoC -

- WebApp using JWT for authentication.
- Removed the signature - Signature is not being verified - Token still works.
- Modified and Re-encoded payload to get an Account takeover.  
PS: Header was untouched - `"alg": "HS256"`

## A small yet descriptive Introduction

JSON Web Tokens are one of the most in-trend authentication mechanisms that are currently being used in modern applications to protect their data and maintain a tight access control over their apps and API endpoints.

The basic structure of a JSON Web Token can be explained really well by [https://jwt.io/](https://jwt.io/)

<figure class="kg-card kg-image-card"><img src="https://imgur.com/ExI4rwL.png" class="kg-image" alt="JWT" loading="lazy"></figure>

As it can be seen in the above image, the left side consist of an encoded JWT i.e.,
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```

These tokens follow a format, that is, all of the token can be divided into three parts separated by a `.` (dot) and each part is encoded separately using Base64.

1. The first part is called the Header - `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9`
2. The middle part is the Payload or the actual data that is encrypted/signed- `eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ`
3. and the last part is the most important part which verifies the token, i.e., the Signature - `SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`

The signature of a JSON Web token is calculated by   
* Base64Url encoding the Header   
* Base64Url encoding the Payload   
* Concatenating them using `.` and   
* Signing it using the `alg` specified in the Header using a Secret

In the above-mentioned token, this can be achieved using -

    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret)

The Base64-decoded data can be seen in the above image. It should however be noted that this is a basic JWT architecture and a JWT supports loads of other parameters as well but we'll talk about them in upcoming articles.

They define a secure way of transmission of data which, if implemented correctly, verifies that the data that is being passed in the JWT is tamper-free because the developers can sign the token using their public/private key pairs or using a Secret with HMAC. This approves the integrity of the data.

* * *

## The actual Bug (PoC)

JWT has been exploited multiple times in numerous articles wherein a vulnerable library is being used that allows attackers to use `"alg": "None"` and an empty Signature to forge their own Payloads and tokens but this PoC exploits a JWT misconfiguration that occured due to missing Signature verification.   
Also take a look at this tool, it's pretty helpful in exploiting those `"None"` algorithm attacks and has a ton of other features - [https://github.com/ticarpi/jwt\_tool](https://github.com/ticarpi/jwt_tool)

Let's call the vulnerable site `redacted.com`

`redacted.com` has a subdomain called `training.redacted.com` that hosts an application which is authenticating users using JWT and signing all their API requests with that JWT.  
The JWT is contained in a Cookie value &nbsp;`RedactedAuthCookie=` and the token looks something like this -

<figure class="kg-card kg-image-card"><img src="https://imgur.com/wfS3E0g.png" class="kg-image" alt="cookie" loading="lazy"></figure>

My first thought was obviously to test the "None" attack so I used `jwt_tool` (link above) and a plugin in Burp called `JSON Web Tokens` to test all kind of attacks.

From what I've learned, to make it work, we have to change the `"alg"` to `"None"` and remove the Signature part but even after trying all variations of None - `none`, `None`, `NONE`, and `nOnE`, **none** of them worked.

Then I kept the algorithm in the Header as it was in the original request, i.e., `HS256` and removed the Signature completely which gave a success response.  
This proved that there is in-fact a bug here, probably the signature is not being verified at all, a disaster from the developers side, which made me think of the possibilities of forging my own tokens.

Then I had to manually try each of the three parameters to find which one of them might lead to access into another account - `userid`, `clientid`, and `userauthenticationid`.  
It was found that the parameter `clientid` stores session information.

And we have ourselves a complete Account takeover bug PoC

<figure class="kg-card kg-image-card"><img src="https://imgur.com/3bMeT3h.png" class="kg-image" alt="poc" loading="lazy"></figure>
