Exploit Me, Baby, One More Time: Befehlsinjektion in Kubernetes Log Query
Redaktion und weitere Kommentare von Tricia Howard
Zusammenfassung
Tomer Peled, Sicherheitsforscher von Akamai, hat kürzlich eine Schwachstelle in Kubernetes entdeckt, der CVE-2024-9042 zugewiesen wurde.
Die Schwachstelle ermöglicht die Remoteausführung von Code (remote code execution, RCE) mit SYSTEM-Berechtigungen auf allen Windows-Endgeräten innerhalb eines Kubernetes-Clusters. Um diese Sicherheitslücke auszunutzen, muss der Cluster so konfiguriert werden, dass er den neuen Protokollierungsmechanismus „Log Query“ ausführt.
Die Schwachstelle kann durch eine einfache GET-Anfrage an den Remote-Knoten ausgelöst werden.
Ein erfolgreicher Exploit dieser Sicherheitslücke kann zur vollständigen Übernahme aller Windows-Knoten in einem Cluster führen.
Die Schwachstelle kann auf Standardinstallationen von Kubernetes, die sich für die Verwendung von Beta-Funktionen (älter als Version 1.32.1) entschieden haben, ausgenutzt werden und wurde sowohl bei On-Premise-Bereitstellungen als auch beim Azure Kubernetes Service getestet.
In diesem Blogbeitrag stellen wir einen Proof-of-Concept-curl-Befehl vor und diskutieren mögliche Abhilfemaßnahmen.
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 Nachforschungen führten uns zunächst zu CVE-2023-3676, einer Sicherheitsanfälligkeit für Befehlsinjektion, die durch das Anwenden einer schädlichen YAML-Datei auf den Cluster ausgenutzt werden kann. Diese Untersuchung führte dann dazu, dass einige andere Probleme im Kubernetes-Quellcode entdeckt wurden, die auch eine vollständige Clusterübernahme ermöglichen.
Diese Schwachstellen waren noch nicht alles, was wir gefunden haben – es gab auch eine signifikante Erkenntnis im Sidecar-Projekt „Git-Sync“. Wir haben diese Ergebnisse auf der DEF CON 32 im Red Team Village vorgestellt und sind beim Vorbereiten des Vortrags auf das Thema für diesen Blogbeitrag gestoßen: Eine weitere Möglichkeit für Befehlsinjektion ist die Beta-Funktion von Kubernetes für ihr größeres Framework zur Protokollabfrage Log Query.
Was ist Log Query?
Mit Log Query können Nutzer Remotecomputer mithilfe der CLI oder curl nach ihrem Systemstatus abfragen. Beispiel: Ein Nutzer kann den folgenden Befehl eingeben, um den Status des kubelet-Dienstes auf einem Remote-Knoten abzufragen:
kubectl get --raw "/api/v1/nodes/node-1.example/proxy/logs/?query=kubelet"
Als wir den obigen Beispielbefehl gesehen haben, kamen uns unsere vorherigen Untersuchungen in den Sinn: Würde die Abfrage, die an den Remotecomputer gesendet wird, validiert werden?
Abbildung 1 zeigt ein Beispiel des Quellcodes für Log Query, in dem mehrere PowerShell-Befehle erstellt wurden.
Diese Befehle werden verwendet, um Protokolle von einem bestimmten Knoten basierend auf einer Reihe verschiedener Parameter abzurufen, wie z. B. Windows-Dienstnamen, Muster in Bezug auf die Zeit der Nutzung usw.
Aus früheren Begegnungen (CVE-2023-3676) wissen wir, dass Kubernetes beim Erstellen eines PowerShell-Befehls nicht unbedingt Nutzereingaben überprüft, bevor sie als Parameter eingefügt werden. Wir wollten sehen, ob dies auch bei Log Query der Fall ist, und stellten fest, dass die Dienstnamen tatsächlich mit einem vordefinierten regex validiert werden (Abbildung 2).
Der Name reServiceNameUnsafeCharacters deutet darauf hin, dass diese Prüfung nur für Dienste gilt. Diese Hypothese wird durch die Tatsache verstärkt, dass im Parsing-Prozess kein anderer regex vorhanden ist.
Nach Betrachtung anderer Parameter wurde deutlich, dass der einzige Parameter, der validiert wird, der Dienstname ist. Dies bedeutet, dass wir uns andere Parameter ansehen können, um eine Befehlsinjektion zu erreichen. In Log Query können Nutzer verschiedene optionale Parameter angeben, aber der einzige Parameter, der eine Zeichenfolge ist, ist der Parameter Pattern (Abbildung 3). Wie bereits erwähnt, gibt es keine Validierung für den Parameter (abgesehen von seiner Länge).
Es ist erwähnenswert, dass die Ausnutzung dieser Schwachstelle recht komplex war. Wir haben versucht, die Befehle auf dem Remotecomputer auszulösen, indem wir verschiedene Permutationen für die PowerShell-Payload verwendet haben, wie z. B. das Hinzufügen von Klammern, das Verwenden von Trennzeichen usw., aber nichts schien zu funktionieren – es gab auch keine Fehler, was die Ermittlung des Problems noch schwieriger machte.
Die Payload ist nicht das Problem
Nachdem wir viele verschiedene Methoden der Befehlsinjektion ausprobiert hatten, stellten wir schließlich fest, dass das Problem nicht mit der Payload selbst zusammenhängt. Um diese Sicherheitslücke auszunutzen, mussten wir einen Dienst angeben, der seinen Status nativ im ETW (Event Tracing for Windows, Ereignisverfolgung von Windows) protokolliert und nicht im regulären klog-Framework, da die fehleranfällige Prüfung nur bei der Anmeldung bei ETW vorhanden ist.
Eine Kubernetes-Umgebung mit Calico (eine beliebte Open-Source-Netzwerkschnittstelle für Kubernetes) bietet eine zuverlässige Möglichkeit, diese Schwachstelle über den Non-Sucking Service Manager (NSSM) auszunutzen.
In einer Calico-Einrichtung ist der NSSM normalerweise vorhanden, um den Status der Kubernetes-Dienste zu steuern. In anderen Umgebungen/Einrichtungen verwenden sie unterschiedliche Methoden, um Dienststatus zu verarbeiten.
- Kubernetes verwaltet die Protokollausgabe von NSSM nicht, sodass Protokolle direkt in ETW und nicht über klog geschrieben werden.
Wie sieht eine Exploit-Abfrage aus?
So würde eine Exploit-Abfrage aussehen:
curl "<Kubernetes API Proxy server IP>/api/v1/nodes/<NODE name>/proxy/logs/?query=nssm&pattern=’\$(Start-process cmd)’"
* Das Authentifizierungstoken, das für die Kommunikation mit dem API-Server erforderlich ist, wird verdeckt
Aufmerksame Leser haben sich vielleicht über die Apostrophe gewundert, die benutzt wurden, um unseren bösartigen Befehl zu escapen. Wir brauchen sie, weil Kubernetes unsere Eingabe mit dem folgenden Befehl einfügt:
…Where-Object -Property Message -Match '%s'...
Ähnlich wie bei klassischen SQL-Injection-Angriffen müssen wir Apostrophe hinzufügen, um ihrem Muster zu entgehen, damit unsere Eingabe als separater Befehl geparst wird (Abbildung 4).
Prioritäts-Patch
Damit Sie von dieser Sicherheitsanfälligkeit betroffen sein können, müssen Sie eine Kubernetes-Version vor 1.32.1 verwenden. Wenn Sie diese Sicherheitslücke 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 folgenden Befehl auf dem Cluster-Controller ausführt (Abbildung 5).
Besteht für mich ein Risiko?
Es lässt sich leicht feststellen, ob Sie gefährdet sind. Beachten Sie folgenden Teil: „os=windows“. Wenn keine Windows-Knoten vorhanden sind, hat der Befehl keine Ausgabe zur Folge. Das bedeutet, dass Sie nicht gefährdet sind.
Da es sich um eine Beta-Funktion handelt, muss der Cluster auch so konfiguriert werden, dass er das Framework selbst verwendet.
Um zu prüfen, ob die Funktion aktiviert ist, können Administratoren den Startparameter „feature-gate“ für „kubelet“ anzeigen lassen. Weitere Informationen finden Sie auf der Kubernetes-Website.
Patch-Analyse
Um diese Sicherheitsanfälligkeit zu beheben, entschied sich Kubernetes, eine Umgebungsvariable namens „kubelet_pattern“ zu verwenden, bevor der Wert an den PowerShell-Befehl selbst weitergegeben wurde.
Auf diese Weise wird die Nutzereingabe als Zeichenfolgenliteral und nicht als untergeordneter Ausdruck betrachtet, der ausgewertet werden muss.
Abwehr
Um diese Sicherheitsanfälligkeit zu mindern, können Administratoren das RBAC-Modul (Role-Based Access Control, rollenbasierte Zugriffssteuerung) verwenden, um zu steuern, wer Zugriff auf Log Query hat, oder den Zugriff auf Log Query sogar vollständig deaktivieren. RBAC ist eine Methode, mit der Nutzervorgänge nach Nutzern segmentiert werden. Beispielsweise kann jeder Nutzer Pods nur im eigenen Namespace erstellen oder nur Informationen für zulässige Namespaces anzeigen. Dies würde das Risiko von RCE nicht nur bei der Ausführung, sondern auch bei der Erkennung verringern – ein abnormales Nutzerverhalten ist oft ein Anzeichen für Cyberkriminalität.
Beachten Sie, dass diese Sicherheitslücke nur Windows-Knoten betrifft. Wenn Ihr Kubernetes-Cluster über keine Windows-Knoten verfügt, haben Sie nichts zu befürchten. Es wird jedoch empfohlen, Ihre Patches so aktuell wie möglich aufzuspielen, um andere unbekannte Sicherheitslücken zu vermeiden.
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
In diesem Blogbeitrag haben wir dargestellt, wie ein Angreifer mit Abfrageberechtigungen Befehle auf jedem Windows-Knoten innerhalb des Clusters ausführen kann. Diese Schwachstelle kann durch einen einfachen curl-Befehl ausgenutzt werden, anstatt eine YAML-Datei senden zu müssen. Diese Tatsache stellt ein großes Risiko dar, da ein Exploit schwerer zu mindern und zu erkennen ist. Wie bereits erwähnt, bestehen derartige Kubernetes-Probleme nicht nur bei Log Query.
Blue-Team-Mitglieder sollten bezüglich ungewöhnlichen Verhaltens in ihrem Unternehmen wachsam sein. Dieser Angriffsvektor kann zu einer vollständigen Übernahme des Clusters führen. Daher ist es wichtig, darauf aufmerksam zu machen und Sicherheitsadministratoren dabei zu unterstützen, die potenziellen Gefahren zu erkennen.
Die Akamai Security Intelligence Group wird Bedrohungen wie diese weiterhin untersuchen und unsere Kunden und die Sicherheits-Community darüber informieren. Wenn Sie in Echtzeit Informationen zu unserer Arbeit erhalten möchten, dann folgen Sie uns auf X (ehemals Twitter).
Wir möchten dem Kubernetes-Team für die schnelle Reaktion und den Austausch danken.
Zeitachse
28.06.2024: Schwachstelle wird dem Kubernetes-Team mitgeteilt
18.07.2024: Das Kubernetes-Team beginnt, das Problem zu beheben
30.07.2024: CVEs werden vom Kubernetes-Team zugewiesen
16.01.2025: Kubernetes veröffentlicht die Problembehebungen für diese CVEs
24.01.2025: Blogbeitrag veröffentlicht