flawopen.com/Teardowns/cve-2024-21626-runc-container-breakout-leaky-vessels
CVE-2024-21626: So behob runc den Leaky-Vessels-Ausbruch
CVE-2024-21626 verband ein internes Dateideskriptorleck in runc mit einer fehlenden Prüfung nach chdir. Je nach Startpfad konnte der Container mit einem Arbeitsverzeichnis im Host-Namespace starten oder über einen verwandten exec-Pfad Hostdateien erreichen.[1], [2], [3]
runc richtet einen isolierten Raum für den Container ein. Ein internes Handle konnte das gewählte Arbeitsverzeichnis aus diesem Raum heraus auf den Host zeigen lassen; die abschließende Grenzprüfung und das Schließen interner Handles verhindern diese Übergabe.[1], [2]
Kernkonzepte & Begriffe
runc- Die OCI-Runtime zum Erstellen und Starten von Containern.[1]
Interner Dateideskriptor- Ein Betriebssystem-Handle für eine geöffnete Datei oder ein Verzeichnis. Ein offener, weitergereichter Deskriptor kann Zugriff über eine Prozessgrenze hinweg erhalten.[1], [3]
cwd- Das Arbeitsverzeichnis eines Prozesses. Linux kann bei Getwd ENOENT melden, wenn cwd außerhalb der Wurzel des Mount-Namespace liegt.[1], [2]
Container-Ausbruch- Ein Pfad, über den ein Containerprozess Hostressourcen außerhalb seiner Isolationsgrenze erreicht.[1]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-403
Ursachenanalyse
Vor runc 1.1.12 konnten interne Dateideskriptoren in runc init offengelegt werden. Sie waren intern für runc init und wurden nicht einfach an den Containerprozess vererbt. Bei Angriff 1 und 2 konnte das konfigurierte oder gewählte Arbeitsverzeichnis über ein Handle des Host-Mount-Namespaces aufgelöst werden; runc prüfte nach chdir nicht, ob das endgültige cwd innerhalb der Containerwurzel lag. Getrennte Varianten nutzten die execve-Pfadbehandlung, um eine Host-Binärdatei zu überschreiben. Version 1.1.12 ergänzte vier Schutzschichten: cwd-Prüfung mit Linux-Getwd/ENOENT-Verhalten, Schließen interner Deskriptoren unmittelbar vor execve, Behebung konkreter Lecks und close-on-exec für Nicht-stdio-Deskriptoren vor dem Start von runc init.[1], [2], [3], [4]
CVE-2024-21626: Angriffsvarianten und Schutzmaßnahmen in runc 1.1.12
| Variante aus dem Hinweis | Erforderliche Bedingungen und Grenze | Relevanter Fix oder Workaround |
|---|---|---|
Angriff 1 — schädliches Image mit runc run | Ein privilegierter Nutzer muss zum Start eines nicht vertrauenswürdigen Images verleitet werden. Dessen konfiguriertes Arbeitsverzeichnis kann außerhalb des Mount-Namespace des Containers aufgelöst werden. | Die Prüfung unix.Getwd() nach chdir schlägt fehl, wenn cwd außerhalb der Namespace-Wurzel liegt. Als vorübergehender Workaround darf cwd für nicht vertrauenswürdige Images nur / sein. |
Angriff 2 — Containerprozess mit runc exec | Ein Prozess im Container muss die Wahl eines cwd ungleich / durch einen Administrator mit runc exec --cwd vorhersehen und den relevanten Pfad vor dem Start vorbereiten. | Dieselbe cwd-Prüfung nach chdir verhindert die Ausführung außerhalb des Containers. Bis zum Update --cwd auf / beschränken. |
| Angriff 3a — Überschreiben einer Host-Binärdatei beim Image-Start | Diese Variante baut auf Angriff 1 auf und setzt weiterhin voraus, dass ein privilegierter Nutzer das schädliche Image startet; sie überschreitet die execve-Grenze zu einer Host-Binärdatei. | Interne runc-Deskriptoren unmittelbar vor execve schließen, erkannte Lecks beheben und O_CLOEXEC setzen. Auf runc 1.1.12 oder eine vom Anbieter korrigierte Version aktualisieren. |
Angriff 3b — Überschreiben einer Host-Binärdatei über runc exec | Diese Variante baut auf Angriff 2 auf und geht von einem schädlichen Prozess in einem laufenden Container aus, den der Angreifer beeinflussen kann; ein Administrator mit erhöhten Rechten muss dennoch einen normalen runc exec für diesen Container ausführen. Laut Hinweis ist dafür weniger Benutzerinteraktion nötig als beim Image-Pfad. | Schließen vor execve und close-on-exec schützen diesen separaten Pfad. Die Maintainer nennen keinen praktikablen Workaround; aktualisieren. |
Schritt-für-Schritt Angriffsablauf
Auswirkung und Bedingungen
Der Hinweis dokumentiert Dateisystemzugriff und Hostkontrolle bei vier Varianten. Image-Angriffe erfordern, dass ein privilegierter Nutzer ein nicht vertrauenswürdiges Image startet. Angriff 3b setzt weiterhin voraus, dass ein Administrator einen normalen runc exec für einen Container ausführt, den der Angreifer beeinflussen kann.[1]
Quellcode: Verwundbar vs. Sicher
// Vereinfachtes Verhalten vor dem Fix; kein wörtlicher runc-Quelltext
if err := os.Chdir(config.Cwd); err != nil {
return err
}
// Es fehlte die Prüfung, ob das endgültige cwd innerhalb der Namespace-Wurzel liegt
// Grenzprüfung aus runc 1.1.12 (Upstream-Auszug)
if wd, err := unix.Getwd(); errors.Is(err, unix.ENOENT) {
return errors.New("cwd liegt außerhalb der Mount-Namespace-Wurzel des Containers")
} else if err != nil {
return fmt.Errorf("cwd-Sicherheit kann nicht geprüft werden: %w", err)
} else if !filepath.IsAbs(wd) {
return fmt.Errorf("cwd ist nicht absolut: %q", wd)
}
Checkliste für Engineering & Systemsicherheit
- ✓Aktualisieren Sie runc auf 1.1.12 oder eine neuere, vom Anbieter unterstützte Version und prüfen Sie die tatsächlich eingesetzte Version in jedem Node-Image.[1], [4]
- ✓Behandeln Sie nicht vertrauenswürdige Container-Images als Codeausführung; beschränken Sie, wer sie über Docker, Kubernetes und Build-Pipelines starten darf.[1]
- ✓Prüfen Sie in Runtime-Implementierungen cwd nach chdir mit der plattformgestützten Namespace-Wurzelprüfung und brechen Sie bei Fehlern sicher ab.[1], [2]
- ✓Setzen Sie O_CLOEXEC für interne Deskriptoren und schließen Sie Nicht-stdio-Deskriptoren am letzten sicheren Punkt vor exec; berücksichtigen Sie runtime-eigene Deskriptoren.[1], [3]
- ✓Betrachten Sie User-Namespaces nicht als Ersatz für den runc-Patch; nutzen Sie sie bei Unterstützung als zusätzliche Isolationsschicht.[1]