Podman-Rootless-Container und der Copy-Fail-Exploit
(garrido.io)- CVE-2026-31431 Copy Fail ermöglicht es lokalen nicht privilegierten Benutzern, eine
root-Shell zu erhalten, und erlaubt auch innerhalb von Podman-Rootless-Containern eine Privilegieneskalation zu internemroot - Podman-Rootless-Container kombinieren User Namespaces, UID-Isolierung und Linux Capabilities, um internes
rootim Container auf einen nicht privilegierten Benutzer auf dem Host abzubilden und Host-Berechtigungen zu begrenzen - In Tests konnte der Benutzer
fooin einem rootless non-root Container nach Ausführung von Copy Fail zwar zu internemrootim Container werden, die Rechte blieben jedoch auf den Umfang des nicht privilegierten Host-Benutzersbarbeschränkt, und Host-Dateien im Besitz vonrootkonnten nicht gelesen werden - Wenn
--security-opt=no-new-privilegesoder--cap-drop=allangewendet wird, bleibt die Shell auch nach Ausführung von Copy Fail beim Benutzerfoound mit Capabilitiesnone, wodurch eine unmittelbare Erlangung einerroot-Shell und eine Capability-Eskalation verhindert werden können - Die Auswirkungen von Copy Fail können über den Lebenszyklus des Containers hinaus bestehen bleiben, daher sind Kernel-Patches und ein Neustart erforderlich; außerdem sollte Defense in Depth mit einem schreibgeschützten Root-Dateisystem, cgroups-Ressourcenlimits, schlanken Runtime-Images und Firewalls gemeinsam eingesetzt werden
Reichweite der Exponierung von Copy Fail und Podman-Rootless-Containern
- CVE-2026-31431 wurde am 29. April auf copy.fail veröffentlicht; durch Ausführung des veröffentlichten Python-Skripts kann ein lokaler nicht privilegierter Benutzer eine
root-Shell erhalten - Copy Fail kann auch innerhalb von Linux-Containern ausgenutzt werden, und auch in Podman-Rootless-Containern ist der Erhalt einer internen
root-Shell im Container möglich - In den Tests war Container-
rootauf Host-Ebene auf den Berechtigungsumfang des nicht privilegierten Benutzersbarbegrenzt, der den Container gestartet hatte - Die Rootless-Implementierung von Podman kombiniert User Namespaces, UID-Isolierung und Linux Capabilities, um die Host-Berechtigungen von Container-Prozessen zu begrenzen
- Copy Fail zeigt, dass auch Rootless-Container nicht immun gegen die Schwachstelle sind, dass sich der Angriffsradius nach einer Kompromittierung mit Podman-Einstellungen jedoch verringern lässt
Funktionsweise von Rootless-Containern
-
Grundbeispiel: Nicht privilegierter Benutzer
barstartet einen HTTP-Server- Die Beispielumgebung besteht daraus, dass der nicht privilegierte Benutzer
barmit UID1001mit Podman ein aufubuntu:latestbasierendes Image baut undpython3 -m http.serverausführt - Auf dem Host ist mit
pszu sehen, dass derpython3-Prozess als Benutzerbarausgeführt wird - Podman verwendet ein Fork/Exec-Modell, daher werden Container-Prozesse zu Nachkommen des Prozesses
podman run; durch die übliche UID-Isolierung lassen sich Container-Prozesse von Host-rootoder anderen Benutzern trennen - In einer typischen Docker-Konfiguration kann auch dann, wenn ein nicht privilegierter Benutzer
docker runausführt, der Docker-Client mit einem Daemon mit Root-Rechten kommunizieren, und da der Daemon letztlich den Container-Prozess erzeugt, kann dieser auf dem Host alsrooterscheinen
- Die Beispielumgebung besteht daraus, dass der nicht privilegierte Benutzer
-
Rootless rootful
- Wenn ein Container-Image keine explizite
USER-Anweisung oder kein--user-Flag enthält, wird der Container-Befehl gewöhnlich intern alsrootausgeführt - In der Ausgabe von
podman topwird der HTTP-Server-Prozess auf den Host-Benutzer1001abgebildet, intern im Container jedoch alsrootausgeführt - Diese Konfiguration ist auf dem Host nicht privilegiert, innerhalb des Containers jedoch
rootund befindet sich somit im Zustand rootless rootful
- Wenn ein Container-Image keine explizite
-
User Namespaces
- Podman-Rootless-Container verwenden User Namespaces, um UID/GID innerhalb und außerhalb des Containers unterschiedlich abzubilden
- Im Beispiel wird internes
rootmit UID0im Container aufbarmit der Host-UID1001abgebildet - Die Einstellung
bar:165536:65536in/etc/subuidlegt den UID-Bereich fest, der den Namespace-Prozessen vonbarzugewiesen werden kann - Im Beispiel können zusätzlich zur UID
1001vonbarUIDs von165536bis231072den Prozessen vonbarzugewiesen werden - Wenn
sleepals interner Container-Benutzerwww-dataausgeführt wird, ist es internwww-data, auf dem Host wird es jedoch als165568angezeigt - Wenn man mit
podman unshareden User Namespace betritt, erscheint das auf dem Hostbar:bargehörende Home-Verzeichnis innerhalb des Namespace alsroot:root - Docker unterstützt ebenfalls User Namespaces, erfordert dafür jedoch eine separate Konfiguration und erlaubt nur einen einzigen User Namespace, während Podman die Rootless-Container jedes UNIX-Benutzers im jeweiligen User Namespace dieses Benutzers ausführt
-
Privilegierte Operationen und Linux Capabilities
- Podman verwendet Linux Capabilities, um Container-Prozessen fein granulierte Root-Rechte zu gewähren
- Während des Image-Builds werden Vorgänge wie
apt installdurch eine Kombination von Capabilities wiechown,dac_override,fowner,setgid,setuid,net_bind_serviceundsys_chrootmöglich - Wenn mit
podman build --cap-drop=allalle Capabilities entfernt werden, schlägt der Image-Build fehl, weilaptbeisetgroups,setegid,seteuid,chownund Ähnlichem scheitert - Es ist auch möglich, nur die benötigten Capabilities hinzuzufügen; im Beispiel werden
CAP_SETUID,CAP_SETGID,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNERhinzugefügt, um die Paketinstallation durchzuführen - Der HTTP-Server im Standardlauf wird intern im Container als
rootausgeführt und besitzt viele effektive Capabilities wieCHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,NET_BIND_SERVICE,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT - Der HTTP-Server benötigt diese Rechte nicht, daher können mit
podman run --cap-drop=allalle Capabilities entfernt werden; inpodman topwerden die effektiven Capabilities dann alsnoneangezeigt
-
Rootless non-root
- Um den HTTP-Server auch innerhalb des Containers als nicht privilegierten Benutzer auszuführen, kann ein vorhandener Benutzer aus
/etc/passwd, etwawww-data, verwendet oder während des Image-Builds ein eigener Benutzer angelegt werden - Im Beispiel werden ein Benutzer und eine Gruppe
foomit UID1002erstellt, Lesezugriff auf/var/www/htmlgewährt und anschließendUSER foo:foogesetzt - Wenn dieses Image mit
--cap-drop=allausgeführt wird, läuft der Prozess intern im Container alsfoo, mit Host-UID166537und effektiven Capabilitiesnone - Container-Prozesse sollten mit den minimal nötigen Rechten ausgeführt werden; wenn
foobeispielsweise an den privilegierten Port80binden muss, sollte--cap-add=CAP_NET_BIND_SERVICEhinzugefügt werden - Die Ausführungsarten von Containern lassen sich in vier Kategorien einteilen
- Host-Benutzer
root+ Container-root: root rootful - Host-Benutzer
root+ nicht privilegierter Container-Benutzer: root non-root - Nicht privilegierter Host-Benutzer + Container-
root: rootless rootful - Nicht privilegierter Host-Benutzer + nicht privilegierter Container-Benutzer: rootless non-root
- Host-Benutzer
- Podman macht das Starten von rootless rootful Containern einfach, und wenn sich Container-Prozesse als nicht privilegierte Benutzer ausführen lassen, ist auch eine rootless non-root Konfiguration vergleichsweise leicht umzusetzen
- Um den HTTP-Server auch innerhalb des Containers als nicht privilegierten Benutzer auszuführen, kann ein vorhandener Benutzer aus
Bind-Mounts und UID-Isolierung
- Wenn ein Host-Verzeichnis in den Container gemountet wird, hängt der Zugriff auf Dateien, die Host-
root, Host-baroder Namespace-foogehören, vom UID-Mapping ab. - Im Beispiel werden im Verzeichnis
/var/lib/bar/testdie Dateiroot.txtim Besitz von Host-rootundbar.txtim Besitz von Host-barerstellt und im Container nach/testmit Lese-/Schreibrechten gemountet. - Wird der Container als
fooausgeführt, erscheint die Datei im Besitz von Host-barim Container alsroot:root, während die Datei im Besitz von Host-root, da sie nicht in den Namespace gemappt ist, alsnobody:nogrouperscheint. fooim Container kann wederbar.txtnochroot.txtlesen, und rootless non-root bietet zusätzliche Isolierung gegenüber rootless rootful.foo.txt, dasfooim gemounteten Verzeichnis erstellt, erscheint auf dem Host als Datei im Besitz der UID166537, und der Host-Benutzerbarkann den Inhalt dieser Datei nicht lesen.- Wird der Container als internes
rootausgeführt, kann Namespace-rootdie Dateien im Besitz von Host-barund vonfoolesen, aber nicht die Dateiroot.txtim Besitz von Host-root. - Wird bei der Ausführung als internes
rootzusätzlich--cap-drop=allangewendet, kann auch die Datei vonfoonicht gelesen werden, und nur die Datei im Besitz von Host-barbleibt lesbar.
Copy-Fail-Test
-
Testbedingungen
- Für den Copy-Fail-Test wurde die Exploit-Version des ursprünglich veröffentlichten Commits
8e918b5verwendet. - Das Beispiel-Container-Image erweitert ein vorhandenes HTTP-Server-Image um
curl, damit das Exploit-Skript im Container heruntergeladen werden kann. - Das Image wird unter dem Namen
copyfailgebaut. - Der Test-Kernel ist Debians
6.12.74+deb13+1-amd64; nach Debian-Maßstab gelten neuere Versionen unterhalb von6.12.85noch als ungepatchte Kernel, die dafür verwendet werden können. - Wenn der unprivilegierte Benutzer
foonormalerweisesuaufruft, wird dasroot-Passwort verlangt. - In jedem Test lädt der Container-Benutzer das Copy-Fail-Skript nach
/tmpherunter, führt es aus und ruft bei erfolgreichem Erlangen einerroot-Shellsleepauf. - Da Copy Fail über den Container-Lebenszyklus hinaus bestehen bleibt, wird die VM vor jedem Test neu gestartet.
- Für den Copy-Fail-Test wurde die Exploit-Version des ursprünglich veröffentlichten Commits
-
Ergebnis bei rootless rootful
- Wenn der Container mit
--user=rootgestartet wird, sind die Prozesse im Container bereitsroot. - Wird in diesem Zustand das Copy-Fail-Skript ausgeführt und
suaufgerufen, erhält man zwar eine Shell mituid=0(root), aber da der Benutzerrootohnehin ohne Passwort persueine weitere root-Shell öffnen kann, bringt Copy Fail praktisch keinen zusätzlichen Effekt. - In
podman topwerden/bin/bash,python3 copy_fail_exp.py,suundsleepjeweils als internes Container-rootund als Host-Benutzer1001angezeigt. - Es bleibt derselbe Capability-Satz erhalten; sichtbar sind
CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,NET_BIND_SERVICE,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT. - Internes
rootkann im gemounteten/testbar.txtundfoo.txtlesen, aber nichtroot.txt, das Host-rootgehört.
- Wenn der Container mit
-
Ergebnis bei rootless non-root
- Wird der Container als
fooausgeführt und danach das Copy-Fail-Skript gestartet undsuaufgerufen, erfolgt eine Rechteausweitung zu internem Container-root. - Das
idder resultierenden Shell wird alsuid=0(root) gid=1002(foo) groups=1002(foo)angezeigt. - In
podman toperscheinen das anfängliche/bin/bash, der Prozess zur Ausführung des Exploits und dersu-Aufruf mit Host-UID166537, Container-Benutzerfoound Capabilitiesnone. - Nach der Rechteausweitung werden
[sh]undsleepals Host-Benutzer1001und Container-Benutzerrootangezeigt und erhalten denselben Capability-Satz wie bei rootless rootful. - Auch das eskalierte Container-
rootkannroot.txtim Besitz von Host-rootnicht lesen. - In diesem Zustand ist der Container zwar kompromittiert, aber der Angriffsbereich bleibt auf den Container und das beschränkt, was der unprivilegierte Host-Benutzer
bartun kann.
- Wird der Container als
-
Ergebnis bei Anwendung von
no-new-privileges- Mit
--security-opt=no-new-privilegeskann Podman verhindern, dass Container-Prozesse mehr Rechte erhalten als beim Start. - Wird diese Option auf einen rootless non-root-Container angewendet und Copy Fail ausgeführt, öffnet sich zwar eine Shell, sie bleibt jedoch im Zustand
uid=1002(foo). - Auch in
podman topbleiben alle Prozesse bei Host-UID166537, Container-Benutzerfoound Capabilitiesnone. - Auch im gemounteten
/testkannfoonur die eigene Datei lesen und wederbar.txtnochroot.txt. - Der Container ist kompromittiert, bleibt aber auf den internen unprivilegierten Benutzer
fooohne Capabilities beschränkt.
- Mit
-
Ergebnis bei Anwendung von
--cap-drop=all- Auch wenn ein rootless non-root-Container mit
--cap-drop=allgestartet wird, besitztfooursprünglich ohnehin keine Capabilities. - Wird in diesem Zustand Copy Fail ausgeführt und
suaufgerufen, bleibt die geöffnete Shell beiuid=1002(foo). - Auch in
podman topbleiben/bin/bash, die Exploit-Ausführung,su, die Shell undsleepsämtlich beifoound Capabilitiesnone. - Der Exploit scheitert daran, eine
root-Shell zu erlangen, undfookann in/testnur die eigene Datei lesen. - Dieses Ergebnis ähnelt dem Test mit
no-new-privileges; beide Maßnahmen können zusammen verwendet werden, um die Exponierung von Capabilities wirksam zu verringern.
- Auch wenn ein rootless non-root-Container mit
-
Persistenz des Exploits
- Der unmittelbare Gewinn einer
root-Shell und von Capabilities konnte zwar mitno-new-privilegesoder--cap-drop=allverhindert werden, die Wirkung des Exploits selbst bleibt jedoch bestehen. - Wird später ein neuer Container ohne Capability-Beschränkung gestartet, kann der unprivilegierte Container-Benutzer
fooallein durch Aufruf vonsuzu Container-rootwerden. - Daher sind ein Kernel-Patch und ein Neustart weiterhin erforderlich.
- Der unmittelbare Gewinn einer
Strategien zur tiefengestaffelten Verteidigung
-
Schreibgeschützte Images
- Wenn
--read-onlyzupodman runhinzugefügt wird, wird das Root-Dateisystem des Containers schreibgeschützt eingehängt - Podman bindet standardmäßig einige Verzeichnisse wie
/tmp,/runund/var/tmpmit Schreibrechten ein; um den Container vollständig schreibgeschützt zu machen, muss daher auch--read-only-tmpfs=falsehinzugefügt werden - Wird ein schreibgeschützter Container kompromittiert, sind keine Schreibzugriffe auf das System erlaubt, was einige Angriffe nach der Ausnutzung einschränken kann
- Allerdings kann die Ausgabe von
curlanpython3weitergeleitet werden, sodass die reine Schreibschutz-Konfiguration die Ausführung des Exploits selbst nicht verhindert - Der
python3-HTTP-Server im Beispiel benötigt keine Schreibzugriffe auf das Dateisystem, sodass diese Option sicher verwendet werden kann - Viele vorgefertigte Images setzen Schreibzugriff auf bestimmte Verzeichnisse voraus und funktionieren mit einem schreibgeschützten Root-Dateisystem möglicherweise nicht korrekt
- Ein schreibgeschütztes Root-Dateisystem ist unabhängig von beschreibbaren Volumes, die an den Container angebunden sind; im Fall einer Kompromittierung kann daher weiterhin in diese eingehängten Verzeichnisse geschrieben werden
- Wenn
-
Ressourcenlimits
- Docker und Podman können mit cgroups die einem Container bereitgestellten Ressourcen begrenzen
- Ein Container benötigt weder unbegrenzten Speicher noch unbegrenzte CPU- oder PID-Ressourcen
- Mit
podman statslässt sich die Ressourcennutzung des Containers prüfen, danach können passende Limits gesetzt werden
-
Verfügbare Binärdateien begrenzen
- Im Beispiel wird der Einfachheit halber das Image
ubuntuverwendet, dieses enthält im Fall einer Kompromittierung jedoch viele Binärdateien, die ein Angreifer nutzen kann - Für den Betrieb des HTTP-Servers werden die meisten dieser Binärdateien nicht benötigt
- Runtime-Images sollten möglichst schlank aufgebaut sein
- Mit Multi-Stage-Builds lassen sich Build-Time- und Runtime-Umgebung voneinander trennen
- Als Basis eignen sich zweckgebundene Images wie python3, Debians
-slim-Varianten oder kleinere Distributionen wiealpine - Wenn der Containerprozess damit kompatibel ist, können distroless images oder
scratchverwendet werden, um eine Runtime ohne Shell, Paketmanager und Systemwerkzeuge zu erstellen
- Im Beispiel wird der Einfachheit halber das Image
-
Firewall
- Mit
iptablesodernftableslassen sich Containerprozesse per Firewall einschränken - Es sollten nur die unbedingt erforderlichen eingehenden und ausgehenden Verbindungen für den Containerprozess erlaubt werden
- Im Beispiel des HTTP-Servers sind weder DNS noch Verbindungen zu lokalen oder entfernten Servern erforderlich, daher kann etwa auf
tcp-Pakete beschränkt werden, die aus bereits aufgebauten eingehenden Verbindungen stammen
- Mit
Bedeutung für den Betrieb
- Standardmäßige Rootless-Container mit Podman bieten von Haus aus bessere Isolationsmechanismen als eine Standardkonfiguration von Docker-Containern
- Auch Docker unterstützt Rootless-Betrieb und die Nutzung unprivilegierter User-Namespaces, benötigt dafür aber mehr Konfigurationsaufwand als Podman; zudem spielen Architekturunterschiede eine Rolle
- Docker ist weiterhin weit verbreitet, und Self-Hosting-Tools wie Dokku, Kamal, Coolify und Dokploy verwenden standardmäßig Docker
- Wenn Images aus Docker Hub ohne ausreichende Prüfung ausgeführt oder keine Härtungsmaßnahmen angewendet werden, kann ein Dienst mit einer größeren Angriffsfläche laufen als nötig
- Die Implementierungsdetails von Container-Images müssen verstanden werden
- Es muss bekannt sein, welcher Benutzer oder welche Benutzer den Containerprozess ausführen
- Es muss bekannt sein, von welchen Verzeichnissen im Root-Dateisystem der Containerprozess abhängt
- Es muss zwischen erforderlichen und nicht erforderlichen Linux-Capabilities unterschieden werden
- Durch die Kombination der verschiedenen Mechanismen von Podman und Containern lassen sich Container härten und der Blast Radius im Fall einer Kompromittierung verkleinern
- Je nach Workload sollte der Container nicht als einzige Sicherheitsgrenze betrachtet werden
- Durch die Kombination von Containern mit separaten physischen oder virtuellen Maschinen lässt sich eine wirksame Trennung erreichen
- Podman bietet auch auf demselben Host eine Möglichkeit zur Isolierung, indem jede Workload unter einem separaten unprivilegierten Benutzer und mit einem eigenen User-Namespace ausgeführt wird
1 Kommentare
Lobste.rs-Meinungen
Man sollte sich eher auf das durch die Schwachstelle ermöglichte ursprüngliche Verhalten konzentrieren als auf den veröffentlichten Exploit.
Diese Schwachstelle erlaubt Schreibzugriffe auf den Page Cache unabhängig davon, ob etwas schreibgeschützt ist. Dadurch kann ein bösartiger Container Seiten manipulieren, die zu Dateien des Base-Images von overlayfs gehören, und je nach Art der Container-Bereitstellung kann sich die Auswirkung auch auf andere Container übertragen.
In einer rootless-Konfiguration wie hier wären andere Container betroffen, die auf dem Host-System unter demselben Benutzer laufen.
Eine andere Exploit-Methode wäre, einen Container auf Basis eines Base-Images zu starten oder zu finden, von dem bekannt ist, dass er bereits verwendet wird, dann den Page Cache in diesem Container zu manipulieren und anschließend anderen Containern, die sich dieselbe Runtime und dieselben overlayfs-Daten teilen, die Ausführung dieses Codes unterzuschieben.
Rootless und User Namespaces sind wichtig, helfen hier aber nicht besonders; wie auf der copy.fail-Website gesagt wird, sollte man bei Containern eher erwägen, den Systemaufruf
socket(AF_ALG, ...)per seccomp zu blockieren.Es wäre gut, genauer zu erläutern, was „je nach Art der Container-Bereitstellung“ konkret bedeutet.
Ein Vorteil von rootless Podman ist, dass man je nach Workload nicht gezwungen ist, Container auf dem Host unter demselben Benutzer auszuführen.
Wenn damit der Fall gemeint ist, mehrere rootless Container unter dem Hauptbenutzer einer Workstation laufen zu lassen, stimme ich zu; auf Servern kann man sie aber jeweils in getrennte Benutzer aufteilen, und selbst dasselbe Container-Image kann unter unterschiedlichen unprivilegierten Benutzern laufen.
Das unterscheidet sich deutlich vom Docker-Standard, das meiste als
rootauszuführen, aber ich habe am Ende des Artikels auch geschrieben, dass dies keine letztgültige Sicherheitsgrenze ist und dass sich die Frage, ob rootless Container auf mehrere unprivilegierte Benutzer verteilt werden sollten, je nach Einsatzzweck unterschiedlich beantwortet.Bestimmte Workloads isoliere ich mit VMs.
Ich frage mich, ob mit der Aussage, dass rootless und User Namespaces hier nicht helfen, die Verhinderung des Exploits gemeint ist.
Mit seccomp habe ich in Containern noch keine expliziten Richtlinien verwendet, aber das ist ein guter Anlass, mich näher damit zu beschäftigen.
Ich mag Podman und rootless Container, aber nach CopyFail bin ich zum selben Schluss gekommen wie im benachbarten Kommentar.
Selbst mit den zusätzlichen Vorteilen bei der Zugriffskontrolle durch
podman+rootlessbestätigt sich am Ende nur erneut der klassische Rat, dass Container keine Sicherheitsgrenze sind, und ein einzelner Kernel-Exploit alles durchbrechen kann.Ich betreibe Systemadministration nur als Hobby, aber als neuen Trend in diesem Bereich habe ich libkrun backend for crun with podman gesehen.
Das Versprechen ist, die meisten containerisierten Workloads unverändert behandeln zu können, intern aber in einer MicroVM mit eigenem Gast-Kernel zu laufen; über Reifegrad, Praxiserprobung und Sicherheits-Audits weiß ich allerdings wenig, und manches wirkt ziemlich bleeding edge.
Da MicroVMs von LLM-Coding-Tools aktiv übernommen werden, könnte dieser Zustand aber nicht lange anhalten.
Auch
podman machinewirkte vielversprechend, war leider aber offenbar nur für Entwickler-Workstations gedacht und folgte dem Modell, pro Host-System nur eine einzige VM für die Containerausführung zu betreiben.Trotzdem halte ich die Aussage „Container sind keine Sicherheitsgrenze“ für zu vereinfacht. Container sind durchaus eine Sicherheitsgrenze, nur eben keine so starke, wie wir es gern hätten.
Bei lokalen Deployments ist diese Trennlinie etwas unschärfer.
Aus Hardware-Sicht sind VMs nicht von Natur aus sicherer als Prozesse, aber aus drei Gründen ist ihre Grenze besser verteidigbar.
VM-Escapes sind seltener als Systemaufrufe, sodass mehr Spielraum besteht, Gegenmaßnahmen gegen Side Channels anzuwenden, ohne die Performance zu beeinträchtigen.
Die Host-Schnittstelle einer VM ist wesentlich einfacher. Blockgeräte haben ein blockweises Lese-/Schreib-Interface, und Netzwerkgeräte senden und empfangen Frames.
Der von Linux oder *BSD für Sockets bereitgestellte Aufruf
setsockoptist eine viel größere Angriffsfläche als die meisten Emulations- oder Paravirtualisierungstreiber, und selbst das ist nur ein sehr kleiner Teil der gesamten Kernel-Angriffsfläche.Auch die VM-Schnittstelle hat deutlich weniger Zustand. Es gibt Ringe mit laufenden Transaktionen im Request-Response-Modell, aber darüber hinaus fast nichts.
Dinge wie Anmeldedaten, UID, GID und Dateideskriptortabellen fügen dem Kernel zustandsbasierte Komplexität hinzu, und bei Bugs kann ein Prozess das ausnutzen.
Die Schwierigkeit bei der Workstation-Variante besteht darin, dass man diese Komplexität wieder einführt.
Beispielsweise könnte die Container-Base-Layer als Blockgerät mit einem unveränderlichen Dateisystem exponiert werden, aber Volumes und geteilte Ordner würden wahrscheinlich über 9pfs oder VirtIO-FS gemountet, also 9p oder FUSE auf VirtIO.
Damit wächst die Angriffsfläche wieder.
Im günstigsten Fall braucht man dann eine Exploit-Kette.
Ich kenne mich eher auf der FreeBSD-Seite aus; dort werden die Komponenten, die Paravirtualisierungs- oder Emulationsgeräte bereitstellen, üblicherweise mit Capsicum sandboxed, sodass man zuerst den Host-Prozess übernehmen und dann noch bis in den Kernel vordringen müsste, um auf etwas zuzugreifen, auf das die VM keine Berechtigung hatte.
Ohne ein solches zusätzliches Sandboxing landet man aber wieder in einer Welt, in der ein Container-Escape alles tun kann, was der Benutzer tun kann, was auf dem Desktop kaum besser ist als ein Root-Kompromiss.
Persönlich bevorzuge ich gVisor. Es ist keine VMM-Runtime, existiert aber schon seit Jahren und wird auch von Unternehmen wie Tencent eingesetzt; in meiner Umgebung, in der alle Container ohnehin bereits in Proxmox-VMs laufen, passt das gut.
Außerdem teste ich gerade syd-oci, das im Vergleich zu den Standardempfehlungen MicroVM oder gVisor etwas weniger Beachtung gefunden zu haben scheint.
Danke auch für den Verweis auf libkrun, das wirkt wie eine vielversprechende Möglichkeit.
Wahrscheinlich wird das auch zu Sicherheits-Audits führen.