Container Runtimes, Engines, Builders, And Sandboxes
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Μία από τις μεγαλύτερες πηγές σύγχυσης στην ασφάλεια container είναι ότι αρκετά εντελώς διαφορετικά συστατικά συχνά συμπτύσσονται στην ίδια λέξη. Το “Docker” μπορεί να αναφέρεται σε ένα image format, σε ένα CLI, σε ένα daemon, σε ένα build system, σε ένα runtime stack, ή απλώς στην ιδέα των containers γενικά. Για εργασίες ασφάλειας, αυτή η ασάφεια είναι πρόβλημα, γιατί διαφορετικά στρώματα ευθύνονται για διαφορετικές προστασίες. Μια απόδραση που προκαλείται από ένα κακό bind mount δεν είναι το ίδιο πράγμα με μια απόδραση που προκαλείται από ένα σφάλμα χαμηλού επιπέδου στον runtime, και ούτε το ένα είναι το ίδιο με ένα λάθος πολιτικής cluster στο Kubernetes.
Αυτή η σελίδα διαχωρίζει το οικοσύστημα κατά ρόλο ώστε το υπόλοιπο της ενότητας να μπορεί να μιλήσει με ακρίβεια για το πού βρίσκεται πραγματικά μια προστασία ή μια αδυναμία.
OCI As The Common Language
Τα σύγχρονα Linux container stacks συχνά λειτουργούν από κοινού επειδή μιλάνε ένα σύνολο προδιαγραφών OCI. Η OCI Image Specification περιγράφει πώς αναπαριστώνται images και layers. Η OCI Runtime Specification περιγράφει πώς ο runtime θα ξεκινήσει τη διεργασία, συμπεριλαμβανομένων namespaces, mounts, cgroups και ρυθμίσεων ασφαλείας. Η OCI Distribution Specification εναρμονίζει τον τρόπο με τον οποίο τα registries εκθέτουν περιεχόμενο.
Αυτό έχει σημασία γιατί εξηγεί γιατί ένα container image που χτίστηκε με ένα εργαλείο συχνά μπορεί να τρέξει με άλλο, και γιατί αρκετοί engines μπορούν να μοιράζονται τον ίδιο χαμηλού επιπέδου runtime. Εξηγεί επίσης γιατί η συμπεριφορά ασφάλειας μπορεί να μοιάζει παρόμοια σε διαφορετικά προϊόντα: πολλοί από αυτά κατασκευάζουν την ίδια OCI runtime configuration και την παραδίδουν στο ίδιο μικρό σύνολο runtimes.
Low-Level OCI Runtimes
Ο low-level runtime είναι το συστατικό που βρίσκεται πιο κοντά στο όριο του kernel. Είναι το μέρος που στην πράξη δημιουργεί namespaces, γράφει ρυθμίσεις cgroup, εφαρμόζει capabilities και seccomp φίλτρα, και τελικά κάνει execve() της διεργασίας του container. Όταν οι άνθρωποι συζητούν την “container isolation” σε μηχανικό επίπεδο, αυτό είναι το στρώμα για το οποίο συνήθως μιλάνε, ακόμα κι αν δεν το λένε ρητά.
runc
runc είναι ο reference OCI runtime και παραμένει η πιο γνωστή υλοποίηση. Χρησιμοποιείται ευρέως κάτω από Docker, containerd, και πολλές Kubernetes αναπτύξεις. Πολύ έρευνα και υλικό εκμετάλλευσης στο δημόσιο στοχεύει σε runc-style περιβάλλοντα απλώς επειδή είναι συνηθισμένα και επειδή το runc ορίζει τη βάση που πολλοί έχουν στο μυαλό τους όταν φαντάζονται ένα Linux container. Η κατανόηση του runc δίνει στον αναγνώστη ένα ισχυρό νοητικό μοντέλο για την κλασική container isolation.
crun
crun είναι ένας άλλος OCI runtime, γραμμένος σε C και ευρέως χρησιμοποιούμενος σε σύγχρονα Podman περιβάλλοντα. Συχνά επαινέται για την καλή υποστήριξη cgroup v2, την ισχυρή ergonomics για rootless, και το χαμηλότερο overhead. Από άποψη ασφάλειας, το σημαντικό δεν είναι ότι είναι γραμμένο σε διαφορετική γλώσσα, αλλά ότι εξακολουθεί να παίζει τον ίδιο ρόλο: είναι το συστατικό που μετατρέπει την OCI configuration σε ένα τρέχον δέντρο διεργασιών υπό τον kernel. Ένα rootless Podman workflow συχνά καταλήγει να φαίνεται πιο ασφαλές όχι επειδή το crun μαγικά διορθώνει τα πάντα, αλλά επειδή το συνολικό stack γύρω του τείνει να εφαρμόζει περισσότερο user namespaces και την αρχή του least privilege.
runsc From gVisor
runsc είναι ο runtime που χρησιμοποιεί το gVisor. Εδώ το όριο αλλάζει ουσιαστικά. Αντί να περνάει τα περισσότερα syscalls απευθείας στον host kernel με τον συνηθισμένο τρόπο, το gVisor εισάγει ένα επίπεδο userspace kernel που εξομοιώνει ή μεσολαβεί σε μεγάλα τμήματα του Linux interface. Το αποτέλεσμα δεν είναι ένα κανονικό runc container με λίγες επιπλέον σημαίες· είναι ένας διαφορετικός σχεδιασμός sandbox που έχει σκοπό να μειώσει την attack surface του host-kernel. Οι συμβιβασμοί στην συμβατότητα και την απόδοση είναι μέρος αυτού του σχεδιασμού, οπότε περιβάλλοντα που χρησιμοποιούν runsc θα πρέπει να τεκμηριώνονται διαφορετικά από τα κανονικά OCI runtime περιβάλλοντα.
kata-runtime
Kata Containers ωθεί το όριο περαιτέρω εκκινώντας το workload μέσα σε μια lightweight virtual machine. Διοικητικά, αυτό μπορεί να φαίνεται ακόμα σαν μια ανάπτυξη container, και τα orchestration layers μπορεί να το αντιμετωπίζουν ως τέτοιο, αλλά το υποκείμενο όριο απομόνωσης είναι πιο κοντά στην virtualization παρά σε ένα κλασικό host-kernel-shared container. Αυτό κάνει το Kata χρήσιμο όταν ζητείται ισχυρότερη απομόνωση tenant χωρίς να εγκαταλειφτούν οι container-centric ροές εργασίας.
Engines And Container Managers
Αν ο low-level runtime είναι το συστατικό που μιλάει απευθείας με τον kernel, ο engine ή ο manager είναι το συστατικό με το οποίο συνήθως αλληλεπιδρούν οι χρήστες και οι χειριστές. Διαχειρίζεται image pulls, metadata, logs, networks, volumes, lifecycle operations, και την έκθεση API. Αυτό το στρώμα έχει τεράστια σημασία γιατί πολλές πραγματικές παραβιάσεις συμβαίνουν εδώ: η πρόσβαση σε ένα runtime socket ή σε ένα daemon API μπορεί να είναι ισοδύναμη με παραβίαση host ακόμη και αν ο low-level runtime είναι απολύτως υγιής.
Docker Engine
Docker Engine είναι η πιο αναγνωρίσιμη πλατφόρμα container για developers και ένας από τους λόγους που το λεξιλόγιο των containers έγινε τόσο Docker-shaped. Η τυπική διαδρομή είναι docker CLI προς dockerd, το οποίο με τη σειρά του συντονίζει χαμηλότερου επιπέδου συστατικά όπως containerd και έναν OCI runtime. Ιστορικά, οι εγκαταστάσεις Docker ήταν συχνά rootful, και η πρόσβαση στο Docker socket ήταν επομένως ένα πολύ ισχυρό primitive. Γι’ αυτό τόσο πολύ πρακτικό υλικό privilege-escalation επικεντρώνεται στο docker.sock: αν μια διεργασία μπορεί να ζητήσει από το dockerd να δημιουργήσει ένα privileged container, να mountάρει host paths, ή να ενταχθεί σε host namespaces, ίσως να μην χρειάζεται καθόλου έναν kernel exploit.
Podman
Το Podman σχεδιάστηκε γύρω από ένα πιο daemonless μοντέλο. Λειτουργικά, αυτό βοηθάει να ενισχυθεί η ιδέα ότι τα containers είναι απλώς διεργασίες που διαχειρίζονται μέσω τυπικών μηχανισμών Linux αντί μέσω ενός μακροχρόνιου privileged daemon. Το Podman επίσης έχει πολύ ισχυρότερη ιστορία για rootless σε σχέση με τις κλασικές Docker αναπτύξεις που πολλοί έμαθαν πρώτοι. Αυτό δεν καθιστά αυτόματα το Podman ασφαλές, αλλά αλλάζει το προεπιλεγμένο προφίλ κινδύνου σημαντικά, ειδικά όταν συνδυάζεται με user namespaces, SELinux, και crun.
containerd
containerd είναι ένα βασικό συστατικό διαχείρισης runtime σε πολλά σύγχρονα stacks. Χρησιμοποιείται κάτω από Docker και είναι επίσης ένας από τους κυρίαρχους Kubernetes runtime backends. Εκθέτει ισχυρά APIs, διαχειρίζεται images και snapshots, και αναθέτει τη τελική δημιουργία της διεργασίας σε έναν low-level runtime. Οι συζητήσεις ασφάλειας γύρω από το containerd πρέπει να τονίζουν ότι η πρόσβαση στο containerd socket ή στη λειτουργικότητα ctr/nerdctl μπορεί να είναι εξίσου επικίνδυνη με την πρόσβαση στο Docker API, ακόμα κι αν το interface και η ροή εργασίας φαίνονται λιγότερο “φιλικά προς τον developer”.
CRI-O
CRI-O είναι πιο στοχευμένο από το Docker Engine. Αντί να είναι μια πλατφόρμα γενικής χρήσης για developers, έχει χτιστεί γύρω από την καθαρή υλοποίηση του Kubernetes Container Runtime Interface. Αυτό το κάνει ιδιαίτερα συνηθισμένο σε Kubernetes distributions και σε περιοχές με έντονο SELinux όπως το OpenShift. Από άποψη ασφάλειας, αυτό το στενότερο πεδίο είναι χρήσιμο επειδή μειώνει την εννοιολογική ακαταστασία: το CRI-O είναι πολύ μέρος του στρώματος “run containers for Kubernetes” παρά μιας πλατφόρμας για τα πάντα.
Incus, LXD, And LXC
Συστήματα Incus/LXD/LXC αξίζουν να διαχωριστούν από τα Docker-style application containers γιατί συχνά χρησιμοποιούνται ως system containers. Ένα system container συνήθως αναμένεται να μοιάζει περισσότερο με μια ελαφριά μηχανή με πληρέστερο userspace, μακροχρόνιες υπηρεσίες, πλουσιότερη έκθεση συσκευών και πιο εκτεταμένη ενσωμάτωση με τον host. Οι μηχανισμοί απομόνωσης είναι ακόμα kernel primitives, αλλά οι επιχειρησιακές προσδοκίες είναι διαφορετικές. Ως αποτέλεσμα, οι κακορυθμίσεις εδώ συχνά μοιάζουν λιγότερο με “κακά defaults εφαρμογής-container” και περισσότερο σαν λάθη σε ελαφριά virtualization ή σε ανάθεση host.
systemd-nspawn
Το systemd-nspawn καταλαμβάνει μια ενδιαφέρουσα θέση γιατί είναι native σε systemd και πολύ χρήσιμο για testing, debugging και λειτουργία περιβαλλόντων που μοιάζουν με OS. Δεν είναι ο κυρίαρχος cloud-native production runtime, αλλά εμφανίζεται αρκετά συχνά σε εργαστήρια και περιβάλλοντα προσανατολισμένα σε διανομές ώστε να αξίζει μνεία. Για ανάλυση ασφάλειας, είναι μια ακόμη υπενθύμιση ότι η έννοια “container” εκτείνεται σε πολλά οικοσυστήματα και επιχειρησιακά στυλ.
Apptainer / Singularity
Το Apptainer (πρώην Singularity) είναι συνηθισμένο σε ερευνητικά και HPC περιβάλλοντα. Οι υποθέσεις εμπιστοσύνης του, η ροή εργασίας του χρήστη και το execution model διαφέρουν με σημαντικούς τρόπους από τα Docker/Kubernetes-centric stacks. Ειδικά, αυτά τα περιβάλλοντα συχνά ενδιαφέρονται βαθιά να επιτρέψουν σε χρήστες να τρέξουν πακετοποιημένα workloads χωρίς να τους δώσουν ευρείες privileged container-management δυνάμεις. Αν ένας εξεταστής υποθέσει ότι κάθε container περιβάλλον είναι βασικά “Docker σε ένα server”, θα καταλάβει λάθος αυτές τις αναπτύξεις.
Build-Time Tooling
Πολλές συζητήσεις ασφάλειας μιλούν μόνο για το runtime, αλλά το build-time tooling επίσης έχει σημασία γιατί καθορίζει τα περιεχόμενα των images, την έκθεση build secrets, και πόσο εμπιστευτικό context ενσωματώνεται στο τελικό artifact.
BuildKit και docker buildx είναι σύγχρονα build backends που υποστηρίζουν χαρακτηριστικά όπως caching, secret mounting, SSH forwarding, και multi-platform builds. Αυτά είναι χρήσιμα χαρακτηριστικά, αλλά από άποψη ασφάλειας δημιουργούν επίσης σημεία όπου secrets μπορούν να leak σε image layers ή όπου ένα υπερβολικά ευρύ build context μπορεί να εκθέσει αρχεία που δεν θα έπρεπε ποτέ να έχουν συμπεριληφθεί. Buildah παίζει παρόμοιο ρόλο σε OCI-native οικοσυστήματα, ειδικά γύρω από Podman, ενώ Kaniko χρησιμοποιείται συχνά σε CI περιβάλλοντα που δεν θέλουν να δώσουν ένα privileged Docker daemon στην build pipeline.
Το βασικό μάθημα είναι ότι η δημιουργία image και η εκτέλεση image είναι διαφορετικές φάσεις, αλλά ένα αδύναμο build pipeline μπορεί να δημιουργήσει μια αδύναμη runtime στάση πολύ πριν ξεκινήσει το container.
Orchestration Is Another Layer, Not The Runtime
Το Kubernetes δεν πρέπει να ταυτίζεται νοητικά με τον ίδιο τον runtime. Το Kubernetes είναι ο orchestrator. Προγραμματίζει Pods, αποθηκεύει desired state, και εκφράζει πολιτική ασφαλείας μέσω της διαμόρφωσης workload. Ο kubelet στη συνέχεια μιλάει σε μια CRI υλοποίηση όπως containerd ή CRI-O, η οποία με τη σειρά της καλεί έναν low-level runtime όπως runc, crun, runsc, ή kata-runtime.
Αυτός ο διαχωρισμός έχει σημασία γιατί πολλοί άνθρωποι εσφαλμένα αποδίδουν μια προστασία στο “Kubernetes” όταν στην πραγματικότητα εφαρμόζεται από τον node runtime, ή κατηγορούν τα “containerd defaults” για συμπεριφορά που προήλθε από ένα Pod spec. Στην πράξη, η τελική στάση ασφάλειας είναι μια σύνθεση: ο orchestrator ζητάει κάτι, το runtime stack το μεταφράζει, και τελικά ο kernel το επιβάλλει.
Why Runtime Identification Matters During Assessment
Αν εντοπίσετε νωρίς τον engine και τον runtime, πολλές μεταγενέστερες παρατηρήσεις γίνονται πιο εύκολες στην ερμηνεία. Ένα rootless Podman container υποδηλώνει ότι user namespaces πιθανώς είναι μέρος της ιστορίας. Ένα Docker socket που έχει mountαριστεί σε ένα workload υποδηλώνει ότι μια API-driven privilege escalation είναι ρεαλιστική διαδρομή. Ένας CRI-O/OpenShift node θα πρέπει αμέσως να σας κάνει να σκεφτείτε για SELinux labels και restricted workload policy. Ένα gVisor ή Kata περιβάλλον θα πρέπει να σας κάνει πιο προσεκτικούς σχετικά με την υπόθεση ότι ένα κλασικό runc breakout PoC θα συμπεριφερθεί το ίδιο.
Γι’ αυτό ένα από τα πρώτα βήματα στην αξιολόγηση container θα πρέπει πάντα να απαντά σε δύο απλές ερωτήσεις: ποιο component διαχειρίζεται το container και ποιος runtime πραγματικά εκκίνησε τη διεργασία. Μόλις αυτές οι απαντήσεις είναι ξεκάθαρες, το υπόλοιπο του περιβάλλοντος συνήθως γίνεται πολύ πιο εύκολο να τοποθετηθεί λογικά.
Runtime Vulnerabilities
Όχι κάθε container escape προέρχεται από κακή διαμόρφωση του χειριστή. Μερικές φορές ο ίδιος ο runtime είναι το ευάλωτο συστατικό. Αυτό έχει σημασία γιατί ένα workload μπορεί να τρέχει με μια φαινομενικά προσεκτική διαμόρφωση και παρ’ όλα αυτά να εκτίθεται μέσω ενός σφάλματος χαμηλού επιπέδου στον runtime.
Το κλασικό παράδειγμα είναι το CVE-2019-5736 στο runc, όπου ένα κακόβουλο container μπορούσε να κάνει overwrite το host runc binary και στη συνέχεια να περιμένει για ένα μετέπειτα docker exec ή παρόμοια κλήση runtime για να ενεργοποιήσει κώδικα υπό τον έλεγχο του επιτιθέμενου. Η διαδρομή εκμετάλλευσης είναι πολύ διαφορετική από ένα απλό bind-mount ή λάθος capability επειδή καταχράται τον τρόπο με τον οποίο ο runtime επανεισάγει το χώρο διεργασίας του container κατά το χειρισμό του exec.
Ένα ελάχιστο workflow αναπαραγωγής από την προοπτική red-team είναι:
go build main.go
./main
Στη συνέχεια, από τον host:
docker exec -it <container-name> /bin/sh
Το βασικό συμπέρασμα δεν είναι η ακριβής ιστορική υλοποίηση του exploit, αλλά η σημασία για την αξιολόγηση: εάν η έκδοση του runtime είναι ευάλωτη, η συνήθης εκτέλεση κώδικα εντός του container μπορεί να είναι αρκετή για να υπονομεύσει το host ακόμη και όταν η εμφανής διαμόρφωση του container δεν φαίνεται προφανώς αδύναμη.
Πρόσφατα runtime CVEs όπως το CVE-2024-21626 στο runc, BuildKit mount races, και containerd parsing bugs ενισχύουν το ίδιο σημείο. Η έκδοση του runtime και το επίπεδο patch είναι μέρος του ορίου ασφαλείας, όχι απλώς θέμα συντήρησης.
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.


