Ιστολόγιο

Η Πλάνη της Εμπιστοσύνης: Πώς η Πολυ-ενοικιαστική Ρύθμιση Docker μας Διέρρευσε Δεδομένα (Και Πώς το Διορθώσαμε)

Μάθετε πώς η αφελής ρύθμιση Docker μιας ομάδας οδήγησε σε διαρροή δεδομένων μεταξύ ενοικιαστών και τη στρατηγική απομόνωσης σε στρώματα που την απέτρεψε.

Σύνοψη

Τα κοντέινερ Docker δεν είναι απομονωμένα από προεπιλογή—μοιράζονται τον πυρήνα του υπολογιστή-ξενοδόχου και χωρίς σκόπιμη διαμόρφωση, οι ενοικιαστές μπορούν να παρεμβαίνουν μεταξύ τους. Αυτό το άρθρο περιγράφει ένα πραγματικό σενάριο όπου ένας πάροχος πολυ-ενοικιαστικής φιλοξενίας ανακάλυψε ότι τα κοντέινερ πελατών μπορούσαν να έχουν πρόσβαση στις βάσεις δεδομένων των άλλων λόγω κοινής δικτύωσης και αδύναμων προεπιλογών ασφάλειας. Δείχνουμε τις σταδιακές αλλαγές που διόρθωσαν την παραβίαση: δίκτυα ανά ενοικιαστή, μη-root χρήστες, αφαιρεμένες δυνατότητες, συστήματα αρχείων μόνο για ανάγνωση και προφίλ seccomp. Μια κοινή υπόθεση είναι ότι τα κοντέινερ παρέχουν εγγενώς ισχυρή απομόνωση· το αμφισβητούμε εξηγώντας γιατί οι εικονικές μηχανές προσφέρουν ακόμα πιο δύσκολο όριο και πότε να εξετάσετε μια υβριδική προσέγγιση. Το συμπέρασμα ενισχύει ότι η απομόνωση είναι μια στρωματική άσκηση, όχι ένα μοναδικό κουτί επιλογής.

Το Συμβάν: Όταν τα Κοντέινερ Μιλούν Υπερβολικά

Έχετε ρυθμίσει το Docker σε έναν υπολογιστή για να εκτελείτε πολλούς ιστότοπους πελατών. Κάθε πελάτης έχει το δικό του κοντέινερ—ένα τακτοποιημένο, απομονωμένο περιβάλλον, σωστά; Αυτό νομίζαμε. Μέχρι που ένας συνήθης έλεγχος ασφάλειας αποκάλυψε ότι το κοντέινερ του Πελάτη Α διάβαζε το socket MySQL του κοντέινερ του Πελάτη Β στον ίδιο υπολογιστή. Μοιράζονταν το προεπιλεγμένο δίκτυο bridge. Χειρότερα, τα κοντέινερ εκτελούνταν ως root, οπότε ένας εισβολέας που παραβίαζε ένα μπορούσε να παραβιάσει το socket Docker του υπολογιστή-ξενοδόχου ή το σύστημα αρχείων άλλου κοντέινερ. Η παραβίαση δεν ήταν μια περίπλοκη εκμετάλλευση· ήταν βασική κακή διαμόρφωση. Δεδομένα διέρρευσαν. Η εμπιστοσύνη καταστράφηκε.

Το σενάριο αποτυχίας δεν είναι ασυνήθιστο. Πολλές ομάδες υποθέτουν ότι οι χώροι ονομάτων και οι ομάδες ελέγχου του Docker απομονώνουν αυτόματα τους ενοικιαστές, αλλά υποτιμούν πόσες διόδους διαφυγής παραμένουν ανοιχτές από προεπιλογή. Τα προεπιλεγμένα δίκτυα γέφυρας δεν προσφέρουν καμία απομόνωση δικτύου μεταξύ κοντέινερ. Η εκτέλεση ως root δίνει στο κοντέινερ περισσότερη δύναμη από όση χρειάζεται. Και χωρίς σαφή όρια πόρων, ένας θορυβώδης γείτονας μπορεί να στερήσει από άλλους CPU ή μνήμη.

Βήμα 1: Σταματήστε να Μοιράζεστε ένα Δίκτυο

