Abusing Roles/ClusterRoles in Kubernetes
Hier finden Sie einige potenziell gefährliche Rollen- und ClusterRoles-Konfigurationen.
Denken Sie daran, dass Sie alle unterstützten Ressourcen mit kubectl api-resources
abrufen können.
Privilege Escalation
Als die Kunst, Zugriff auf einen anderen Hauptbenutzer innerhalb des Clusters mit unterschiedlichen Berechtigungen (innerhalb des Kubernetes-Clusters oder zu externen Clouds) zu erhalten, gibt es in Kubernetes im Wesentlichen 4 Haupttechniken zur Eskalation von Berechtigungen:
Die Fähigkeit, andere Benutzer/Gruppen/SAs mit besseren Berechtigungen innerhalb des Kubernetes-Clusters oder zu externen Clouds zu impersonieren
Die Fähigkeit, Pods zu erstellen/zu patchen/auszuführen, in denen Sie SAs finden oder anhängen können, die über bessere Berechtigungen innerhalb des Kubernetes-Clusters oder zu externen Clouds verfügen
Die Fähigkeit, Secrets zu lesen, da die SAs-Token als Secrets gespeichert sind
Die Fähigkeit, aus einem Container auf den Node zu entkommen, wo Sie alle Secrets der in dem Node ausgeführten Container, die Anmeldeinformationen des Nodes und die Berechtigungen des Nodes innerhalb der Cloud, in der er ausgeführt wird (falls vorhanden), stehlen können
Eine fünfte Technik, die erwähnenswert ist, ist die Fähigkeit, Port-Forward in einem Pod auszuführen, da Sie möglicherweise auf interessante Ressourcen innerhalb dieses Pods zugreifen können.
Zugriff auf jede Ressource oder jedes Verb (Wildcard)
Das Wildcard (*) gibt Berechtigungen über jede Ressource mit jedem Verb. Es wird von Admins verwendet. Innerhalb eines ClusterRoles bedeutet dies, dass ein Angreifer auf jeden Namespace im Cluster zugreifen könnte.
Zugriff auf beliebige Ressourcen mit einem bestimmten Verb
Im RBAC stellen bestimmte Berechtigungen erhebliche Risiken dar:
create
: Gewährt die Fähigkeit, beliebige Cluster-Ressourcen zu erstellen und riskiert damit eine Privilegieneskalation.list
: Ermöglicht das Auflisten aller Ressourcen und könnte potenziell sensible Daten preisgeben.get
: Erlaubt den Zugriff auf Secrets von Service-Accounts und birgt eine Sicherheitsbedrohung.
Pod erstellen - Token stehlen
Ein Angreifer mit den Berechtigungen zum Erstellen eines Pods könnte einem privilegierten Service Account in den Pod anhängen und das Token stehlen, um sich als den Service Account auszugeben. Dadurch könnten Berechtigungen effektiv eskaliert werden.
Beispiel eines Pods, der das Token des bootstrap-signer
Service Accounts stehlen und an den Angreifer senden wird:
Pod Erstellen & Entkommen
Das Folgende zeigt alle Berechtigungen, die ein Container haben kann:
Privilegierter Zugriff (Deaktivierung von Schutzmaßnahmen und Festlegung von Fähigkeiten)
Deaktivierung der Namespaces hostIPC und hostPid, die zur Eskalation von Berechtigungen beitragen können
Deaktivierung des hostNetwork-Namespaces, der Zugriff auf gestohlene Cloud-Berechtigungen und besseren Zugriff auf Netzwerke ermöglicht
Einbinden von hosts / innerhalb des Containers
Erstellen Sie das Pod mit:
Ein-Liner aus diesem Tweet und mit einigen Ergänzungen:
Jetzt, da du zum Knoten entkommen kannst, überprüfe Post-Exploitationstechniken in:
Stealth
Du möchtest wahrscheinlich unauffälliger sein, auf den folgenden Seiten kannst du sehen, auf welche Ressourcen du zugreifen könntest, wenn du ein Pod erstellst, der nur einige der erwähnten Berechtigungen im vorherigen Template aktiviert:
Privileged + hostPID
Nur privilegiert
hostPath
hostPID
hostNetwork
hostIPC
Ein Beispiel, wie man die vorherigen privilegierten Pod-Konfigurationen erstellt/missbraucht, findest du unter https://github.com/BishopFox/badPods
Pod erstellen - In die Cloud wechseln
Wenn du einen Pod erstellen kannst (und optional ein Service-Konto), könntest du Berechtigungen in der Cloud-Umgebung erhalten, indem du Cloud-Rollen einem Pod oder einem Service-Konto zuweist und dann darauf zugreifst. Darüber hinaus, wenn du einen Pod mit dem Host-Netzwerk-Namensraum erstellen kannst, kannst du die IAM-Rolle der Knoten-Instanz stehlen.
Für weitere Informationen siehe:
Pod Escape PrivilegesErstellen/Patchen von Bereitstellungen, Daemonsets, Statefulsets, Replikationscontrollern, Replikasets, Jobs und Cronjobs
Es ist möglich, diese Berechtigungen zu missbrauchen, um einen neuen Pod zu erstellen und Berechtigungen wie im vorherigen Beispiel zu erhalten.
Das folgende YAML erstellt ein Daemonset und schmuggelt das Token des SA innerhalb des Pods aus:
Pods Exec
pods/exec
ist eine Ressource in Kubernetes, die zum Ausführen von Befehlen in einer Shell innerhalb eines Pods verwendet wird. Dies ermöglicht es, Befehle innerhalb der Container auszuführen oder eine Shell zu öffnen.
Daher ist es möglich, in einen Pod einzudringen und das Token des SA zu stehlen, oder in einen privilegierten Pod einzutreten, auf den Knoten zu entkommen und alle Tokens der Pods im Knoten zu stehlen und den Knoten zu (miss)brauchen:
port-forward
Diese Berechtigung ermöglicht es, einen lokalen Port auf einen Port im angegebenen Pod weiterzuleiten. Dies soll es ermöglichen, Anwendungen, die innerhalb eines Pods laufen, einfach zu debuggen, aber ein Angreifer könnte sie missbrauchen, um Zugriff auf interessante (wie DBs) oder anfällige Anwendungen (Webs?) innerhalb eines Pods zu erhalten:
Hosts beschreibbar /var/log/ Escape
Wie in dieser Forschung angegeben, wenn Sie auf ein Pod mit dem hosts /var/log/
Verzeichnis gemountet darauf zugreifen oder es erstellen können, können Sie aus dem Container ausbrechen.
Dies liegt im Wesentlichen daran, dass wenn der Kube-API versucht, die Logs eines Containers abzurufen (mit kubectl logs <pod>
), fordert er die Datei 0.log
des Pods über den /logs/
Endpunkt des Kubelet Dienstes an.
Der Kubelet-Dienst stellt den /logs/
Endpunkt bereit, der im Grunde genommen das Dateisystem /var/log
des Containers freigibt.
Daher könnte ein Angreifer mit Zugriff zum Schreiben im /var/log/ Verzeichnis des Containers dieses Verhalten auf 2 Arten ausnutzen:
Ändern der
0.log
Datei seines Containers (normalerweise im Verzeichnis/var/logs/pods/namespace_pod_uid/container/0.log
) so dass sie ein Symbolic Link auf/etc/shadow
beispielsweise ist. Dann können Sie die hosts shadow Datei extrahieren, indem Sie:
Wenn der Angreifer irgendeinen Hauptbenutzer mit den Berechtigungen zum Lesen von
nodes/log
kontrolliert, kann er einfach einen Symlink in/host-mounted/var/log/sym
zu/
erstellen und wenn er aufhttps://<gateway>:10250/logs/sym/
zugreift, wird er die Wurzel des Host-Dateisystems auflisten (das Ändern des Symlinks kann den Zugriff auf Dateien ermöglichen).
Ein Labor und ein automatisierter Exploit finden Sie unter https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts
Umgehen des Schreibschutzes für readOnly
Wenn Sie Glück haben und die hochprivilegierte Fähigkeit CAP_SYS_ADMIN
verfügbar ist, können Sie einfach den Ordner als rw neu einhängen:
Umgehen des Schutzes vor schreibgeschütztem hostPath
Wie in dieser Forschung dargelegt, ist es möglich, den Schutz zu umgehen:
Was dazu gedacht war, Ausbrüche wie die vorherigen zu verhindern, indem anstelle eines hostPath-Mounts ein PersistentVolume und ein PersistentVolumeClaim verwendet werden, um einen Host-Ordner im Container mit Schreibzugriff einzubinden:
Vortäuschen privilegierter Konten
Mit einem Benutzerimitations-Privileg könnte ein Angreifer ein privilegiertes Konto vortäuschen.
Verwenden Sie einfach den Parameter --as=<Benutzername>
im kubectl
-Befehl, um einen Benutzer zu imitieren, oder --as-group=<Gruppe>
, um eine Gruppe zu imitieren:
Oder verwenden Sie die REST-API:
Auflisten von Geheimnissen
Die Berechtigung zum Auflisten von Geheimnissen könnte einem Angreifer tatsächlich ermöglichen, die Geheimnisse zu lesen, indem er auf den REST-API-Endpunkt zugreift:
Lesen eines Geheimnisses – Brute-Force von Token-IDs
Ein Angreifer, der im Besitz eines Tokens mit Leseberechtigungen ist, benötigt den genauen Namen des Geheimnisses, um es zu verwenden. Im Gegensatz zu den umfassenderen Auflisten von Geheimnissen-Berechtigungen bestehen jedoch immer noch Schwachstellen. Standarddienstkonten im System können aufgelistet werden, von denen jedes mit einem Geheimnis verbunden ist. Diese Geheimnisse haben eine Namensstruktur: ein statisches Präfix gefolgt von einem zufälligen alphanumerischen Token mit fünf Zeichen (unter Ausschluss bestimmter Zeichen) gemäß dem Quellcode.
Das Token wird aus einem begrenzten 27-Zeichen-Set (bcdfghjklmnpqrstvwxz2456789
) generiert, anstatt des vollständigen alphanumerischen Bereichs. Diese Einschränkung reduziert die Gesamtanzahl möglicher Kombinationen auf 14.348.907 (27^5). Folglich könnte ein Angreifer in wenigen Stunden einen Brute-Force-Angriff ausführen, um das Token zu erraten, was möglicherweise zu einem Privileg-Eskalation durch den Zugriff auf sensible Dienstkonten führt.
Zertifikatanforderungen signieren
Wenn Sie die Verben create
in der Ressource certificatesigningrequests
haben (oder zumindest in certificatesigningrequests/nodeClient
). Können Sie eine neue CeSR eines neuen Knotens erstellen.
Gemäß der Dokumentation ist es möglich, diese Anfragen automatisch zu genehmigen, sodass Sie in diesem Fall keine zusätzlichen Berechtigungen benötigen. Andernfalls müssten Sie in der Lage sein, die Anfrage zu genehmigen, was ein Update in certificatesigningrequests/approval
und approve
in signers
mit dem Ressourcennamen <signerNameDomain>/<signerNamePath>
oder <signerNameDomain>/*
bedeutet.
Ein Beispiel für eine Rolle mit allen erforderlichen Berechtigungen ist:
So können Sie mit der Genehmigung des neuen Knoten-Zertifikatantrags die speziellen Berechtigungen der Knoten missbrauchen, um Geheimnisse zu stehlen und Privilegien zu eskalieren.
In diesem Beitrag und diesem wird die GKE K8s TLS-Bootstrap-Konfiguration mit automatischer Signierung konfiguriert und missbraucht, um Anmeldeinformationen für einen neuen K8s-Knoten zu generieren und diese dann zu missbrauchen, um Privilegien zu eskalieren, indem Geheimnisse gestohlen werden. Wenn Sie über die genannten Berechtigungen verfügen, könnten Sie dasselbe tun. Beachten Sie, dass das erste Beispiel den Fehler umgeht, der verhindert, dass ein neuer Knoten auf Geheimnisse in Containern zugreifen kann, da ein Knoten nur auf die Geheimnisse von Containern zugreifen kann, die auf ihm eingebunden sind.
Der Weg, dies zu umgehen, besteht einfach darin, Anmeldeinformationen für einen Knoten mit dem Namen des Knotens zu erstellen, auf dem der Container mit den interessanten Geheimnissen eingebunden ist (aber prüfen Sie einfach, wie es im ersten Beitrag gemacht wird):
AWS EKS aws-auth ConfigMaps
Prinzipien, die configmaps
im kube-system Namespace auf EKS ändern können (müssen in AWS sein), können Cluster-Admin-Berechtigungen erhalten, indem sie den aws-auth ConfigMap überschreiben.
Die benötigten Verben sind update
und patch
, oder create
, wenn der ConfigMap nicht erstellt wurde:
Sie können aws-auth
für Persistenz verwenden, um Benutzern aus anderen Konten Zugriff zu gewähren.
Jedoch funktioniert aws --profile other_account eks update-kubeconfig --name <cluster-name>
nicht von einem anderen Konto aus. Aber tatsächlich funktioniert aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing
, wenn Sie die ARN des Clusters anstelle des Namens angeben.
Um kubectl
zum Laufen zu bringen, stellen Sie einfach sicher, dass Sie die Kubeconfig des Opfers konfigurieren und in den aws exec-Argumenten --profile other_account_role
hinzufügen, damit kubectl das Profil des anderen Kontos verwendet, um das Token zu erhalten und AWS zu kontaktieren.
Eskalation in GKE
Es gibt 2 Möglichkeiten, K8s-Berechtigungen für GCP-Prinzipale zuzuweisen. In jedem Fall benötigt der Prinzipal auch die Berechtigung container.clusters.get
, um Anmeldeinformationen zum Zugriff auf den Cluster zu sammeln, oder Sie müssen Ihre eigene kubectl-Konfigurationsdatei generieren (folgen Sie dem nächsten Link).
Beim Sprechen mit dem K8s-API-Endpunkt wird das GCP-Authentifizierungstoken gesendet. Dann überprüft GCP über den K8s-API-Endpunkt zuerst, ob der Prinzipal (per E-Mail) Zugriff innerhalb des Clusters hat, dann wird überprüft, ob er über GCP IAM Zugriff hat. Wenn eines davon zutrifft, wird er beantwortet. Wenn nicht, wird ein Fehler gemeldet, der darauf hinweist, Berechtigungen über GCP IAM zu erteilen.
Dann ist die erste Methode die Verwendung von GCP IAM, die K8s-Berechtigungen haben ihre entsprechenden GCP IAM-Berechtigungen, und wenn der Prinzipal diese hat, kann er sie verwenden.
GCP - Container PrivescDie zweite Methode besteht darin, K8s-Berechtigungen innerhalb des Clusters zuzuweisen, um den Benutzer anhand seiner E-Mail zu identifizieren (GCP-Servicekonten eingeschlossen).
Erstellen von Serviceaccounts-Token
Prinzipale, die TokenRequests erstellen können (serviceaccounts/token
) Beim Sprechen mit dem K8s-API-Endpunkt können SAs (Informationen von hier).
ephemeralcontainers
Prinzipale, die pods/ephemeralcontainers
aktualisieren
oder patchen
können, können Code auf anderen Pods ausführen und möglicherweise über einen ephemeral Container mit einem privilegierten securityContext auf ihren Knoten ausbrechen.
ValidatingWebhookConfigurations oder MutatingWebhookConfigurations
Prinzipale mit einem der Verben create
, update
oder patch
über validatingwebhookconfigurations
oder mutatingwebhookconfigurations
können möglicherweise eine solche Webhook-Konfiguration erstellen, um Berechtigungen zu eskalieren.
Für ein Beispiel zu mutatingwebhookconfigurations
siehe diesen Abschnitt dieses Beitrags.
Eskalation
Wie Sie im nächsten Abschnitt lesen können: Eingebaute Vorbeugung gegen privilegierte Eskalation, ein Prinzipal kann weder Rollen noch Clusterrollen aktualisieren oder erstellen, ohne selbst diese neuen Berechtigungen zu haben. Es sei denn, er hat das Verb escalate
über Rollen
oder Clusterrollen
.
Dann kann er neue Rollen und Clusterrollen mit besseren Berechtigungen als die, die er hat, aktualisieren/erstellen.
Knoten-Proxy
Prinzipale mit Zugriff auf die nodes/proxy
-Unterressource können über die Kubelet-API Code auf Pods ausführen (gemäß diesem). Weitere Informationen zur Kubelet-Authentifizierung auf dieser Seite:
Hier finden Sie ein Beispiel, wie Sie RCE autorisiert mit einer Kubelet-API sprechen.
Pods löschen + nicht planbare Knoten
Prinzipale, die Pods löschen können (delete
-Verb über Ressource pods
), oder Pods evakuieren können (create
-Verb über Ressource pods/eviction
), oder den Pod-Status ändern können (Zugriff auf pods/status
) und Knoten nicht planbar machen können (Zugriff auf nodes/status
) oder Knoten löschen können (delete
-Verb über Ressource nodes
) und die Kontrolle über einen Pod haben, könnten Pods von anderen Knoten stehlen, sodass sie auf dem kompromittierten Knoten ausgeführt werden und der Angreifer die Token von diesen Pods stehlen kann.
Dienststatus (CVE-2020-8554)
Prinzipale, die services/status
ändern können, können das Feld status.loadBalancer.ingress.ip
ausnutzen, um die ungefixte CVE-2020-8554 zu nutzen und MiTM-Angriffe gegen den Cluster zu starten. Die meisten Maßnahmen gegen CVE-2020-8554 verhindern nur ExternalIP-Dienste (gemäß diesem).
Knoten- und Pod-Status
Prinzipale mit Berechtigungen zum Aktualisieren
oder Patchen
von nodes/status
oder pods/status
könnten Labels ändern, um die durchgesetzten Terminierungsbeschränkungen zu beeinflussen.
Integrierte Vorbeugung gegen privilegierte Eskalation
Kubernetes verfügt über einen integrierten Mechanismus, um privilegierte Eskalation zu verhindern.
Dieses System stellt sicher, dass Benutzer ihre Berechtigungen nicht erhöhen können, indem sie Rollen oder Rollenbindungen ändern. Die Durchsetzung dieser Regel erfolgt auf API-Ebene und bietet einen Schutz, selbst wenn der RBAC-Autorisierer inaktiv ist.
Die Regel besagt, dass ein Benutzer nur eine Rolle erstellen oder aktualisieren kann, wenn er alle Berechtigungen besitzt, die die Rolle umfasst. Darüber hinaus muss der Umfang der vorhandenen Berechtigungen des Benutzers mit dem der Rolle übereinstimmen, die er zu erstellen oder zu ändern versucht: entweder clusterweit für ClusterRoles oder auf denselben Namespace (oder clusterweit) beschränkt für Roles.
Es gibt eine Ausnahme von der vorherigen Regel. Wenn ein Prinzipal das Verb eskaliere
über Rollen
oder ClusterRoles
hat, kann er die Berechtigungen von Rollen und ClusterRoles erhöhen, auch ohne die Berechtigungen selbst zu besitzen.
RolleBindings/ClusterRoleBindings abrufen & patchen
Anscheinend hat diese Technik früher funktioniert, aber laut meinen Tests funktioniert sie nicht mehr aus demselben Grund, der im vorherigen Abschnitt erklärt wurde. Du kannst keine Rollebindung erstellen/ändern, um dir oder einem anderen SA einige Berechtigungen zu geben, wenn du sie nicht bereits hast.
Die Berechtigung zum Erstellen von RolleBindings ermöglicht es einem Benutzer, Rollen an einen Dienstaccount zu binden. Diese Berechtigung kann potenziell zu einer privilegierten Eskalation führen, da es dem Benutzer ermöglicht, Admin-Berechtigungen an einen kompromittierten Dienstaccount zu binden.
Andere Angriffe
Sidecar-Proxy-App
Standardmäßig gibt es keine Verschlüsselung in der Kommunikation zwischen Pods. Gegenseitige Authentifizierung, bidirektional, Pod zu Pod.
Erstellen einer Sidecar-Proxy-App
Erstelle deine .yaml
Bearbeite deine .yaml und füge die auskommentierten Zeilen hinzu:
Siehe die Logs des Proxys:
Mehr Informationen unter: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
Bösartiger Zulassungscontroller
Ein Zulassungscontroller interceptiert Anfragen an den Kubernetes-API-Server vor der Persistenz des Objekts, aber nachdem die Anfrage authentifiziert und autorisiert wurde.
Wenn ein Angreifer es irgendwie schafft, einen Mutationg-Zulassungscontroller einzuschleusen, wird er in der Lage sein, bereits authentifizierte Anfragen zu modifizieren. Dies könnte potenziell zu Privilegienerweiterung führen und sich häufiger im Cluster behaupten.
Beispiel von https://blog.rewanthtammana.com/creating-malicious-admission-controllers:
Überprüfen Sie den Status, um zu sehen, ob es bereit ist:
Dann bereitstellen eines neuen Pods:
Wenn Sie den Fehler ErrImagePull
sehen, überprüfen Sie den Bildnamen mit einem der folgenden Abfragen:
Wie Sie im obigen Bild sehen können, haben wir versucht, das Image nginx
auszuführen, aber das letztendlich ausgeführte Image ist rewanthtammana/malicious-image
. Was ist gerade passiert!!?
Technische Details
Das Skript ./deploy.sh
richtet einen mutierenden Webhook-Zulassungscontroller ein, der Anfragen an die Kubernetes-API gemäß den in seinen Konfigurationszeilen festgelegten Änderungen modifiziert und somit die beobachteten Ergebnisse beeinflusst:
OPA Gatekeeper Umgehung
Kubernetes - OPA Gatekeeper bypassBest Practices
Deaktivierung des automatischen Einbindens von Service Account Tokens
Pods und Service Accounts: Standardmäßig binden Pods ein Service Account Token ein. Um die Sicherheit zu erhöhen, erlaubt Kubernetes die Deaktivierung dieses automatischen Einbindens.
Anwendung: Setzen Sie
automountServiceAccountToken: false
in der Konfiguration von Service Accounts oder Pods ab Kubernetes Version 1.6.
Einschränkende Benutzerzuweisung in RoleBindings/ClusterRoleBindings
Selektive Einbindung: Stellen Sie sicher, dass nur notwendige Benutzer in RoleBindings oder ClusterRoleBindings eingeschlossen sind. Überprüfen Sie regelmäßig und entfernen Sie irrelevante Benutzer, um die Sicherheit zu gewährleisten.
Rollen für bestimmte Namespaces anstelle von Clusterweiten Rollen
Rollen vs. ClusterRoles: Verwenden Sie bevorzugt Rollen und RoleBindings für bereichsspezifische Berechtigungen anstelle von ClusterRoles und ClusterRoleBindings, die clusterweit gelten. Dieser Ansatz bietet eine feinere Kontrolle und begrenzt den Umfang der Berechtigungen.
Verwenden Sie automatisierte Tools
Referenzen
Last updated