![Wie man versteckte Schwachstellen in Kubernetes RBAC-Berechtigungen verwaltet](https://assets.gcore.pro/blog_containerizing_prod/uploads/2024/06/k8s-rbac-permissions-fi.png)
Dieser Artikel wurde ursprünglich auf The New Stack veröffentlicht. Er wurde von Dmitrii Bubnov geschrieben, einem DevSecOps-Ingenieur bei Gcore mit 14 Jahren Erfahrung in der IT.
Die rollenbasierte Zugriffskontrolle (RBAC) ist der Standardansatz für die Zugriffskontrolle in Kubernetes. Dieses Modell kategorisiert Berechtigungen mit Hilfe spezifischer Verbs, um erlaubte Interaktionen mit Ressourcen zu definieren. Innerhalb dieses Systems können drei weniger bekannte Berechtigungen –escalate
, bind
und impersonate
– bestehende Rollenbeschränkungen außer Kraft setzen, unbefugten Zugriff auf eingeschränkte Bereiche gewähren, vertrauliche Daten offenlegen oder sogar die vollständige Kontrolle über einen Cluster ermöglichen. Dieser Artikel erläutert diese leistungsstarken Berechtigungen und gibt einen Überblick über ihre Funktionen sowie Hinweise zur Minderung der damit verbundenen Risiken.
Eine kurze Erinnerung an RBAC-Rollen und Verbs
In diesem Artikel gehe ich davon aus, dass Sie bereits mit den Schlüsselkonzepten von Kubernetes RBAC vertraut sind. Falls nicht, lesen Sie bitte die Dokumentation von Kubernetes.
Wir müssen jedoch kurz an ein wichtiges Konzept erinnern, das in direktem Zusammenhang mit diesem Artikel steht: Role. Hier werden die Zugriffsrechte auf K8s-Ressourcen innerhalb eines bestimmten Namespace und die verfügbaren Operationen beschrieben. Rollen bestehen aus einer Reihe von Regeln. Die Regeln umfassen verbs
-verfügbare Vorgänge für definierte Ressourcen.
Hier ist ein Beispiel für eine Rolle aus der K8s-Dokumentation, die Lesezugriff auf Pods gewährt:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-reader rules: - apiGroups: [""] # "" points to the core API group resources: ["pods"] verbs: ["get", "watch", "list"]
Verbs wie get
, watch
, und list
werden häufig verwendet. Aber es gibt andere, die noch viel spannender sind.
Drei weniger bekannte Kubernetes RBAC-Berechtigungen
Für eine detailliertere und komplexere Verwaltung von Berechtigungen verfügt das K8s RBAC über die folgenden Verbs:
escalate
: Ermöglicht es Benutzern, Rollen zu erstellen und zu bearbeiten, auch wenn sie nicht über die ursprünglichen Berechtigungen dazu verfügen.bind
: Ermöglicht Benutzern die Erstellung und Bearbeitung von Rollenbindungen und Cluster-Rollenbindungen mit Berechtigungen, die ihnen nicht zugewiesen wurden.impersonate
: Ermöglicht es Benutzern, sich als andere Benutzer auszugeben und deren Berechtigungen im Cluster oder in einer anderen Gruppe zu erhalten. Mit diesem Verb kann auf kritische Daten zugegriffen werden.
Im Folgenden werden wir sie genauer kennenlernen. Aber zuerst wollen wir einen Test-Namespace erstellen und ihn rbac nennen:
kubectl create ns rbac
Erstellen Sie dann eine Test-SA privesc:
kubectl -n rbac create sa privesc
Wir werden sie im weiteren Verlauf dieses Lehrgangs verwenden.
Escalate
Standardmäßig erlaubt die RBAC-API von Kubernetes Benutzern nicht, ihre Berechtigungen durch einfaches Bearbeiten einer Rolle oder Rollenbindung zu erweitern. Diese Einschränkung gilt auf API-Ebene auch dann, wenn die RBAC-Autorisierung deaktiviert ist. Die einzige Ausnahme ist, wenn die Rolle das Verb escalate
hat.
In der folgenden Abbildung kann die SA, die nur über die Berechtigungen update
und patch
verfügt, der Rolle kein neues Verb hinzufügen. Aber wenn wir eine neue Rolle mit dem Verb escalate
hinzufügen, wird es möglich:
![Wie das Hinzufügen des Verbs](https://assets.gcore.pro/blog_containerizing_prod/uploads/2024/06/k8s-rbac-permissions-1.png)
Schauen wir uns die Funktionsweise im Detail an.
Erstellen Sie eine Rolle, die nur Lesezugriff auf Pods und Rollen in diesem Namespace erlaubt:
kubectl -n rbac create role view --verb=list,watch,get --resource=role,pod
Verknüpfen Sie diese Rolle mit der SA privesc:
kubectl -n rbac create rolebinding view --role=view --serviceaccount=rbac:privesc
Prüfen Sie, ob die Rolle aktualisiert werden kann:
kubectl auth can-i update role -n rbac --as=system:serviceaccount:rbac:privesc no
Wie wir sehen können, kann die SA Rollen lesen, aber nicht bearbeiten.
Erstellen Sie eine neue Rolle, die die Bearbeitung von Rollen im rbac-Namenspace ermöglicht:
kubectl -n rbac create role edit --verb=update,patch --resource=role
Verknüpfen Sie diese neue Rolle an die SA privesc:
kubectl -n rbac create rolebinding edit --role=edit --serviceaccount=rbac:privesc
Prüfen Sie, ob die Rolle aktualisiert werden kann:
kubectl auth can-i update role -n rbac --as=system:serviceaccount:rbac:privesc yes
Prüfen Sie, ob die Rolle gelöscht werden kann:
kubectl auth can-i delete role -n rbac --as=system:serviceaccount:rbac:privesc no
Die SA kann jetzt Rollen bearbeiten, aber nicht löschen.
Im Interesse der experimentellen Genauigkeit sollten wir die SA-Fähigkeiten überprüfen. Dazu verwenden wir ein JWT (JSON Web Token):
TOKEN=$(kubectl -n rbac create token privesc --duration=8h)
Wir sollten die alten Authentifizierungsparameter aus der Konfiguration entfernen, da Kubernetes zuerst das Zertifikat des Benutzers überprüft und das Token nicht überprüft, wenn es das Zertifikat bereits kennt.
cp ~/.kube/config ~/.kube/rbac.conf export KUBECONFIG=~/.kube/rbac.conf kubectl config delete-user kubernetes-admin kubectl config set-credentials privesc --token=$TOKEN kubectl config set-context --current --user=privesc
Diese Rolle zeigt, dass wir andere Rollen bearbeiten können:
kubectl -n rbac get role edit -oyaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: edit namespace: rbac rules: - apiGroups: - rbac.authorization.k8s.io resources: - roles verbs: - update - patch
Versuchen wir, ein neues Verb hinzuzufügen, list
, das wir bereits in der Ansichtsrolle verwendet haben:
kubectl -n rbac edit role edit OK apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: edit namespace: rbac rules: - apiGroups: - rbac.authorization.k8s.io resources: - roles verbs: - update - patch - list # the new verb we added
Success.
Versuchen wir nun, ein neues Verb hinzuzufügen, nämlich delete, das wir in anderen Rollen noch nicht verwendet haben:
kubectl -n rbac edit role edit apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: edit namespace: rbac rules: - apiGroups: - rbac.authorization.k8s.io resources: - roles verbs: - update - patch - delete # trying to add a new verb error: roles.rbac.authorization.k8s.io "edit" could not be patched: roles.rbac.authorization.k8s.io "edit" is forbidden: user "system:serviceaccount:rbac:privesc" (groups=["system:serviceaccounts" "system:serviceaccounts:rbac" "system:authenticated"]) is attempting to grant RBAC permissions not currently held: {APIGroups:["rbac.authorization.k8s.io"], Resources:["roles"], Verbs:["delete"]}
Dies bestätigt, dass Kubernetes es Benutzern oder Dienstkonten nicht erlaubt, neue Berechtigungen hinzuzufügen, wenn sie diese nicht bereits haben – nur wenn Benutzer oder Dienstkonten an Rollen mit solchen Berechtigungen gebunden sind.
Erweitern wir die privesc SA-Berechtigungen. Dazu verwenden wir die Admin-Konfiguration und fügen eine neue Rolle mit dem Verb escalate
hinzu:
KUBECONFIG=~/.kube/config kubectl -n rbac create role escalate --verb=escalate --resource=role
Jetzt binden wir die privesc SA an die neue Rolle:
KUBECONFIG=~/.kube/config kubectl -n rbac create rolebinding escalate --role=escalate --serviceaccount=rbac:privesc
Prüfen Sie noch einmal, ob wir der Rolle ein neues Verb hinzufügen können:
kubectl -n rbac edit role edit apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: edit namespace: rbac rules: - apiGroups: - rbac.authorization.k8s.io resources: - roles verbs: - update - patch - delete # the new verb we added role.rbac.authorization.k8s.io/edit edited
Jetzt funktioniert es. Der Benutzer kann die SA-Rechte erweitern, indem er die bestehende Rolle bearbeitet. Das bedeutet, dass das Verb escalate
die Rechte eines Admins, einschließlich der Rechte eines Namespace-Admins oder sogar eines Cluster-Admins, verleiht.
Bind
Das bind
Verb erlaubt es dem Benutzer die Bearbeitung der RoleBinding
oder ClusterRoleBinding
für Berechtigungserweiterung, ähnlich wie bei escalate
die es dem Benutzer ermöglicht, die Role
oder ClusterRole
.
In der folgenden Abbildung kann die SA mit der Rollenbindung, die die Verbs update
, patch
und create
enthält, erst dann delete
hinzufügen, wenn wir eine neue Rolle mit dem Verb bind
erstellen.
![Wie das Hinzufügen des Verbs](https://assets.gcore.pro/blog_containerizing_prod/uploads/2024/06/k8s-rbac-permissions-2.png)
Schauen wir uns nun genauer an, wie das funktioniert.
Ändern wir die kubeconfig-Datei auf admin:
export KUBECONFIG=~/.kube/config
Entfernen Sie alte Rollen und Bindungen:
kubectl -n rbac delete rolebinding view edit escalate kubectl -n rbac delete role view edit escalate
Erlauben Sie der SA, die Rollenbindung und die Pod-Ressourcen im Namenspace anzuzeigen und zu bearbeiten:
kubectl -n rbac create role view --verb=list,watch,get --resource=role,rolebinding,pod kubectl -n rbac create rolebinding view --role=view --serviceaccount=rbac:privesc kubectl -n rbac create role edit --verb=update,patch,create --resource=rolebinding,pod kubectl -n rbac create rolebinding edit --role=edit --serviceaccount=rbac:privesc
Erstellen Sie separate Rollen für die Arbeit mit Pods, aber binden Sie die Rolle trotzdem nicht:
kubectl -n rbac create role pod-view-edit --verb=get,list,watch,update,patch --resource=pod kubectl -n rbac create role delete-pod --verb=delete --resource=pod
Ändern Sie die kubeconfig auf das SA-Recht und versuchen Sie, die Rollenbindung zu bearbeiten:
export KUBECONFIG=~/.kube/rbac.conf kubectl -n rbac create rolebinding pod-view-edit --role=pod-view-edit --serviceaccount=rbac:privesc rolebinding.rbac.authorization.k8s.io/pod-view-edit created
Die neue Rolle wurde erfolgreich an die SA gebunden. Beachten Sie, dass die Rolle pod-view-edit
Verbs und Ressourcen enthält, die bereits durch die Rollenbindung view
und edit
an die SA gebunden wurden.
Versuchen wir nun, eine Rolle mit einem neuen Verb zu binden, delete
, das in den an die SA gebundenen Rollen fehlt:
kubectl -n rbac create rolebinding delete-pod --role=delete-pod --serviceaccount=rbac:privesc error: failed to create rolebinding: rolebindings.rbac.authorization.k8s.io "delete-pod" is forbidden: user "system:serviceaccount:rbac:privesc" (groups=["system:serviceaccounts" "system:serviceaccounts:rbac" "system:authenticated"]) is attempting to grant RBAC permissions not currently held: {APIGroups:[""], Resources:["pods"], Verbs:["delete"]}
Kubernetes lässt dies nicht zu, obwohl wir die Berechtigung haben, Rollenbindungen zu bearbeiten und zu erstellen. Aber das können wir mit dem Verb bind
ändern. Verwenden wir dazu die Admin-Konfiguration:
KUBECONFIG=~/.kube/config kubectl -n rbac create role bind --verb=bind --resource=role role.rbac.authorization.k8s.io/bind created KUBECONFIG=~/.kube/config kubectl -n rbac create rolebinding bind --role=bind --serviceaccount=rbac:privesc rolebinding.rbac.authorization.k8s.io/bind created
Versuchen Sie noch einmal, eine Rollenbindung mit dem neuen Verb delete
zu erstellen:
kubectl -n rbac create rolebinding delete-pod --role=delete-pod --serviceaccount=rbac:privesc rolebinding.rbac.authorization.k8s.io/delete-pod created
Jetzt funktioniert es. Mit dem Verb bind
kann die SA also jede Rolle an sich selbst oder an jeden Benutzer binden.
Impersonate
Das Verb impersonate
in K8s ist wie sudo
in Linux. Wenn Benutzer Zugriff auf impersonate
haben, können sie sich als andere Benutzer authentifizieren und Befehle in deren Namen ausführen. kubectl verfügt über die Optionen --as
, --as-group
und --as-uid
, die es ermöglichen, Befehle unter einem anderen Benutzer, einer anderen Gruppe bzw. einer anderen UID (einem universell eindeutigen Bezeichner) auszuführen. Wenn ein Benutzer Impersonation-Berechtigungen erhält, wird er zum Namespace-Admin oder – wenn es im Namespace ein cluster-admin-Dienstkonto gibt – sogar zum Cluster-Admin.
Impersonate ist hilfreich, um die an einen Benutzer delegierten RBAC-Berechtigungen zu überprüfen: Ein Administrator sollte einen Befehl gemäß der Vorlage kubectl auth can-i --as=$USERNAME -n $NAMESPACE $VERB $RESOURCE
ausführen und prüfen, ob die Berechtigung wie vorgesehen funktioniert.
In unserem Beispiel würde die SA keine Informationen über Pods im rbac-Namensraum erhalten, wenn sie nur kubectl -n rbac get pod
ausführt. Aber es wird möglich, wenn es eine Rolle mit dem Verb impersonate
gibt:
kubectl auth can-i get pod -n rbac --as=system:serviceaccount:rbac:privesc yes
![Die Rolle mit dem Verb impersonate hilft dem Benutzer, Informationen über Pods zu erhalten](https://assets.gcore.pro/blog_containerizing_prod/uploads/2024/06/k8s-rbac-permissions-3.png)
Erstellen wir ein neues Dienstkonto, impersonator, im rbac-Namensraum; diese SA wird keine Berechtigungen haben:
KUBECONFIG=~/.kube/config kubectl -n rbac create sa impersonator serviceaccount/impersonator created
Erstellen Sie nun eine Rolle mit dem Verb impersonate und einer Rollenbindung:
KUBECONFIG=~/.kube/config kubectl -n rbac create role impersonate --resource=serviceaccounts --verb=impersonate --resource-name=privesc
(Sehen Sie sich den Parameter --resource-name
im obigen Befehl an: er erlaubt nur Impersonation als privesc SA.)
role.rbac.authorization.k8s.io/impersonate created KUBECONFIG=~/.kube/config kubectl -n rbac create rolebinding impersonator --role=impersonate --serviceaccount=rbac:impersonator rolebinding.rbac.authorization.k8s.io/impersonator created
Erstellen Sie einen neuen Kontext:
TOKEN=$(KUBECONFIG=~/.kube/config kubectl -n rbac create token impersonator --duration=8h) kubectl config set-credentials impersonate --token=$TOKEN User "impersonate" set. kubectl config set-context impersonate@kubernetes --user=impersonate --cluster=kubernetes Context "impersonate@kubernetes" created. kubectl config use-context impersonate@kubernetes Switched to context "impersonate@kubernetes".
Überprüfen Sie die Berechtigungen:
kubectl auth can-i --list -n rbac Resources Non-Resource URLs Resource Names Verbs selfsubjectaccessreviews.authorization.k8s.io [] [] [create] selfsubjectrulesreviews.authorization.k8s.io [] [] [create] ... serviceaccounts [] [privesc] [impersonate]
Neben impersonate
gibt es keine weiteren Berechtigungen, wie in der Rolle angegeben. Wenn wir jedoch die impersonator
SA als privesc
SA ausgeben, können wir sehen, dass wir dieselben Berechtigungen erhalten, die die privesc
SA hat:
kubectl auth can-i --list -n rbac --as=system:serviceaccount:rbac:privesc Resources Non-Resource URLs Resource Names Verbs roles.rbac.authorization.k8s.io [] [edit] [bind escalate] selfsubjectaccessreviews.authorization.k8s.io [] [] [create] selfsubjectrulesreviews.authorization.k8s.io [] [] [create] pods [] [] [get list watch update patch delete create] ... rolebindings.rbac.authorization.k8s.io [] [] [list watch get update patch create bind escalate] roles.rbac.authorization.k8s.io [] [] [list watch get update patch create bind escalate] configmaps [] [] [update patch create delete] secrets [] [] [update patch create delete]
Somit hat die impersonate
SA alle ihre eigenen Privilegien und alle Privilegien der SA, die sie verkörpert, einschließlich derjenigen, die ein Namespace-Admin hat.
Wie man potenzielle Bedrohungen entschärft
Die Verbs escalate
, bind
und impersonate
können zur Erstellung flexibler Berechtigungen verwendet werden, die eine granulare Verwaltung des Zugriffs auf die Infrastruktur von K8 ermöglichen. Sie öffnen aber auch Tür und Tor für eine böswillige Nutzung, da sie in einigen Fällen einem Benutzer den Zugriff auf wichtige Infrastrukturkomponenten mit Administratorrechten ermöglichen.
Drei Vorgehensweisen können helfen, die potenziellen Gefahren einer missbräuchlichen oder böswilligen Verwendung dieser Verbs zu entschärfen:
- Regelmäßige Überprüfung der RBAC-Manifests
- Verwenden Sie das Feld
resourceNames
in den ManifestsRole
undClusterRole
- Externe Tools zur Überwachung von Rollen verwenden
Betrachten wir sie der Reihe nach.
Regelmäßige Überprüfung der RBAC-Manifests
Um unbefugten Zugriff und RBAC-Fehlkonfigurationen zu verhindern, sollten Sie die RBAC-Manifests Ihres Clusters regelmäßig überprüfen:
kubectl get clusterrole -A -oyaml | yq '.items[] | select (.rules[].verbs[] | contains("esalate" | "bind" | "impersonate")) | .metadata.name' kubectl get role -A -oyaml | yq '.items[] | select (.rules[].verbs[] | contains("esalate" | "bind" | "impersonate")) | .metadata.name'
Verwenden Sie das Feld ResourceNames
Um die Verwendung von escalate
, bind
, impersonate
oder beliebige andere Verben, konfigurieren Sie die resourceNames
Feld in der Role
und ClusterRole
Manifests. Dort können – und sollten – Sie die Namen der Ressourcen eingeben, die verwendet werden können.
Hier ist ein Beispiel für ein ClusterRole
, das die Erstellung eines ClusterRoleBinding
mit roleRef
named edit
und view
ermöglicht:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: role-grantor rules: - apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles"] verbs: ["bind"] resourceNames: ["edit","view"]
Das Gleiche gilt für „escalate“ und „impersonate“.
Beachten Sie, dass im Fall von bind
ein Administrator die Berechtigungen in einer Rolle festlegt und die Benutzer diese Rolle nur an sich selbst binden können, wenn dies in resourceNames
erlaubt ist. Mit escalate
können Benutzer beliebige Parameter innerhalb einer Rolle schreiben und Admins eines Namespaces oder Clusters werden. So schränkt bind
die Nutzer ein, während escalate
ihnen mehr Möglichkeiten bietet. Beachten Sie dies, wenn Sie diese Berechtigungen erteilen müssen.
Verwenden Sie externe Tools für das Monitoring von Rollen
Ziehen Sie den Einsatz automatischer Systeme in Betracht, die das Erstellen oder Bearbeiten von Rollen mit verdächtigen Inhalten überwachen, z.B. Falco oder Tetragon.
Sie können Kubernetes-Audit-Protokolle auch an ein Protokollverwaltungssystem wie Gcore Managed Logging weiterleiten, das für die Analyse und Analyse von K8s-Protokollen nützlich ist. Um ein versehentliches Löschen von Ressourcen zu verhindern, erstellen Sie ein separates Dienstkonto mit dem Verb delete
und erlauben Sie den Benutzern, nur dieses Dienstkonto zu verkörpern. Das ist das Prinzip des geringsten Widerstandes. Um diesen Prozess zu vereinfachen, können Sie das kubectl-Plugin kubectl-sudo verwenden.
Bei Gcore nutzen wir diese Methoden, um unseren Managed Kubernetes-Service sicherer zu machen. Wir empfehlen allen unseren Kunden, dasselbe zu tun. Die Nutzung von Managed Services garantiert nicht, dass Ihre Dienste standardmäßig 100% sicher sind, aber bei Gcore tun wir alles, um den Schutz unserer Kunden zu gewährleisten, einschließlich der Förderung von RBAC Best Practices.
Fazit
Mit den Verben escalate
, bind
und impersonate
können Administratoren den Zugriff auf die K8-Infrastruktur flexibel verwalten und Benutzern die Möglichkeit geben, ihre Berechtigungen zu erweitern. Dies sind mächtige Werkzeuge, die bei Missbrauch erheblichen Schaden an einem K8s-Cluster anrichten können. Prüfen Sie jede Verwendung dieser Verben sorgfältig und stellen Sie sicher, dass die Regel der geringsten Zugriffsberechtigung befolgt wird: Benutzer müssen die minimalen Rechte haben, die für den Betrieb erforderlich sind, nicht mehr.
Suchen Sie nach einer einfachen Möglichkeit, Ihre K8s-Cluster zu verwalten? Testen Sie Gcore Managed Kubernetes. Wir bieten virtuelle Maschinen und Bare-Metal-Server mit GPU-Worker-Nodes zur Steigerung Ihrer KI/ML-Workloads. Die Preise für Worker Nodes sind dieselben wie für unsere virtuellen Maschinen und Bare Metal Server. Wir bieten Ihnen ein kostenloses, production-grade Cluster-Management mit einem SLA von 99,9 %, damit Sie sich keine Sorgen machen müssen.