Η πρώτη μας διόρθωση ήταν να δώσουμε σε κάθε ενοικιαστή το δικό του δίκτυο Docker που ορίζεται από τον χρήστη. Αυτό εμποδίζει τα κοντέινερ να προσεγγίζουν το ένα το άλλο εκτός αν τα συνδέσετε ρητά. Δημιουργήσαμε ένα σενάριο που, για κάθε ενοικιαστή, δημιουργεί ένα αποκλειστικό δίκτυο και επισυνάπτει το κοντέινερ της εφαρμογής του σε αυτό. Το κοντέινερ βάσης δεδομένων ζει στο ίδιο δίκτυο ενοικιαστή, αλλά προσθέσαμε επίσης ένα εσωτερικό δίκτυο μόνο για επικοινωνία εντός ενοικιαστή. Τέλος στην περιέργεια μεταξύ ενοικιαστών.

Απομονώσαμε επίσης τις βάσεις δεδομένων εκτελώντας τες σε ξεχωριστά κοντέινερ στο ίδιο δίκτυο ενοικιαστή, χρησιμοποιώντας ξεχωριστούς όγκους δεδομένων. Αυτό εξασφάλισε ότι ακόμα κι αν ένας εισβολέας έμπαινε στο κοντέινερ εφαρμογής, δεν μπορούσε να υποκλέψει κίνηση βάσης δεδομένων από άλλον ενοικιαστή.

Για μια βαθύτερη ανάλυση των στρατηγικών απομόνωσης δικτύου, δείτε το Μια Πρακτική Λίστα Ελέγχου Ασφάλειας Απομόνωσης Docker για Πολυ-ενοικιαστική Φιλοξενία.

Βήμα 2: Αφαιρέστε Περιττά Προνομιακά Δικαιώματα

Από προεπιλογή, τα κοντέινερ Docker εκτελούνται με ένα περιορισμένο σύνολο δυνατοτήτων Linux, αλλά εξακολουθούν να έχουν περισσότερες από όσες χρειάζονται οι περισσότερες εφαρμογές. Τα κοντέινερ μας εκτελούνταν ως root, επιτρέποντας σε διεργασίες εντός να εκτελούν ενέργειες όπως προσάρτηση συστημάτων αρχείων ή αλλαγή παραμέτρων πυρήνα. Αλλάξαμε σε εκτέλεση της εφαρμογής ως μη-root χρήστης μέσα στο κοντέινερ (χρησιμοποιώντας την οδηγία USER στο Dockerfile) και αφαιρέσαμε όλες τις δυνατότητες εκτός από εκείνες που είναι απολύτως απαραίτητες. Για μια τυπική web εφαρμογή, αυτές μπορεί να είναι μόνο NET_BIND_SERVICE (για σύνδεση σε θύρες κάτω από το 1024) και CHOWN (για εγγραφή σε καταλόγους). Προσθέσαμε επίσης --security-opt no-new-privileges για να αποτρέψουμε την κλιμάκωση προνομίων.

Αυτό το βήμα από μόνο του εξάλειψε πολλούς κοινούς φορείς διαφυγής από κοντέινερ. Ένας εισβολέας που παραβιάζει τον web server δεν μπορεί να εγκαταστήσει πακέτα, να τροποποιήσει δυαδικά αρχεία συστήματος ή να έχει πρόσβαση στο socket Docker του υπολογιστή-ξενοδόχου επειδή η διεργασία δεν έχει τις δυνατότητες CAP_SYS_ADMIN ή CAP_DAC_OVERRIDE.

Βήμα 3: Κλειδώστε το Σύστημα Αρχείων

Τα εγγράψιμα συστήματα αρχείων είναι συχνή επιφάνεια επίθεσης. Κάναμε το ριζικό σύστημα αρχείων μόνο για ανάγνωση (--read-only) για όλα τα κοντέινερ, και στη συνέχεια προσαρτήσαμε προσωρινά συστήματα αρχείων (tmpfs) για καταλόγους που χρειάζονται πρόσβαση εγγραφής, όπως το /tmp και ο κατάλογος cache της εφαρμογής. Αυτό αποτρέπει έναν εισβολέα από το να τροποποιήσει τον κώδικα της εφαρμογής ή να διατηρήσει κακόβουλα δυαδικά αρχεία.

Επιπλέον, χρησιμοποιήσαμε την επιλογή --mount του Docker για να προσαρτήσουμε με δέσμευση ευαίσθητους καταλόγους όπως το socket Docker μόνο όταν είναι απολύτως απαραίτητο—και ποτέ σε κοντέινερ παραγωγής. Η αρχή: αν το κοντέινερ δεν χρειάζεται να γράψει σε ένα μονοπάτι, κάντε το μόνο για ανάγνωση.

