# JWT

## What is JWT?

Read this article first:

{% embed url="<https://jwt.io/introduction>" %}
JSON Web Tokens Introduction - JWT.IO
{% endembed %}

JWT is similar to a session token, but they work differently:

* A **session token** contains only the session ID. The client sents this session token to the server and server looks up this ID in its database. This backend database stores all the information regarding the user's session, for example, username, authorization, and etc.
* A **JWT** contains the entire session object and it is stored on the client side. JWT consists of a signature so the server can verify its integrity.

To summarize, with session ID cookies, sessions live on the **server**, but with JWTs, sessions live on the **client**.

## Vulnerability 1: `decode()` || `verify()`

Many JWT libraries provide one method to decode the token and another to verify it:

* `decode()`: Only decodes the token from base64url encoding without verifying the signature.
* `verify()`: Decodes the token and verifies the signature.

Here `decode()` does **NOT** verify the signature at all. Sometimes developers might mix up these methods.

## Vulnerability 2: The "None" Algorithm

If the `none` algorithm is accepted by the server, then the signature won't be verified at all. That is, anyone can forge a malicious JWT and the server will accept it blindly. This is a dumb vulnerability, just disable the `none` algorithm, please.

## Vulnerability 3: HS256 Weak Secret

{% hint style="info" %}
With symmetric encryption, a cryptographic signature is only as strong as the secret used.
{% endhint %}

If an application uses a weak secret, the attacker can simply **brute-force** it by trying different secret values until the original signature matches the forged one. Having discovered the secret, the attacker can use it to generate valid signatures for malicious tokens. To avoid this vulnerability, strong secrets must always be used with symmetric encryption.

## Vulnerability 4: RSA || HMAC Confusion

JWT accepts both symmetric and asymmetric encryption algorithms. Depending on the encryption type, you need to use either a shared secret or a public-private key pair:

| **Algorithm**    | **Key used to sign** | **Key used to verify** |
| ---------------- | -------------------- | ---------------------- |
| Asymmetric (RSA) | Private key          | Public key             |
| Symmetric (HMAC) | Shared secret        | Shared secret          |

When an application uses asymmetric encryption, it can openly publish its public key and keep the private key secret. This allows the application to sign tokens using its private key and anyone can verify this token using its public key. The algorithm confusion vulnerability arises when an application does not check whether the algorithm of the received token matches the expected algorithm.

In many JWT libraries, the method to verify the signature is something like `verify()` which takes two arguments depending on user-specified algorithm:

* `verify(token, secret)` – if the user-specified algorithm is HS256
* `verify(token, public_key)` – if the user-specified algorithm is RS256

Unfortunately, in some libraries, `verify()` does **NOT** check whether the received token is signed using the application's expected algorithm. **Suppose the server uses RS256. If the public key is accessible within the application, an attacker can forge malicious tokens by:**

1. Changing the algorithm of the token to HS256
2. Tampering with the payload to get the desired outcome
3. Signing the malicious token with the public key found in the application
4. Sending the JWT back to the application

The application expects RSA encryption, so when an attacker supplies HMAC instead, the `verify()` method will **treat the public key as an HMAC shared secret** and use symmetric rather than asymmetric encryption. This means that the token will be signed using the application’s non-secret public key and then verified using the same public key.

To avoid this vulnerability, applications must check if the algorithm of the received token is the expected one before they pass the token to the `verify()` method.

## Vulnerability 5: RSA || HMAC Confusion without Public Key

In RSA || HMAC Confusion, the attacker needs the public key to exploit the vulnerability. **What if the attacker does not have the public key?** Bad luck, it is still vulnerable. Read this article to learn more:

{% embed url="<https://blog.silentsignal.eu/2021/02/08/abusing-jwt-public-keys-without-the-public-key>" %}
Abusing JWT public keys without the public key
{% endembed %}

## Lab

{% embed url="<https://cryptohack.org/challenges/web>" %}
Crypto on the Web - CryptoHack
{% endembed %}

## Reference

{% embed url="<https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/>" %}
Critical vulnerabilities in JSON Web Token libraries
{% endembed %}

{% embed url="<https://www.invicti.com/blog/web-security/json-web-token-jwt-attacks-vulnerabilities>" %}
JSON Web Token attacks and vulnerabilities
{% endembed %}
