# JWT security testing: alg:none, algorithm confusion και αδύναμα secrets

**URL:** <https://forum.iguru.gr/t/jwt-security-testing-alg-none-algorithm-confusion-secrets/182>\
**Category:** /pentesting\
**Created:** [November 10, 2026, 5:52pm UTC](https://forum.iguru.gr/t/jwt-security-testing-alg-none-algorithm-confusion-secrets/182 "2026-11-10T17:52:09Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://forum.iguru.gr/uploads/default/original/1X/96d4854ffa9560674a510c0710f31f15e4cbc5cd.png) [@system](https://forum.iguru.gr/u/system)\
**Post date:** [November 10, 2026, 5:52pm UTC](https://forum.iguru.gr/t/jwt-security-testing-alg-none-algorithm-confusion-secrets/182/1 "2026-11-10T17:52:09Z")

</div>

Τα JSON Web Tokens είναι παντού στα σύγχρονα APIs: ένα υπογεγραμμένο token που ο client κουβαλά σε κάθε αίτημα, και ο server το εμπιστεύεται χωρίς να κρατά session state. Ακριβώς επειδή ο server «εμπιστεύεται την υπογραφή», τα λάθη στην επαλήθευσή της είναι κρίσιμα: ένα κακώς ελεγμένο JWT σημαίνει πλαστοπροσωπία οποιουδήποτε χρήστη. Ακολουθεί η μεθοδολογία ελέγχου, πάντα σε συστήματα με γραπτή εξουσιοδότηση και δοκιμαστικούς λογαριασμούς.

## Η ανατομία ενός JWT

Τρία μέρη χωρισμένα με τελείες, κωδικοποιημένα σε Base64URL: **header** (ο αλγόριθμος, π.χ. {“alg”:“HS256”,“typ”:“JWT”}), **payload** (τα claims: ποιος είναι ο χρήστης, πότε λήγει, τι ρόλο έχει) και **signature**. Σημαντικό: τα δύο πρώτα μέρη είναι απλώς κωδικοποιημένα, όχι κρυπτογραφημένα. Οποιοσδήποτε τα διαβάζει. Η ασφάλεια στηρίζεται αποκλειστικά στην **υπογραφή**.

Δύο οικογένειες αλγορίθμων: **συμμετρική** (HS256, ένα κοινό μυστικό που υπογράφει και επαληθεύει) και **ασύμμετρη** (RS256, ιδιωτικό κλειδί υπογράφει, δημόσιο επαληθεύει).

## Οι κλασικές επιθέσεις

- **alg: none.** Μερικές παλιές ή κακώς ρυθμισμένες βιβλιοθήκες δέχονται token με “alg”:“none” και **κενή υπογραφή**. Αλλάζετε τα claims, βάζετε none, αφαιρείτε την υπογραφή, και αν ο server το δεχτεί, έχετε πλήρη πλαστοπροσωπία.

- **Algorithm confusion (RS256 προς HS256).** Αν ο server περιμένει RS256 αλλά δεν επιβάλλει τον αλγόριθμο, μπορεί κανείς να φτιάξει ένα token HS256 και να το υπογράψει χρησιμοποιώντας το **δημόσιο** κλειδί του server ως κοινό μυστικό. Ο server, που επαληθεύει με το ίδιο δημόσιο κλειδί, το δέχεται. Το δημόσιο κλειδί συχνά είναι όντως δημόσιο: σε ένα endpoint JWKS, σε ένα πιστοποιητικό, στο documentation.

- **Αδύναμο secret σε HS256.** Αν το κοινό μυστικό είναι μια αδύναμη λέξη, σπάει offline. Εργαλεία όπως το hashcat (mode 16500) δοκιμάζουν εκατομμύρια secrets το δευτερόλεπτο πάνω σε ένα μόνο υποκλαπέν token, χωρίς κανένα αίτημα στον server.

- **Παραποίηση του `kid`.** Το πεδίο kid (key ID) δείχνει ποιο κλειδί να χρησιμοποιηθεί. Αν περνά ανεξέλεγκτο σε query ή path, μπορεί να οδηγήσει σε SQL injection, path traversal (π.χ. kid που δείχνει σε /dev/null, οπότε το secret γίνεται κενό), ή command injection.

- **Ενσωματωμένο ή απομακρυσμένο κλειδί (`jwk`, `jku`, `x5u`).** Τρία πεδία του header μπορούν να υποδείξουν το κλειδί επαλήθευσης. Το jwk ενσωματώνει δημόσιο κλειδί μέσα στο ίδιο το token (CVE-2018-0114): φτιάχνετε δικό σας ζεύγος κλειδιών, βάζετε το δημόσιό σας στο jwk, υπογράφετε με το ιδιωτικό σας, και αν ο server το εμπιστευτεί, περνά. Τα jku (JWK Set URL) και x5u (X.509 URL) δείχνουν σε απομακρυσμένο JWKS: αν ο server τα ακολουθεί χωρίς έλεγχο, τα στρέφετε σε δικό σας server, ή τα χρησιμοποιείτε για SSRF.

- **Αγνοημένο expiry.** Αν ο server δεν ελέγχει το claim exp, ένα υποκλαπέν token ισχύει για πάντα.

## Η ροή του ελέγχου

Αποκτήστε ένα έγκυρο token ως χαμηλόβαθμος χρήστης. Στο Burp, το extension **JWT Editor** (ή το jwt\_tool στη γραμμή εντολών) αποκωδικοποιεί, τροποποιεί και υπογράφει ξανά tokens. Δοκιμάστε με τη σειρά:

1. **Αλλάξτε ένα claim χωρίς να αγγίξετε την υπογραφή** (π.χ. “role”:“admin”). Αν γίνει δεκτό, η υπογραφή δεν ελέγχεται καθόλου. Κρίσιμο εύρημα.

2. **Δοκιμάστε `alg:none`** σε όλες τις παραλλαγές (None, NONE, nOnE: ορισμένοι έλεγχοι είναι case-sensitive).

3. **Αν ο server χρησιμοποιεί RS256,** βρείτε το δημόσιο κλειδί (δοκιμάστε /.well-known/jwks.json) και επιχειρήστε algorithm confusion προς HS256.

4. **Αν χρησιμοποιεί HS256,** δοκιμάστε offline brute force του secret με μια λίστα συνηθισμένων τιμών.

5. **Πειράξτε τα πεδία κλειδιού του header.** Δοκιμάστε injection στο kid (SQL, path traversal, /dev/null), ενσωμάτωση δικού σας κλειδιού με jwk (-X i στο jwt\_tool), και παραπομπή των jku/x5u σε δικό σας JWKS (-X s). Το JWT Editor του Burp τα αυτοματοποιεί (Attack → Embedded JWK, jku/x5u payloads).

6. **Ελέγξτε το `exp`:** στείλτε ένα ληγμένο token και δείτε αν γίνεται δεκτό.

Προσοχή στα ψευδώς θετικά: μια απάντηση 200 δεν σημαίνει πάντα επιτυχία. Επιβεβαιώστε ότι όντως εκτελέσατε ενέργεια ως άλλος χρήστης.

## Οι σωστές άμυνες

- **Επιβάλλετε έναν συγκεκριμένο αλγόριθμο** στην επαλήθευση· μη δέχεστε τον αλγόριθμο από το header του token.

- **Ποτέ `none` σε production.**

- **Ισχυρά, τυχαία secrets** για HS256 (τουλάχιστον 256 bit), ή ασύμμετρα κλειδιά.

- **Ελέγχετε πάντα `exp`,** και ιδανικά iss και aud.

- **Σύντομη διάρκεια ζωής** και μηχανισμός ανάκλησης (refresh tokens, denylist), γιατί ένα JWT δεν «ακυρώνεται» από μόνο του.

- **Αγνοήστε ή ελέγξτε αυστηρά τα `kid`/`jku`/`x5u`:** allowlist για το kid, και μόνο γνωστά, προκαθορισμένα URLs για jku/x5u.

- **Χρησιμοποιήστε συντηρημένη βιβλιοθήκη** που δεν έχει τα παραπάνω ελαττώματα· μην υλοποιείτε μόνοι σας την επαλήθευση.

## Για συζήτηση

1. Ποια εργαλεία χρησιμοποιείτε για JWT testing, το JWT Editor του Burp, το jwt\_tool, ή κάτι άλλο;

2. Έχετε συναντήσει algorithm confusion σε πραγματικό engagement; Πόσο εύκολο ήταν να βρείτε το δημόσιο κλειδί;

3. Προτιμάτε σύντομης διάρκειας JWTs με refresh tokens, ή επιστροφή σε server-side sessions; Πού βάζετε το όριο;