Βήμα 4: Εφαρμόστε Προφίλ Seccomp και AppArmor

Τα προεπιλεγμένα προφίλ seccomp ήδη μπλοκάρουν πολλές επικίνδυνες κλήσεις συστήματος, αλλά τα προσαρμόσαμε περαιτέρω για να επιτρέψουμε μόνο τις κλήσεις που χρειάζεται πραγματικά η εφαρμογή μας. Αυτό είναι ένα trade-off επειδή απαιτεί προφίλ της εφαρμογής. Μια απλούστερη προσέγγιση είναι να χρησιμοποιήσετε το προεπιλεγμένο προφίλ seccomp του Docker και στη συνέχεια να προσθέσετε --security-opt seccomp=path/to/profile.json αν χρειάζεστε αυστηρότερους κανόνες. Ομοίως, τα προφίλ AppArmor μπορούν να περιορίσουν τις διεργασίες του κοντέινερ σε συγκεκριμένα μονοπάτια αρχείων και δυνατότητες. Ενεργοποιήσαμε το AppArmor και χρησιμοποιήσαμε ένα προσαρμοσμένο προφίλ που περιόριζε την πρόσβαση μόνο στους καταλόγους δεδομένων της εφαρμογής.

Για έναν ολοκληρωμένο οδηγό αυτών των βημάτων σκλήρυνσης, ανατρέξτε στο Σκλήρυνση Κοντέινερ Docker για Πολυ-ενοικιαστική Φιλοξενία: Ένας Βήμα-προς-Βήμα Οδηγός Απομόνωσης.

Η Αντίθετη Άποψη: Μερικές Φορές Χρειάζονται Εικονικές Μηχανές

Όσο σκληρυμένα κι αν είναι, τα κοντέινερ μοιράζονται τον πυρήνα του υπολογιστή-ξενοδόχου. Μια ευπάθεια πυρήνα μπορεί να σπάσει όλη την απομόνωση ταυτόχρονα. Γι' αυτό πολλές πλατφόρμες με επίγνωση ασφάλειας εκτελούν κοντέινερ μέσα σε ελαφριές εικονικές μηχανές—κάθε ενοικιαστής έχει τον δικό του πυρήνα. Αυτό προσθέτει επιβάρυνση αλλά παρέχει ένα όριο σε επίπεδο υλικού που τα κοντέινερ από μόνα τους δεν μπορούν. Αν οι ενοικιαστές σας διαχειρίζονται δεδομένα πιστωτικών καρτών ή ιατρικά αρχεία, μια υβριδική προσέγγιση (κοντέινερ μέσα σε εικονικές μηχανές) μπορεί να είναι η σωστή επιλογή. Μην υποθέτετε ότι η απομόνωση κοντέινερ είναι επαρκής για το μοντέλο απειλών σας· αξιολογήστε την ευαισθησία των δεδομένων και τις κανονιστικές απαιτήσεις.

Για μια βαθύτερη σύγκριση επιπέδων απομόνωσης, διαβάστε Σχεδιάζοντας μια Πολυ-ενοικιαστική Αρχιτεκτονική Docker: Επιλέγοντας το Σωστό Επίπεδο Απομόνωσης.

Συμπέρασμα: Η Απομόνωση είναι Στοίβα, όχι Διακόπτης

Η διόρθωση δεν ήταν μια μοναδική αλλαγή—ήταν στρωματική: απομόνωση δικτύου, περιορισμένα προνόμια, συστήματα αρχείων μόνο για ανάγνωση και φιλτράρισμα κλήσεων συστήματος. Ακόμα και τότε, αποδεχθήκαμε ότι τέλεια απομόνωση είναι αδύνατη με κοντέινερ που μοιράζονται πυρήνα. Για τους ενοικιαστές μας υψηλότερης ασφάλειας, τους μεταφέραμε σε αποκλειστικούς υπολογιστές. Το μάθημα: μην εμπιστεύεστε καμία προεπιλογή. Ελέγξτε τη ρύθμιση Docker σας σαν να έχει ήδη συμβεί παραβίαση. Η ώρα για κλείδωμα είναι πριν από τη διαρροή, όχι μετά.

Sources (5)