· ~4 λεπτά ανάγνωσης

Στήνοντας μια PKI με mutual TLS, και τι κάνει ένας MitM χωρίς αυτή

Μια certificate authority δύο επιπέδων, ένας Apache με κλειδιά ελλειπτικών καμπυλών που δέχεται μόνο clients με πιστοποιητικό, και μια προσομοίωση man-in-the-middle σε απροστάτευτο LAN που δείχνει γιατί υπάρχουν αυτά τα μέτρα.

Στόχος

Να στήσω την υποδομή πιστοποιητικών που θα χρειαζόταν ένας μικρός οργανισμός, να κλειδώσω μια web υπηρεσία πίσω από mutual TLS, και μετά να δω το ίδιο είδος δικτύου από την πλευρά του επιτιθέμενου, για να φανεί τι πάει στραβά όταν το layer 2 και το TLS δεν προστατεύονται. Το αμυντικό κομμάτι είναι ο πυρήνας του lab· η επίθεση υπάρχει για να το δικαιολογήσει.

Οι εντολές και τα screenshots είναι στο repository στο GitHub.

Μια certificate authority δύο επιπέδων

ΕπίπεδοΡόλοςΠού βρίσκεται
Root CA (RSA 4096, κλειδί κρυπτογραφημένο με AES-256)Υπογράφει μόνο την intermediateOffline
Intermediate CA (RSA 4096)Υπογράφει servers και clients καθημερινάOnline, αντικαταστάσιμη
Server (ECDSA P-256)Ο web server ApacheWeb server
Client (RSA 4096, εξαγωγή ως .p12)Ο browser ενός χρήστηΜηχάνημα του χρήστη

Το νόημα του δεύτερου επιπέδου είναι ο περιορισμός της ζημιάς. Αν παραβιαστεί το κλειδί της intermediate, η root την ανακαλεί και εκδίδει νέα· τίποτα που εμπιστεύεται τη root δεν χρειάζεται να αλλάξει. Αν η ίδια η root ήταν online και κλεβόταν, θα έπρεπε να ξαναχτιστεί όλη η ιεραρχία.

Ο server χρησιμοποιεί κλειδί ελλειπτικής καμπύλης (P-256): το ίδιο επίπεδο ασφάλειας με ένα πολύ μεγαλύτερο κλειδί RSA, με μικρότερα handshakes και λιγότερη CPU ανά σύνδεση.

Mutual TLS στον Apache

Το απλό TLS αποδεικνύει τον server στον client. Το mutual TLS κάνει και τον client να αποδείξει ποιος είναι, με πιστοποιητικό από μια CA που εμπιστεύεται ο server:

SSLCertificateFile      server.crt
SSLCertificateKeyFile   server.key
SSLCertificateChainFile chain.crt

SSLCACertificateFile    chain.crt
SSLVerifyClient require
SSLVerifyDepth  2

Το SSLVerifyClient require αρνείται το TLS handshake σε όποιον δεν έχει έγκυρο πιστοποιητικό client· δεν υπάρχει σελίδα σύνδεσης να δεχτεί επίθεση, γιατί η σύνδεση δεν φτάνει ποτέ ως εκεί. Το SSLVerifyDepth 2 επιτρέπει ακριβώς την αλυσίδα client, intermediate, root. Η ρύθμιση ελέγχθηκε μετά με το sslscan.

Η άλλη πλευρά: ένας man-in-the-middle σε απροστάτευτο LAN

Σε ξεχωριστή προσομοίωση, σε απομονωμένο δίκτυο εργαστηρίου, έπαιξα τον επιτιθέμενο απέναντι σε ένα μηχάνημα-θύμα στο ίδιο LAN. Το ARP poisoning έβαλε τον επιτιθέμενο ανάμεσα στο θύμα και το gateway, και μια κλωνοποιημένη σελίδα σύνδεσης σε απλή διεύθυνση HTTP μάζεψε τα credentials που πληκτρολόγησε το θύμα. Τίποτα δεν ήταν εξελιγμένο, και αυτό είναι το δίδαγμα: σε ένα επίπεδο LAN χωρίς προστασία στο layer 2, ένας χρήστης που δεν κοιτά τη γραμμή διευθύνσεων απέχει ένα βήμα από το να δώσει τον κωδικό του.

Η ίδια επίθεση δεν κάνει τίποτα στην υπηρεσία με mTLS παραπάνω: ο επιτιθέμενος δεν μπορεί να παρουσιάσει το πιστοποιητικό του server, ούτε να ολοκληρώσει το handshake χωρίς πιστοποιητικό client.

Μέτρα

Τι έμαθα

Ξαναδιαβάζοντας το δικό μου write-up, θα διόρθωνα και θα πρόσθετα κάποια πράγματα.

Προσωπικό lab σε απομονωμένο εικονικό δίκτυο· η επίθεση έτρεξε μόνο απέναντι στα δικά μου μηχανήματα του lab.

Θέλεις τα configs ή τον κώδικα από αυτό το lab, ή έχεις κάποια ερώτηση; Στείλε μου email στο papas@viotnet.com

← όλα τα άρθρα