Wie man versteckte Schwachstellen in Kubernetes RBAC-Berechtigungen verwaltet

Wie man versteckte Schwachstellen in Kubernetes RBAC-Berechtigungen verwaltet

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
Abbildung 1: Durch Hinzufügen des Verbs „escalate“ zur Rolle kann der Benutzer die Rollenberechtigungen ändern und ein neues Verb hinzufügen

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 escalatedie 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
Abbildung 2: Das Hinzufügen der neuen Rolle mit dem Verb bind ermöglicht es dem Benutzer, die Bindungsberechtigungen der Rolle zu erweitern

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
Abbildung 3: Abrufen von Informationen über Pods mit einer Rolle, die das Verb impersonate hat

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 Manifests Role und ClusterRole
  • 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, impersonateoder 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.

Entdecken Sie Gcore Managed Kubernetes

Wie man versteckte Schwachstellen in Kubernetes RBAC-Berechtigungen verwaltet

Melden Sie sich
für unseren Newsletter an

Erhalten Sie die neuesten Branchentrends, exklusive Einblicke und Gcore-Updates
direkt in Ihren Posteingang.