JSON Web Token
Liste des différentes attaques sur les JWT
Signature non vérifiée
Principe : Modifier le token puis rejouer la requête en enlevant la partie signature.
Exemple d’un token envoyé sans signature :
Il est important de garder le séparateur final “.
” pour indiquer que la signature est vide.
Explication de la vulnérabilité : certaines librairies fournissent les méthodes verify()
, permettant de vérifier une signature, et decode()
qui décode simplement le token. L’emploi de ce dernier ne vérifie ainsi pas la signature et est à l’origine de cette vulnérabilité.
Algorithme défini à none
Principe : Modifier l’en-tête alg
et mettre sa valeur à none
, puis rejouer la requête en enlevant la partie signature.
Cryptographie avec secret faible
Principe : Récupérer un token JWT et effectuer une attaque par bruteforce ou dictionnaire afin d’en récupérer le secret. Cette méthode ne fonctionne qu’avec des algorithmes de signature symétriques : HS256, HS384 ou HS512).
Injection d’en-tête
Si seul l’attribut alg
est obligatoire dans l’en-tête d’un JWT, il existe d’autres attributs optionnels pouvant être manipulés par l’utilisateur.
Certains serveurs mal configurés utilisent n’importe quelle clé intégrée dans le paramètre jwt
pour vérifier la signature du token. Ces attaques visent alors principalement à remplacer les clés privée/publique du serveur par une paire de clés que l’on contrôle, afin de signer les tokens JWT.
Pour générer des clés RSA, il est recommandé d’utiliser l’extension Burp JWT Editor.
JSON Web Key (JWK)
Attribut : Correspond à la clé publique lié à la clé privée servant à signer les JWT. Avec cet attribut, la clé publique est directement injectée dans l’en-tête.
Principe : Signer un token JWT modifié avec sa propre clé privée RSA, puis injecter la clé publique dans l’attribut jwk
afin que le token soit vérifié par l’application.
État initial :
En-tête modifiée :
Reproduire avec BurpSuite :
- Installer les extensions JSON Web Token et JWT Editor Key ;
- Se rendre dans l’onglet JWT Editor Key et générer une nouvelle clé RSA ;
- Envoyer une requête contenant un token JWT au Repeater ;
- Dans le Repeater, passer sur l’onglet JSON Web Token et modifier le payload du token comme souhaité ;
- Cliquer sur “Attack”, puis sélectionner “Embedded JWK” et sélectionner la clé RSA que l’on a généré précédemment ;
- Envoyer la requête et regarder le résultat.
JSON Web Key Set URL (JKU)
Attribut : Correspond à un JWT Set contenant des URLs vers des clés publiques. Lors de la vérification d’une signature, le serveur va utiliser les clés présentes sur ces URLs.
Principe : Faire pointer l’URL sur un serveur que l’on possède, et héberger notre propre clé publique pour vérifier le token. Signer le token modifié avec notre clé privée et rejouer les requêtes.
Voici le modèle du fichier jwks.json
qui sera hébergé sur notre serveur.
La valeur kid
doit être remplacée par celle de l’en-tête du JWT original.
Voici maintenant l’en-tête modifiée avec le paramètre jku
pointant vers notre serveur :
Reproduire avec BurpSuite :
- Installer les extensions JSON Web Token et JWT Editor Key ;
- Se rendre dans l’onglet JWT Editor Key et générer une nouvelle clé RSA ;
- Créer un fichier
jwks.json
à partir du modèle plus haut. Remplacer lekid
par celui présent dans l’en-tête original du JWT et len
par celui de la clé publique générée précédemment. - Envoyer une requête contenant un token JWT au Repeater ;
- Dans le Repeater, passer sur l’onglet JSON Web Token et modifier le payload du token comme souhaité. Ensuite, rajouter l’attribut
jku
dans l’en-tête, et mettre l’URL pointant vers le fichierjwks.json
en valeur ; - Toujours dans Repeater, dans l’onglet JSON Web Token, cliquer sur Sign en bas de la fenêtre. Sélectionner la clé privée générée et cliquer sur OK. Il est maintenant possible de copier le Serialized JWT et le réutiliser.
Injection dans le paramètre kid
Attribut : Correspond à l’identifiant d’une clé (Key ID).
Principe : Exploiter un path traversal dans la valeur du kid
pour le faire pointer vers un fichier local du serveur, puis signer le token JWT modifié avec le secret correspondant au contenu de ce fichier. Ne fonctionne qu’avec un algorithme symétrique (HS***)
Reproduire avec BurpSuite :
- Installer les extensions JSON Web Token et JWT Editor Key ;
- Se rendre dans l’onglet JWT Editor Key et générer une nouvelle clé symétrique. Dans le cas où le serveur est un Linux, le fichier arbitraire utilisé sera le
/dev/null
par soucis de simplicité. Remplacer alors la valeur dek
par un null-byte (AA==
) et sauvegarder la clé ; - Envoyer une requête contenant un token JWT au Repeater ;
- Dans le Repeater, passer sur l’onglet JSON Web Token et modifier le payload du token comme souhaité ;
- Modifier la valeur du kid en la faisant pointer vers
../../../../../../dev/null
; - Signer le token en cliquant sur Sign et en utilisant la clé symétrique générée précédemment. Il est maintenant possible de copier le Serialized JWT et le réutiliser.
Explication de la vulnérabilité : le kid possède une valeur arbitraire voulue par le développeur. Il peut alors pointer sur une entrée de base de données ou un fichier. Ainsi, si ce paramètre est vulnérable à un path traversal, l’attaquant peut forcer le serveur à utiliser un fichier local prédictible.
Algorithm confusion attacks
Principe : Modifier l’algorithme RSA utilisé par une variante HMAC (HS256/HS384/HS512) et signer le token à l’aide de la clé publique. Ainsi il est ainsi possible de tromper le serveur dans sa fonction de vérification.
Reproduire avec BurpSuite :
- Installer les extensions JSON Web Token et JWT Editor Key ;
- Récupérer la clé publique en interrogeant des endpoints par défaut (
/.well_known/jwks.json
ou juste/jwks.json
). Copier le contenu présent dans lekey
; - Dans BurpSuite, onglet JWT Editor Key, créer une nouvelle clé RSA au format JWT. Coller le contenu de
key
pour remplacer la valeur générée lors de la création de la clé. - Envoyer une requête contenant un token JWT au Repeater ;
- Dans le Repeater, passer sur l’onglet JSON Web Token et modifier le payload du token comme souhaité ;
- Cliquer sur Attack, puis sélectionner HMAC Key Confusion. Sélectionner la clé correspondante et cliquer sur OK. Il est maintenant possible de copier le Serialized JWT et le réutiliser.