Skip to content

Dieses Tool ist nicht mit The Linux Foundation, der Cloud Native Computing Foundation (CNCF) oder dem Kubernetes-Projekt verbunden und wird von diesen weder befürwortet noch gesponsert. Kubernetes und K8s sind eingetragene Marken von The Linux Foundation. EKS, GKE, AKS und andere Namen sind Marken ihrer jeweiligen Inhaber.

Kubernetes-RBAC-Rechteausweitung in Audit-Logs erkennen

Kubernetes-RBAC-Rechteausweitung in Audit-Logs finden: Bindings an cluster-admin, Verben escalate, bind und impersonate, Impersonation und anonymer Zugriff.

Veröffentlicht am 5 Min. Lesezeit

TL;DR. Im Audit-Log ist eine RBAC-Eskalation ein Schreibzugriff: ein create, update oder patch auf clusterrolebindings, rolebindings, clusterroles oder roles. Gefährlich sind die, die cluster-admin binden, die Verben escalate, bind oder impersonate oder *-Wildcards gewähren oder system:anonymous / system:unauthenticated nennen. Um roleRef und subjects zu sehen, brauchen Sie Request-Bodies (Level Request). Achten Sie außerdem auf das Feld impersonatedUser und denken Sie daran, dass Cloud-IAM Clusterzugriff ganz ohne Kubernetes-RBAC-Objekt gewähren kann.

Ein neues Binding an cluster-admin ist das verlässlichste Zeichen für einen ernsten Kubernetes-Einbruch: So macht ein Angreifer aus einem geliehenen Token eine dauerhafte Identität. ATT&CK führt das als T1098.006, Additional Container Cluster Roles.

RBAC in einer Tabelle

RBAC kennt vier Objektarten:

ObjektGeltungsbereichGewährt
RoleNamespaceRegeln (Verben auf Ressourcen) in einem Namespace
ClusterRoleClusterRegeln auf clusterweite Ressourcen oder wiederverwendbar über Namespaces
RoleBindingNamespaceEine Role oder ClusterRole an Subjects, innerhalb eines Namespace
ClusterRoleBindingClusterEine ClusterRole an Subjects, überall

Das roleRef des Bindings nennt die Rolle; subjects listet Benutzer, Gruppen oder Service Accounts. Beides steht im Request-Body, eine Policy, die RBAC-Schreibzugriffe auf Metadata protokolliert, sagt Ihnen also „ein ClusterRoleBinding namens node-health-admin wurde angelegt“ und nichts darüber, was es gewährt.

Die Verben zur Eskalationsverhinderung

Kubernetes blockiert naive Eskalation: Die RBAC-Dokumentation erklärt, dass Sie eine Rolle nur mit Rechten anlegen oder ändern dürfen, die Sie bereits haben, und nur eine Rolle binden dürfen, deren Rechte Sie bereits besitzen. Drei Verben heben diese Prüfungen auf:

  • escalate auf roles oder clusterroles: eine Rolle mit mehr Rechten schreiben, als man selbst hat.
  • bind auf roles oder clusterroles: eine Rolle binden, die man nicht besitzt, auch cluster-admin.
  • impersonate auf Benutzer, Gruppen oder Service Accounts: als jemand anderes handeln.

Die RBAC Good Practices führen alle drei als Risiken der Rechteausweitung, ebenso *-Wildcards, die auch jeden künftig hinzukommenden Ressourcentyp abdecken. Eine Rolle, die eines davon einer Person oder einem Workload gewährt, ist ein Weg zu cluster-admin.

Erkennungen

Der Audit-Log-Analyzer prüft RBAC-Schreibzugriffe mit diesen Regeln:

RegelSchweregradLogik
Binding an cluster-admin erstelltKritisch(Cluster)RoleBinding mit roleRef.name: cluster-admin
Zugriff für anonyme / nicht authentifizierte Nutzer gewährtKritischBinding mit Subject system:anonymous oder system:unauthenticated
Rolle gewährt escalate/bind/impersonate oder WildcardsHoch(Cluster)Role mit diesen Verben oder *-Verben/-Ressourcen geschrieben
Request unter Impersonation einer anderen IdentitätMittelimpersonatedUser vorhanden
Anonymer Request zugelassenHochsystem:anonymous über Health-, Version- und OIDC-Discovery-Endpunkte hinaus erlaubt
Cluster-weites Role-Binding erstelltNiedrigJedes ClusterRoleBinding, das eine Nicht-System-Identität schreibt

Die Regel mit niedrigem Schweregrad gibt es wegen der oben genannten Logging-Lücke: Fehlt der Body, ist ein neues ClusterRoleBinding trotzdem einen Blick wert, und die Annotation authorization.k8s.io/reason späterer Requests nennt es, sobald es genutzt wird.

Ein bösartiges Binding lesen

Ein fiktives Beispiel, protokolliert auf Level RequestResponse:

