🗝️JSON Web Token
JWT
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
JWK (JSON Web Key) est un format standardisé permettant de représenter les clés sous forme d'objet JSON.
Prérequis: Extension JWT Editor de Burp Suite
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
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)
Prérequis: Extension JWT Editor de Burp Suite
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
Ecrivez votre exploit sur votre serveur d'attaque avec les données copiées
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
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
Payload
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
Prérequis: Extension JWT Editor de Burp Suite
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)
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:
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
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
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êtecty
pour changer le type de contenu entext/xml
ouapplication/x-java-serialized-object
, ce qui peut potentiellement activer de nouveaux vecteurs pour les attaques XXE ou de désérialisation.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 vue précédemment. Ressources:
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
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.
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.
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"
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
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
Dernière mise à jour