Was für ein Cluster: Sicherheitslücke in Bezug auf lokale Volumes in Kubernetes
Redaktion und weitere Kommentare von Tricia Howard
Zusammenfassung
Tomer Peled, ein Sicherheitsforscher von Akamai, hat vor kurzem eine gravierende Schwachstelle in Kubernetes entdeckt. Ihr wurde die CVE-Nummer CVE-2023-5528 mit einem CVSS-Score von 7,2 zugewiesen.
Die Sicherheitslücke ermöglicht Remoteausführung von Code mit SYSTEMBERECHTIGUNGEN auf allen Windows-Endpunkten innerhalb eines Kubernetes-Clusters. Zur Ausnutzung dieser Schwachstelle muss der Angreifer schädliche YAML-Dateien auf dem Cluster anwenden.
Diese Sicherheitslücke kann zur vollständigen Übernahme aller Windows-Knoten in einem Cluster führen.
Die Schwachstelle kann auf Standardinstallationen von Kubernetes (älter als Version 1.28.4) ausgenutzt werden und wurde sowohl bei On-Premise-Bereitstellungen als auch beim Azure Kubernetes Service getestet.
- In diesem Blogbeitrag stellen wir eine YAML-Datei mit Proof of Concept sowie eine OPA-Regel (Open Policy Agent) zur Blockierung dieser Schwachstelle bereit.
Einführung
Kubernetes und Container sind aus der Sicherheitswelt nicht mehr wegzudenken. Daher sind sie für Forscher weltweit von Interesse und natürlich auch für uns. Unsere Forschungsreise führte uns zunächst zu CVE-2023-3676 (CVSS von 8,8): Dabei handelt es sich um eine Sicherheitslücke für Befehlsinjektion, für deren Exploit eine schädliche YAML-Datei auf den Cluster angewendet werden muss. Da das Kubernetes-Framework YAML-Dateien für praktisch alles verwendet – von der CNI-Konfiguration (Container Network Interface) über die Pod-Verwaltung bis hin zur diskreten Abwicklung –, kann eine Ausnutzung dieser Schwachstelle verheerende Schäden anrichten.
Durch die Entdeckung dieser Schwachstelle konnten zwei weitere entdeckt werden, die dieselbe Ursache haben: unsicherer Funktionsaufruf und unzureichende Bereinigung von Nutzereingaben.
Die unzureichende Bereinigung des Parameters subPath in YAML-Dateien, der Pods mit Volumes erstellt, eröffnet die Möglichkeit einer Injection mit Schadcode. Das war das ursprüngliche Ergebnis. Allerdings haben wir zum Ende dieser Studie eine potenzielle Stelle im Code bemerkt, die aussah, als könnte sie zu einer weiteren Command-Injection-Schwachstelle führen. Nach mehreren Versuchen gelang es uns, ein ähnliches Ergebnis zu erzielen: die Ausführung von Befehlen als „kubelet"-Service (mit SYSTEMBERECHTIGUNGEN). Hier beginnen wir heute unsere Reise mit CVE-2023-5528.
In diesem Blogbeitrag werden wir die Details zu der Sicherheitslücke und die Probleme im Kubernetes-Quellcode, die diese ermöglichen, erläutern und darüber hinaus den Patch des Kubernetes-Teams und seine Effektivität analysieren. Obwohl ein schnellstmögliches Patchen empfohlen wird, haben wir kurze Anleitungen dazu aufgenommen, wie Sie nach betroffenen Knoten suchen und wie Sie eine OPA-Regel (Open Policy Agent) anwenden, um diese Art von Verhalten zu erkennen und zu blockieren.
Dieser Beitrag zeigt einmal mehr auf, wie wichtig es ist, die YAMLs für die Kubernetes-Konfiguration zu überprüfen, da die Eingabebereinigung in mehreren Codebereichen von Kubernetes selbst und von zusammenhängenden Projekten nur unzureichend ist (wie z. B. Ingress).
Schwachstellendetails
Bevor wir uns mit den Besonderheiten dieser Schwachstelle selbst befassen, gilt es zunächst einige wichtige Komponenten in Kubernetes zu verstehen.
Was sind Kubernetes-Volumes?
Kubernetes-Volumes sind eine Funktion, die die gemeinsame Nutzung von Daten zwischen Pods oder die dauerhafte Speicherung außerhalb des Lebenszyklus eines Pods unterstützen soll. Für Entwickler gibt es viele verschiedene Arten von Volumes. In unserer früheren Studie zu CVE-2023-3676 haben wir beispielsweise hostPath-Volumes verwendet. Bei dieser Schwachstelle konzentrieren wir uns auf lokale Volumes – eine andere Art von Volume in Kubernetes. Lokale Volumes sind so konzipiert, dass Nutzer Datenträgerpartitionen in einem Pod bereitstellen können. hostPath-Volumes ermöglichen es Nutzern dagegen, Verzeichnisse von ihrem Knoten (Host) in einem Pod einzuhängen.
Beim Erstellen eines Pods, der ein lokales Volume enthält, wird der Service kubelet (früher oder später) die folgende Funktion erreichen: „MountSensitive()“. Darin befindet sich ein cmd-Aufruf für „exec.command“, wodurch ein Symlink zwischen der Position des Volumes auf dem Knoten und der Position im Pod hergestellt wird (Abbildung 1).
Viele Terminals verwenden eine Art der Befehlsverkettung (Abbildung 2) für den Betrieb, um die Bedienung zu vereinfachen. Dies gilt auch für die Eingabeaufforderung in Windows (cmd) . Durch Nutzung des Tokens „&&“ führt das Terminal zwei oder mehr Befehle nacheinander aus.
C:\Users\user>echo "by using &&" && echo "we can execute multiple commands in the same command line"
"by using &&"
"we can execute multiple commands in the same command line"
C:\Users\user>
Abb. 2: Befehlsverkettung in cmd
Die Tatsache, dass wir einen Parameter der cmd-Ausführung kontrollieren können, bedeutet, dass Command Injection verwendet werden kann. Es gibt jedoch einige Voraussetzungen dafür: Damit Nutzer lokale Volumes verwenden können, müssen sie ein persistentVolume angeben oder erstellen.
Was sind persistentVolumes?
persistentVolumes sind Speicherressourcen, die ein Clusteradministrator erstellen kann, um Speicherplatz im Voraus bereitzustellen, der über die Lebensdauer des Pods hinausgeht (Abbildung 3). Sobald ein persistentVolume erstellt wird, kann ein Nutzer mithilfe von persistentVolumeClaim Speicherplatz erbitten.
Hier kann die Injection platziert werden. Ein Angreifer kann den Wert des Parameters „local.path“ innerhalb der YAML-Datei des persistentVolume ändern, um einen schädlichen Befehl hinzufügen, der während des Mount-Prozesses ausgeführt wird.
In Abbildung 4 verwenden wir den harmlosen Befehl „&calc.exe&&“ (wodurch ein Taschenrechner auf dem Knoten geöffnet wird). Aber dieser Prozess kann auch für weitaus schädlichere Folgen genutzt werden.
Abbildung 5 zeigt, wie ein erfolgreicher Exploit auf einem Zielknoten nach der Injection unseres „schädlichen“ Taschenrechnerbefehls aussieht.
Patch-Analyse
In dem Bemühen, eine Injection unmöglich zu machen, entschied sich das Kubernetes-Team, den cmd-Aufruf zu löschen und durch eine native GO-Funktion zu ersetzen, die denselben Vorgang durchführt – „os.Symlink()“ (Abbildung 6).
So führt die GO-„os“-Bibliothek nur einen Symlink-Vorgang aus, wie ursprünglich vorgesehen.
Besteht für mich ein Risiko?
Damit Nutzer von dieser Sicherheitslücke betroffen sind, muss eine frühere Version von Kubernetes als 1.28.4 verwendet werden. Wenn Sie sie noch nicht gepatcht haben, sollten Sie dies priorisieren. Dies gilt insbesondere für Unternehmen mit Windows-Knoten innerhalb eines Clusters, da hier die Schwachstelle liegt.
Glücklicherweise scheint dies nicht der branchenweite Standard zu sein. Ein Administrator kann einfach testen, ob Ihr Unternehmenscluster Windows-Knoten enthält, indem er den in Abbildung 7 dargestellten Befehl auf dem Cluster-Controller ausführt.
root@controller:~/$ kubectl get nodes -o wide --show-labels | grep “os=windows”
akswin000000 Ready agent 4d17h v1.26.6 agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows…
akswin000001 Ready agent 4d17h v1.26.6 agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows…
root@controller:~/$
Abb. 7: Der Befehl, der Windows-Knoten in einem Cluster anzeigt
Es lässt sich leicht feststellen, ob Sie gefährdet sind. Beachten Sie den Teil „os=windows“. Wenn keine Windows-Knoten vorhanden sind, hat der Befehl keine Ausgabe zur Folge. Das bedeutet, dass Sie nicht gefährdet sind.
Abwehr
Die einzige verfügbare Sicherheitsmaßnahme besteht darin, Kubernetes auf eine Version nach 1.28.3 zu patchen.
Wir wissen natürlich, dass sofortiges Patchen in einigen Unternehmen und Netzwerken nicht möglich ist. Für Fälle, in denen vorerst kein Patch aufgespielt werden kann, haben wir eine OPA-Regel zur Erkennung und Blockierung dieser Art von Verhalten bereitgestellt, um das Risiko zu mindern.
package kubernetes.admission
deny[msg] {
input.request.kind.kind == "PersistentVolume"
path := input.request.object.spec.local.path
contains(path, "&")
msg := sprintf("malicious path: %v was found", [path])
}
OPA ist ein Open-Source-Agent, mit dem Nutzer Daten über an Knoten ein- und ausgehenden Traffic erhalten und richtlinienbasierte Aktionen bei empfangenen Daten ausführen können.
Beachten Sie, dass diese Sicherheitslücke nur Windows-Knoten betrifft. Wenn Ihr Kubernetes-Cluster über keine Windows-Knoten verfügt, müssen Sie diese spezielle Schwachstelle auch nicht umgehend beheben. Aber wenn Sie Zeit haben, sollten Sie sie dennoch patchen.
Da das Problem im Quellcode liegt, bleibt diese Bedrohung aktiv und der Exploit wird wahrscheinlich zunehmen. Daher empfehlen wir dringend, das Patchen Ihres Clusters durchzuführen, auch wenn er keine Windows-Knoten hat.
Fazit
Diese Schwachstelle ist ein ausgezeichnetes Beispiel dafür, warum das Modell der geteilten Verantwortung für die Sicherheit von entscheidender Bedeutung ist. Wenn Sie sich der unzureichenden Bereinigung von Eingaben im Kubernetes-Quellcode bewusst sind, können Sie von außen Maßnahmen ergreifen, um schwerwiegende Folgen für die Sicherheit zu vermeiden.
Allein im Jahr 2023 wurden sieben verschiedene Command-Injection-Sicherheitslücken entdeckt und in anderen Bereichen des Codes ergaben sich noch weitere Möglichkeiten. Blue Teams und ihre Unternehmen sollten diesen wachsenden Trend wachsamer beobachten und versuchen, YAML-Dateiinhalte zu überwachen, da sich darin möglicherweise versteckte Bedrohungen befinden. Die OPA-Regel, die wir in diesem Beitrag angegeben haben, kann sie in dieser Hinsicht unterstützen.
Die Akamai Security Intelligence Group wird diese und andere Bedrohungen weiterhin überwachen und ihre Ergebnisse veröffentlichen. Um über diese Schwachstelle und unsere übrige Sicherheitsforschung auf dem Laufenden zu bleiben, folgen Sie uns auf X (ehemals Twitter).
Wir möchten dem Kubernetes-Team für die schnelle Reaktion und die reibungslose Kommunikation danken.
Chronik der Veröffentlichung
01.11.2023: Schwachstelle wird dem Kubernetes-Team mitgeteilt
11.11.2023: CVEs werden vom Kubernetes-Team zugewiesen
14.11.2023: Kubernetes veröffentlicht die Problembehebungen für diese CVEs
13.03.2024: Dieser Blogbeitrag wird veröffentlicht