> For the complete documentation index, see [llms.txt](https://blog.s1rn3tz.ovh/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://blog.s1rn3tz.ovh/pentest-web/json-web-token.md).

# JSON Web Token

## Contournement d'authentification via signature non vérifiée

Etapes:

* Surlignez le payload de votre JWT sur Burp
* Dans Burp Inspector, changez la valeurs de votre nom d'utilisateur (exp: "username":"user123 => "username":"administrator")
* Cliquez sur "apply changes"
* Envoyez la requête
* Constater que vous êtes connecté en temps que "administrator"

## Contournement d'authentification via signature nulle

Etapes:

* Surlignez le header de votre JWT sur Burp
* Dans Burp Inspector, changer l'algorithme de chiffrement du token en "none" (exp: "alg":"RS256" => "alg":"none")
* Cliquez sur "apply changes"
* Surlignez le payload de votre JWT sur Burp
* Dans Burp Inspector, changez la valeurs de votre nom d'utilisateur (exp: "username":"user123 => "username":"administrator")
* Cliquez sur "apply changes"
* Supprimez la signature (attention: gardez le "." à la fin du payload)
* Envoyez la requête
* Constater que vous êtes connecté en temps que "administrator"

## Brute force du secret

Si le JWT utilise un chiffrement faible tel que HS256 il est possible de bruteforce le secret de la signature avec hashcat comme ceci:

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

Une fois le secret trouvé, on peut alors générer de nouveaux token comme on le souhaite.

On peut utiliser l'extension JWT Editor de Burp Suite pour ce faire.

Ressource:

<https://portswigger.net/web-security/jwt/working-with-jwts-in-burp-suite#adding-new-signing-keys>

## Contournement d'authentification via injection d'en-tête jwk

{% hint style="info" %}
JWK (JSON Web Key) est un format standardisé permettant de représenter les clés sous forme d'objet JSON.
{% endhint %}

{% hint style="warning" %}
Prérequis: Extension JWT Editor de Burp Suite
{% endhint %}

Etapes:

* Allez dans l'onglet d'extension JWT Editor Keys
* Cliquez sur "New RSA key" > "Generate" > "OK"
* Interceptez la requête voulu
* Allez dans l'onglet "JSON Web Token"
* Changez votre nom d'utilisateur par celui de votre cible dans le payload
* Cliquez sur "Attack" > "Embedded JWK"
* Sélectionnez la clé RSA précédemment générée puis lancez l'attaque
* Remarquez qu'un paramètre "jwk" contenant votre clé a été ajouté au payload
* Envoyez la requête et retournez sur votre navigateur
* Remarquez que vous êtes maintenant connecté sur compte de votre cible

## Contournement d'authentification via injection d'en-tête jku

{% hint style="info" %}
JKU (JWK Set URL) est un URI qui fait référence à une ressource pour un ensemble de clés publiques encodées en JSON, dont l'une correspond à la clé utilisée pour signer numériquement le JWS (JSON Web Signature)
{% endhint %}

{% hint style="warning" %}
Prérequis: Extension JWT Editor de Burp Suite
{% endhint %}

Etapes:

* Allez dans l'onglet d'extension JWT Editor Keys
* Cliquez sur "New RSA key" > "Generate" > "OK"
* Interceptez la requête voulu
* Allez dans l'onglet "JSON Web Token"
* Changez votre nom d'utilisateur par celui de votre cible dans le payload
* Cliquez sur "Attack" > "Embedded JWK"
* Sélectionnez la clé RSA précédemment générée puis lancez l'attaque
* Remarquez qu'un paramètre "jwk" contenant votre clé a été ajouté au payload
* Copier le contenu du paramètre "jwk" et supprimer le paramètre ainsi que son contenu

```json
{
        "kty": "RSA",
        "e": "AQAB",
        "kid": "daf86875-f562-4b2d-9a62-0f13f8ed77d2",
        "n": "qCjZDCcGtvsnLxro6OxWapUxUIqO4NP0WKWAmOcNUn-VKr0C4sVnNjx9AkpREfDU9GhUuvLqjxQYjRt9JjE5dkOi3W43kwCHm-zbVaI2Bjt0_XpyBGi1INiD1lrNl9UWo5PykdwN3j_ByJ9tiDVgrHUmuLXV3THju7XluPlQ5B-c7nZQx0zqMqYnihFSKeUuZwIL0KIPAEwVZpCg0WBOgHIaSDybuuKw5sAUQ4W9SuVTNXZ1DEOB7fRAE6eidRPMxUNS9sAcOEWohhe3ZYCQO0tNVM5asn3YUQBMHlxsu317YydnM4AS82Y61eu7Vr-nnf-lIpTEco00U_LL9dcb4Q"
 }
```

* Ecrivez votre exploit sur votre serveur d'attaque avec les données copiées

```json
{
  "keys": [
    {
        "kty": "RSA",
        "e": "AQAB",
        "kid": "daf86875-f562-4b2d-9a62-0f13f8ed77d2",
        "n": "qCjZDCcGtvsnLxro6OxWapUxUIqO4NP0WKWAmOcNUn-VKr0C4sVnNjx9AkpREfDU9GhUuvLqjxQYjRt9JjE5dkOi3W43kwCHm-zbVaI2Bjt0_XpyBGi1INiD1lrNl9UWo5PykdwN3j_ByJ9tiDVgrHUmuLXV3THju7XluPlQ5B-c7nZQx0zqMqYnihFSKeUuZwIL0KIPAEwVZpCg0WBOgHIaSDybuuKw5sAUQ4W9SuVTNXZ1DEOB7fRAE6eidRPMxUNS9sAcOEWohhe3ZYCQO0tNVM5asn3YUQBMHlxsu317YydnM4AS82Y61eu7Vr-nnf-lIpTEco00U_LL9dcb4Q"
    }
  ]
}
```

* Copiez l'URL vers votre exploit et l'ajouter dans le header du JWT dans un paramètre "jku"
* Remplacer le "kid" par celui dans l'exploit
* Remplacer votre nom d'utilisateur par celui de votre victime
* Cliquez sur "Sign" et sélectionnez la clé RSA utilisée pour l'exploit&#x20;
* Vérifiez que l'option "Don't modify header" est cochée puis cliquez sur "OK"

Vous devriez à la fin avoir un JWT qui ressemble à ceci:

#### Header

```json
{
    "kid": "daf86875-f562-4b2d-9a62-0f13f8ed77d2",
    "alg": "RS256"
    "jku": "https://evil.com/exploit"
}
```

#### Payload

```json
{
    "username": "<target_username>",
    ...
}
```

* Finalement, envoyez la requête et constatez que vous êtes connecté en tant que \<target\_username>

## Contournement d'authentification via manipulation de paramètre kid

{% hint style="warning" %}
Prérequis: Extension JWT Editor de Burp Suite
{% endhint %}

Etapes:

* Allez dans l'onglet JWK Editor Keys
* Cliquez sur "New Symmetric Key" > "Generate"
* Modifiez le paramètre "k" par un byte null encodé en base64 (signature nulle)&#x20;

```json
{
    "kty": "oct",
    "kid": "86d1d9cb-1284-48fa-b29f-bdeeba2a6814",
    "k": "AA=="
}
```

* Interceptez la requête voulu
* Allez dans l'onglet "JSON Web Token"
* Remplacer le paramètre "kid" par un path traversal (vers dev/null afin d'ignorer le "kid"

Exemple:

```json
{
    "kid": "../../../../../../../dev/null",
    "alg": "HS256"
}
```

* Modifiez votre nom d'utilisateur par celui de votre cible
* Cliquez sur "Sign", sélectionnez la clé symétrique généré précédemment, vérifiez que l'option "Don't modify" header est cochée  puis cliquez sur "OK"
* Finalement, envoyez la requête et constatez que vous êtes connecté au compte de votre cible

{% hint style="info" %}
Notez que si le serveur stock ses clés de vérification dans une base de données, le paramètre "kid" peut potentiellement devenir un vecteur d'attaque par injection SQL
{% endhint %}

## Autres vecteurs d'attaque

* Le paramètre `cty` (Content Type) est parfois utilisé pour déclarer un type de média pour le contenu dans la charge utile JWT. Ceci est généralement omis de l'en-tête, mais la bibliothèque d'analyse sous-jacente peut le prendre en charge de toute façon. Si vous avez trouvé un moyen de contourner la vérification de signature, vous pouvez essayer d'injecter un en-tête `cty` pour changer le type de contenu en `text/xml`ou `application/x-java-serialized-object`, ce qui peut potentiellement activer de nouveaux vecteurs pour les attaques [XXE](/pentest-web/injections/xxe.md) ou de[ désérialisation](/pentest-web/insecure-deserialization.md).
* `x5c`(Chaîne de certificats X.509) - Parfois utilisé pour transmettre le certificat de clé publique X.509 ou la chaîne de certificats de la clé utilisée pour signer numériquement le JWT. Ce paramètre d'en-tête peut être utilisé pour injecter des certificats auto-signés, similaires aux attaques par [injection d'en-tête jwk](/pentest-web/json-web-token.md#contournement-dauthentification-via-injection-den-tete-jwk) vue précédemment. Ressources:
  * &#x20;<https://talosintelligence.com/vulnerability_reports/TALOS-2017-0293>
  * <https://mbechler.github.io/2018/01/20/Java-CVE-2018-2633/>

## Attaques par confusion d'algorithme

Etapes généralement suivies:

* Obtenir la clé publique du serveur
* Convertir la clé dans un format approprié
* Créer un JWT malveillant en manipulant le payload et en changeant l'algorithme de chiffrement en HS256
* Signer le jeton en HS256 avec la clé publique comme secret

{% hint style="info" %}
Les serveurs exposent parfois leurs clés publiques en tant qu'objets JSON Web Key (JWK) via un point de terminaison standard mappé sur `/jwks.json`ou `/.well-known/jwks.json`, par exemple. Ceux-ci peuvent être stockés dans un tableau de JWK appelé `keys`. C'est ce qu'on appelle un ensemble JWK.
{% endhint %}

{% hint style="warning" %}
Pour que l'attaque fonctionne, la version de la clé que vous utilisez pour signer le JWT doit être identique à la copie locale du serveur. En plus d'être dans le même format, chaque octet doit correspondre, y compris tous les caractères non imprimables.
{% endhint %}

Exemple pour une clé au format X.509 PEM:

Etapes:

* Trouvez la clé publique du serveur (via l'endpoint jwks.json par exemple)
* Copiez l'objet jwk dans le tableau "keys"

```json
{
    "kty":"RSA",
    "e":"AQAB",
    "use":"sig",
    "kid":"013acf5d-65af-4aa8-8527-898bac386146",
    "alg":"RS256",
    "n":"z5YvN4498LC-kwchA9Kzp60DOzIS3a3ckOKGE47YV9xPiw-msN5xeJHiG3-F-A9as_ioRFZGp4YZ7aCU5kGz_ILLPBq7ePKmvJ8-rCL2jtKHASG-sjL1qGE0ItgIbgNnhEGtHPDpc_Cd9c9OzzhM3VNNqRdVi5WRBttxBzAZj8iJASQTelOcLY4Ve6bIGg3qos-DUAqke5m9MVaxIPg8IzDy8HsWk2-olzTKB9y0xkIb-a3l9j62yIWu6qBT1ZzlFXLa0P4oOQi-LJ1MS-Z7k87VyltIQlbFCQUA67OBCfiQlhqsr_ibXkYJwAshSt0lMifXDGb2tt9K4AcOJhgsnQ"
}
```

* Allez dans l'onglet "JWK Editor Keys"
* Cliquez sur "New RSA Key" > Collez l'objet JWK dans le champ "Key"
* Cliquez sur "OK" puis faites un clic droit sur la clé puis sélectionnez "Copy Public Key as PEM"
* Allez dans l'onglet "Decoder" puis encodez la clé publique PEM en base64
* Copiez le résultat puis retournez dans l'onglet "JWT Editor Key"
* Cliquez sur "New Symmetric Key" > "Generate"
* Echangez le contenu du paramètre "k" par la clé PEM encodé
* Cliquez sur "OK"
* Interceptez la requête voulu
* Allez dans l'onglet "JSON Web Token"
* Modifiez le paramètre "alg" du header en "HS256" si ce n'est pas déjà le cas
* Echangez votre nom d'utilisateur par celui de votre cible
* Signez votre JWT avec la clé **symétrique** générée précédemment (en vérifiant que l'option "Don't modify header" est cochée
* Enfin, envoyez la requête et remarquez que vous êtes connecté au compte de votre cible

{% hint style="info" %}
Dans le cas où il vous serait trop difficile de trouver la clé publique du serveur, il existe des outils permettant de la bruteforce.

ressource: <https://github.com/silentsignal/rsa_sign2n>
{% endhint %}
