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.
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:
| Objekt | Geltungsbereich | Gewährt |
|---|---|---|
Role | Namespace | Regeln (Verben auf Ressourcen) in einem Namespace |
ClusterRole | Cluster | Regeln auf clusterweite Ressourcen oder wiederverwendbar über Namespaces |
RoleBinding | Namespace | Eine Role oder ClusterRole an Subjects, innerhalb eines Namespace |
ClusterRoleBinding | Cluster | Eine 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:
escalateauf roles oder clusterroles: eine Rolle mit mehr Rechten schreiben, als man selbst hat.bindauf roles oder clusterroles: eine Rolle binden, die man nicht besitzt, auch cluster-admin.impersonateauf 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:
| Regel | Schweregrad | Logik |
|---|---|---|
| Binding an cluster-admin erstellt | Kritisch | (Cluster)RoleBinding mit roleRef.name: cluster-admin |
| Zugriff für anonyme / nicht authentifizierte Nutzer gewährt | Kritisch | Binding mit Subject system:anonymous oder system:unauthenticated |
| Rolle gewährt escalate/bind/impersonate oder Wildcards | Hoch | (Cluster)Role mit diesen Verben oder *-Verben/-Ressourcen geschrieben |
| Request unter Impersonation einer anderen Identität | Mittel | impersonatedUser vorhanden |
| Anonymer Request zugelassen | Hoch | system:anonymous über Health-, Version- und OIDC-Discovery-Endpunkte hinaus erlaubt |
| Cluster-weites Role-Binding erstellt | Niedrig | Jedes 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-authIAM-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
aggregationRulepassen, 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
- Sichern Sie die betroffenen Objekte (
kubectl get clusterrolebinding <name> -o yaml) als Beweis und löschen Sie sie dann. - 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.
- Prüfen Sie jedes Binding an cluster-admin und an Rollen, die RBAC schreiben, Secrets lesen oder exec in Pods ausführen dürfen.
- Entfernen Sie
escalate,bind,impersonateund Wildcards aus Rollen, die sie nicht zwingend brauchen. - Deaktivieren Sie die anonyme Authentifizierung oder beschränken Sie sie auf Health-Endpunkte.