{
  "verb": "create",
  "user": { "username": "system:serviceaccount:kubernetes-dashboard:kubernetes-dashboard" },
  "sourceIPs": ["203.0.113.45"],
  "userAgent": "kubectl/v1.30.2 (linux/amd64) kubernetes/3968350",
  "objectRef": { "resource": "clusterrolebindings", "name": "node-health-admin",
                 "apiGroup": "rbac.authorization.k8s.io" },
  "requestObject": {
    "kind": "ClusterRoleBinding",
    "metadata": { "name": "node-health-admin" },
    "roleRef": { "apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "cluster-admin" },
    "subjects": [ { "kind": "ServiceAccount", "name": "node-health", "namespace": "kube-system" } ]
  },
  "responseStatus": { "code": 201 }
}

Drei Dinge fallen auf: ein Service Account, der RBAC-Objekte anlegt, von einer Internetadresse, mit kubectl; ein Name, der wie eine Systemkomponente klingen soll; und ein neuer Service Account in kube-system als Subject. Der nächste Schritt des Angreifers ist meist ein TokenRequest für diesen Service Account, der ihm ein Zugangsdatum unabhängig vom ursprünglich gestohlenen verschafft. Der fiktive Walkthrough folgt genau dieser Abfolge.

Impersonation

Ein Aufrufer mit der Berechtigung impersonate kann die Header Impersonate-User, Impersonate-Group (und verwandte) senden; der Request wird dann als die impersonierte Identität autorisiert. Das Audit-Event hält beides fest: user ist der echte Aufrufer, impersonatedUser die behauptete Identität. Berichten Sie immer beides und prüfen Sie, wer überhaupt impersonate hat: In den meisten Clustern sollte diese Liste sehr kurz sein.

kubectl --as=<user> und --as-group nutzen diese Header; manche Zugriffs-Proxys und Dashboards ebenfalls, deshalb markiert der Analyzer Impersonation mit mittlerem Schweregrad und überlässt Ihnen die Bewertung.

Anonymer Zugriff

Sofern nicht deaktiviert, werden Requests ohne Zugangsdaten als system:anonymous in der Gruppe system:unauthenticated authentifiziert, wie die Dokumentation zur Authentifizierung beschreibt. Health- und Discovery-Endpunkte sind häufig offen. Ein Binding, das diesen Subjects mehr gewährt, bedeutet, dass jeder, der den API-Server erreicht, diese Rechte hat. Die Einstellungen dazu finden Sie im Glossareintrag system:anonymous.

Eskalationswege ohne RBAC-Schreibzugriff

Nicht jede Eskalation erscheint als Binding:

  • Cloud-IAM. Auf EKS bilden Access Entries und die ConfigMap aws-auth IAM-Principals auf Kubernetes-Identitäten ab; eine Admin-Zugriffsrichtlinie einem Access Entry zuzuordnen geschieht in der AWS-API (CloudTrail), nicht im Kubernetes-Audit-Log. GKE gewährt Clusterzugriff über Google-Cloud-IAM-Rollen, AKS über Azure-RBAC-Rollenzuweisungen, wenn Azure RBAC für Kubernetes aktiv ist. Prüfen Sie diese Änderungen in den Control-Plane-Logs der Cloud.
  • ClusterRole-Aggregation. Eine ClusterRole mit Labels, die zu einer aggregationRule passen, wird mit ihren Regeln in die aggregierte Rolle übernommen. Eine solche Rolle hinzuzufügen erweitert still jedes Binding der aggregierten Rolle.
  • Workloads anlegen. Wer in einem Namespace Pods anlegen darf, kann jeden Service Account dieses Namespace mounten und als er handeln. Siehe Secrets und Token-Diebstahl.
  • Zertifikate. Das Recht, CertificateSigningRequests zu genehmigen, erlaubt Client-Zertifikate für beliebige Identitäten.
  • Admission-Webhooks. Wer Webhook-Konfigurationen kontrolliert, kann Objekte beim Anlegen sehen oder umschreiben.

Hunting-Abfragen

Rohe JSON-Zeilen, Bindings an cluster-admin:

jq -c 'select((.objectRef.resource == "clusterrolebindings" or .objectRef.resource == "rolebindings")
              and (.verb == "create" or .verb == "update" or .verb == "patch")
              and .requestObject.roleRef.name == "cluster-admin")
       | {t: .requestReceivedTimestamp, user: .user.username, ip: .sourceIPs,
          name: .objectRef.name, subjects: .requestObject.subjects}' audit.log

EKS, CloudWatch Logs Insights, alle RBAC-Schreibzugriffe:

fields @timestamp, user.username, verb, objectRef.resource, objectRef.name
| filter @logStream like "kube-apiserver-audit"
| filter objectRef.apiGroup = "rbac.authorization.k8s.io"
| filter verb in ["create", "update", "patch", "delete"]
| sort @timestamp desc

Behebung

  1. Sichern Sie die betroffenen Objekte (kubectl get clusterrolebinding <name> -o yaml) als Beweis und löschen Sie sie dann.
  2. Löschen Sie jeden Service Account, der cluster-admin erhalten hat, und legen Sie ihn neu an, damit für ihn ausgestellte Tokens nicht mehr funktionieren.
  3. Prüfen Sie jedes Binding an cluster-admin und an Rollen, die RBAC schreiben, Secrets lesen oder exec in Pods ausführen dürfen.
  4. Entfernen Sie escalate, bind, impersonate und Wildcards aus Rollen, die sie nicht zwingend brauchen.
  5. Deaktivieren Sie die anonyme Authentifizierung oder beschränken Sie sie auf Health-Endpunkte.

Verwandte Artikel

Verwandte Artikel

Krypto-Mining in Kubernetes-Clustern über Audit-Logs erkennen: Miner-Images und -Argumente, unübliche Registries, Persistenz per CronJob und DaemonSet.
Vorbereitung eines Container-Escapes in Kubernetes-Audit-Logs erkennen: privilegierte Pods, hostPID, hostNetwork, hostPath auf / und DaemonSets in kube-system.
Secret-Diebstahl und gestohlene Service-Account-Tokens in Kubernetes-Audit-Logs erkennen: clusterweite Lists, Häufungen, TokenRequest, öffentliche IPs.

Dieses Tool ist nicht mit The Linux Foundation, der Cloud Native Computing Foundation (CNCF) oder dem Kubernetes-Projekt verbunden und wird von diesen weder befürwortet noch gesponsert. Kubernetes und K8s sind eingetragene Marken von The Linux Foundation. EKS, GKE, AKS und andere Namen sind Marken ihrer jeweiligen Inhaber.