# notes

### What are JWTs?

* JSON web tokens (JWTs) - standarized format for sending cryptographically signed JSON data between systems
* 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

#### JWT format

* 3 parts: `header`, `payload` and `signature` separated by dot
* header and payload parts of a JWT are just base64url-encoded JSON objects
* header contains metadata about the token itself, while the payload contains actual claims about the user

  eg -

```
eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA
```

* header part is decoded as follow

```json
{ "kid": "9136ddb3-cb0a-4a19-a07e-eadf5a44c8b5", "alg": "RS256" }
```

* payload part

```json
{
  "iss": "portswigger",
  "exp": 1648037164,
  "name": "Carlos Montoya",
  "sub": "carlos",
  "role": "blog_author",
  "email": "carlos@carlos-montoya.net",
  "iat": 1516239022
}
```

* security of any JWT-based mechanism is heavily reliant on the cryptographic signature

### JWT attacks

* user sending modified JWTs to the server in order to achieve a malicious goal
* goal is to bypass authentication and access controls by impersonating another user who has been authenticated
* impact - severe

#### Exploiting flawed JWT signature verification

* by design, servers don't store any information about the JWTs that they issue and instead each token is an entirely self-contained entity
* one problem is that server doesn't know anything about the original contents of the token or even what the original signature was
* if the server doesn't verify the signature properly, the attacker can chage the rest of the token

1. Accepting arbitary signatures

* the application doesn't verify the signature part at all
* just change the payload parameters and it works

1. Accepting tokens with no signature

* in header part, it looks like :

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

* "alg" parameter is set to `none` -> `unsecured JWT`
* servers usually reject tokens with no signature
* but this kind of filtering relies on string parsing, and can bypass by using classic obfuscation techniques such as mixed capitalization and unexpected encodings

1. Brute-forcing secret keys

* some signing algorithms such as HS256 (HMAC + SHA-256) use an arbitary standalone string as the secret key like password and this secret can't be easily guessed or brute-forced by an attacker
* otherwise, they may be able to create JWTs with any header and payload values and use that key to resign the token with a valid signature
* sometimes, develpers make mistakes like forgetting to change default or placeholder secrets, or copy and paste code snippets they find online
* an attacker can brute-force a server's secret using [wordlist of well-known secrets](https://github.com/wallarm/jwt-secrets)
* use `hashcat` to burte-force

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

#### JWT header parameter injections

* only `alg` header is mandatory
* but JWT header (JOSE header) often contain several other parameters
* eg - `jwk` (JSON Web Key) - provides an embedded JSON object representing the key
  * `jku` (JSON Web Key Set URL) - provides URL from which servers can fetch a set of keys containing the correct key
  * `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

**Injecting self-signed JWTs via jwk**

* JWK - standarized format for representing keys as a JSON object eg -

```json
{
  "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
  "typ": "JWT",
  "alg": "RS256",
  "jwk": {
    "kty": "RSA",
    "e": "AQAB",
    "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
    "n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
  }
}
```

* ideally, servers should only use a limited whitelist of public keys to verify JWT signature
* but, misconfigured servers sometimes use any key that's embedded in the `jwk` parameter
* exploit by signing a modified JWT using your own RSA pirvate key, then embedding the matching public key in the jwk header

**Injecting self-signed JWTs via jku parameter**

* instead of using the jwk header parameter, some servers let you use the jku (JWK Set URL) header parameter to reference a JWK Set containing the key
* JWK Set - JSON object containing an array of JWKs representing different keys

```json
{
  "keys": [
    {
      "kty": "RSA",
      "e": "AQAB",
      "kid": "75d0ef47-af89-47a9-9061-7c02a610d5ab",
      "n": "o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ"
    },
    {
      "kty": "RSA",
      "e": "AQAB",
      "kid": "d8fDFo-fS9-faS14a9-ASf99sa-7c1Ad5abA",
      "n": "fc3f-yy1wpYmffgXBxhAUJzHql79gNNQ_cb33HocCuJolwDqmk6GPM4Y_qTVX67WhsN3JvaFYw-dfg6DH-asAScw"
    }
  ]
}
```

* JWK Sets are sometimes exposed publicly via a standard endpoint `/.well-known/jwks.json`
* more secure websites will only fetch keys from trusted domains, and can bypass like SSRF bypass

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

* header of JWT may contain a `kid` (Key ID) parameter, which helps the server to identify which key to use when verifying the signature
* Verification keys are often stored as a JWK Set
* the server may simply look for the JWK with the same `kid` as the token
* `kid` was not defined a concrete structure
* developers 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, an attacker can potentially force the server to use an arbitary file from its filesystem

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

* if the server supports JWTs signed using symmetric algorithm, it is dangerous
* one simplest methods is in Linux server use `/dev/null` path, which is an empty file and fetching it return null and signing the token with a Base64-encoded null byte will result a valid signature

#### Other JWT header parameters

* `cty` (Content Type) - to declare a media type for the content in the JWT payload; if you 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 enable new vectors for XXE and deserialization attacks
* `x5c` (X.509 Certificate Chain) - can be used to inject self-signed certificates similar to the jwk header injection (CVE-2017-2800, CVE-2018-2633)

### JWT algorithm confusion

* known as key confusion attacks
* occur when an attacker is able to force the server to verify the signature of a JSON web token using a different algorithm than is intended by the developers

#### Symmetric Vs Asymmetric

* JWT can be signed using different algorithms
* eg - HS256 (HMAC + SHA256) use a symmetric key means the server uses a single key to both sign and verify the token

!\[\[Pasted image 20221101205841.jpg]]

* other algorithms such as RS256 (RSA + SHA256) uses asymmetric key pairs which contains a private key which the server uses to sign the token and a mathematically related public key that can be used to verify the signature

!\[\[Pasted image 20221101210036.jpg]]

#### Performing algorithm confusion attack

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

Step 1. Obtain the server's public key

* servers sometimes expose their public keys as JSON Web Key (JWK) objects via endpoint such as `/jwks.json` or `/.well-known/jwks.json` and they may be stored in an array of JWKs called `keys` and known as `JWK Set`

```json
{
	"keys": [
		{
			"kty": "RSA",
			"e": "AQAB",
			"kid": "...",
			"n": "..."
		},
		{
			"kty": "RSA",
			"e": "AQAB",
			"kid": "...",
			"n": "..."
		}
	]
}
```

Step 2 - Convert the public key to a suitable format

* version of the key that you use to sign the JWT must be identical to the server's local copy and every signle byte must match including any non-printing characters
* In Burp
  1. In JWT Editor Keys tab, `New RSA` > paste the JWK that was obtained earlier
  2. Select the `PEM` radio button and copy the resulting PEM key
  3. in Decoder Tab, `Base64-encode` the PEM
  4. in JWT Editor Keys, `New Symmetric Key` > `Generate`
  5. replace the generated value for the `k` parameter with a Base64-encoded PEM key that was copied and save the key

Step 3 - Modify your JWT

* modify the JWT as you like and make sure the `alg` header to `HS256`

Step 4 - Sign the JWT using the public key

* Sign the token using the HS256 algorithm with the RSA public key as secret


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://singha-notes.gitbook.io/web-security-notes/portswigger/jwt-attacks/notes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
