Hinweis perev. : Dieser Hinweis wurde von einem IT-Sicherheitsforscher bei Aqua Security, einem DevSecOps-Unternehmen, verfasst. Sie ist ein hervorragendes Beispiel für die Feinheiten in der Kubernetes-Konfiguration, die wichtig sind, wenn Sie Cluster in der Produktion bedienen. Natürlich, wenn Sie an ihre Sicherheit denken ...
Kubernetes besteht aus vielen Komponenten, und manchmal führt die Kombination auf bestimmte Weise zu unerwarteten Ergebnissen. In diesem Artikel werde ich zeigen, wie ein Pod, der mit Root-Rechten und einem gemounteten
/var/log
Verzeichnis eines Knotens gestartet wurde
, den Inhalt des gesamten Host-Dateisystems für einen Benutzer mit Zugriff auf seine Protokolle erweitern kann. Wir werden auch Lösungen für dieses Problem diskutieren.
Wie Kubernetes Protokolle sieht
Haben Sie sich jemals gefragt, wie
kubectl logs <pod_name>
Protokolle aus dem Pod extrahiert? Wer ist für das Sammeln von Protokollen aus Containern verantwortlich? Und wie kommen sie auf Ihren Computer?
Das folgende Diagramm veranschaulicht den Prozess:

Kubelet erstellt eine Struktur im Verzeichnis
/var/log
auf dem Host, die die Pods auf dem Host darstellt. Es gibt eine Datei
0.log
(1) im Verzeichnis für unseren
0.log
, aber tatsächlich ist es ein Symlink zum Containerprotokoll in
/var/lib/docker/containers
. Dies ist alles aus Sicht des Gastgebers.
Kubelet öffnet den Endpunkt
/logs/
(2), der einfach mit dem HTTP-Dateiserver in Verzeichnis (3) zusammenarbeitet und die Protokolle für Anforderungen vom API-Server verfügbar macht.
Stellen Sie sich nun vor, wir hätten einen Pod mit
hostPath
in
/var/log
bereitgestellt. Ein solcher Pod hat Zugriff auf alle Protokolldateien auf dem Host. Obwohl dies an sich ein potenzielles Problem darstellt, können wir den nächsten logischen Schritt unternehmen. Was ist, wenn wir
0.log
durch einen Symlink zu ... say,
/etc/shadow
ersetzen?
│ ├── var │ ├── logs │ │ ├── pods │ │ │ ├── default_mypod_e7869b14-abca-11e8-9888-42010a8e020e │ │ │ │ ├── mypod │ │ │ │ │ ├── 0.log -> /etc/shadow │ │ │ │ │ │
kubectl logs
wir nun versuchen, die Protokolle mithilfe von
kubectl logs
auf dem Client-Computer herunterzuladen, erhalten wir:
$ kubectl logs mypod failed to get parse function: unsupported log format: "root:*:18033:0:99999:7:::\n"
Kubelet folgt dem Link und liest den Inhalt der Datei, auf die er verweist (es kann sich um eine beliebige Datei auf dem Knoten handeln).
Da JSON erwartet wurde, stürzte kubectl nach der ersten Zeile ab. Wir können jedoch die spezifischen Zeilen der
shadow
leicht lesen, indem wir den Befehl mit dem
–-tail=-<line_number>
.
Das ist unglaublich. Da kubelet dem Symlink folgt, können Sie seine Root-Berechtigungen verwenden, um jede Datei auf dem Knoten zu lesen, indem Sie einfach einen symbolischen Link im Pod erstellen.
Entkomme aus der Kapsel
Gehen wir noch weiter. Wir wissen, dass beim Starten eines Pods in Kubernetes das ServiceAccount-Token darin installiert ist. Wenn das Dienstkonto den Zugriff auf die Protokolle zulässt, können wir direkt auf die Kubelet- und Root-Berechtigungen auf dem Knoten zugreifen.
Ich habe einen Proof of Concept (POC) geschrieben, der diesen Angriffsvektor demonstriert:
- Bereitstellung des Pods mit Mountpunkt
/var/log
; - Erstellen einer symbolischen Verknüpfung zum Stammverzeichnis des Hosts;
- Lesen des privaten SSH-Schlüssels des Benutzers auf dem Host.
Das
folgende Video zeigt zwei spezielle Befehle, die in einem Pod ausgeführt werden:
lsh == ls
(auf dem Host-Dateisystem);cath == cat
(im Host-Dateisystem).
Hinweis perev. : Leider wurde das Einfügen von Inhalten aus asciinema auf dem Hub nicht behoben, obwohl wir dieses Problem bereits behoben haben. Daher sind wir gezwungen, das Video mit dem obigen einfachen Link einzubetten.Alle an diesem POC beteiligten Dateien befinden sich im
entsprechenden GitHub-Repository . Es gibt ein weiteres POC-Skript, das automatisch private Schlüssel und ServiceAccount-Token aus dem Host-Dateisystem sammelt.
Das Mounten von Verzeichnissen kann gefährlich sein
Ist das also eine Sicherheitslücke oder nur eine schlechte Praxis?
Das Bereitstellen eines Pods mit einem in
/var/log
hostPath
ist selten (es gibt auch andere Möglichkeiten, das Mounten von geheimen
hostPath
im Pod zu missbrauchen). Aber selbst wenn Sie wüssten, dass das Mounten von
/var/log
eine zweifelhafte Praxis ist, haben Sie wahrscheinlich nicht erwartet, dass Sie den Knoten so einfach übernehmen können.
Vor der Veröffentlichung haben wir das Sicherheitsteam von Kubernetes kontaktiert, um herauszufinden, ob dies eine Sicherheitslücke darstellt. Sie kamen zu dem Schluss, dass dies nur eine traurige Folge der Bereitstellung eines privaten Hostverzeichnisses mit Schreibberechtigungen war: Die damit verbundenen Risiken sind gut
dokumentiert . Diese Sicherheitsanfälligkeit ist jedoch recht einfach auszunutzen. In der Welt gibt es
viele Projekte , die diese Halterung verwenden. Wenn Sie eines dieser Projekte verwenden, denken Sie daran, dass Ihre Bereitstellung für diese Art der Flugzeugentführung anfällig ist.
Diese Methode wurde auf Kubernetes 1.15 und 1.13 getestet, betrifft jedoch höchstwahrscheinlich andere Versionen.
Beseitigung
Ein solches "Escape" ist nur möglich, wenn der Pod als Root ausgeführt wird. Dies
sollte generell
vermieden werden . Mit Aqua CSP können Sie mit minimalem Aufwand eine Richtlinie festlegen, die verhindert, dass Container als Root ausgeführt werden, oder Berechtigungen nur für eine bestimmte Gruppe von Bildern erteilt, die wirklich Root benötigen.
Eine andere Möglichkeit besteht darin, Pods mit
hostPath
mit Schreibberechtigungen in
/var/log
einfach nicht
hostPath
. Dieser Ansatz ist nicht standardmäßig festgelegt und keine gängige Praxis. Daher muss er bewusst festgelegt werden (die Möglichkeit bleibt jedoch weiterhin bestehen). Aber wie soll man das überprüfen?
Wir haben
kube-hunter ein neues Skript (hunter)
hinzugefügt - unser leichtes Open Source-Tool zum Testen von Kubernetes - das den Cluster auf Pods mit solch gefährlichen Mount-Punkten überprüft.
( Hinweis : Kube-hunter war kürzlich in einer Überprüfung der K8-Sicherheitsdienstprogramme vertreten, die wir in unserem Blog veröffentlicht haben.)Aqua-Benutzer können sich vor diesem Risiko schützen, indem sie mithilfe der Laufzeitrichtlinie verhindern, dass bestimmte Volumes bereitgestellt werden:
Hinweis perev. : Ein Teil dieses Problems kann mithilfe von Pod-Sicherheitsrichtlinien , nämlich AllowedHostPaths
, gelöst werden. Dies ist jedoch auch kein Schutz gegen Symlinks. Schließlich können wir, wie aus den Kommentaren hervorgeht, den Start einfach als Root einschränken, was wiederum von der PSP geleitet wird.Zusammenfassung
Kubernetes ist ein komplexes System mit vielen Feinheiten in den Sicherheitseinstellungen, die für den durchschnittlichen und sogar erfahrenen Benutzer nicht immer offensichtlich sind. In diesem Artikel habe ich gezeigt, wie unschuldige Protokollierung unter bestimmten Umständen zu potenziellen Sicherheitslücken führen kann. In den meisten Fällen ist dies nicht möglich, aber Kubernetes bietet Benutzern mehr Handlungsspielraum, der die Sicherheit beeinträchtigen kann. Es ist wichtig, dies zu berücksichtigen und geeignete Kontrollen zu implementieren, um solche Fehler zu vermeiden.
PS vom Übersetzer
Lesen Sie auch in unserem Blog: