Skip to content

Cet outil n'est ni affilié à The Linux Foundation, à la Cloud Native Computing Foundation (CNCF) ou au projet Kubernetes, ni approuvé ni sponsorisé par eux. Kubernetes et K8s sont des marques déposées de The Linux Foundation. EKS, GKE, AKS et les autres noms sont des marques de leurs propriétaires respectifs.

Pods privilégiés et évasion de conteneur : les indices

Repérer une évasion de conteneur en préparation dans les logs d'audit Kubernetes : pods privilégiés, hostPID, hostPath sur /, DaemonSets dans kube-system.

Publié le 6 min de lecture

TL;DR. Le log d'audit ne voit pas une évasion de conteneur se produire, mais il voit la spec de pod qui la rend triviale. Cherchez les écritures de workloads (pods, deployments, daemonsets, jobs, cronjobs…) dont le corps fixe securityContext.privileged: true, ajoute SYS_ADMIN, partage hostPID / hostNetwork / hostIPC, ou monte un hostPath sur /, /etc, /var/lib/kubelet ou un socket de runtime de conteneurs. Un conteneur privilégié avec le système de fichiers racine ou l'espace PID du nœud, c'est la prise de contrôle du nœud. Enchaînez avec l'exec qui l'a exploité (chroot /host, nsenter). Tout cela exige les corps de requête dans le log.

ATT&CK découpe cela en T1610, Deploy Container et T1611, Escape to Host. Dans Kubernetes, les deux se suivent en général à moins d'une minute, et le log d'audit enregistre la première en entier.

Pourquoi ces réglages comptent

Un conteneur, c'est un ensemble de namespaces Linux et de restrictions sur un noyau partagé. Chacun de ces réglages de pod retire une couche :

RéglageCe qu'il donne au conteneur
securityContext.privileged: trueToutes les capabilities, accès aux périphériques de l'hôte ; peut monter le disque de l'hôte
capabilities.add: ["SYS_ADMIN"] (ou ALL)L'essentiel de ce que donne privileged, montages compris
hostPID: trueVoit et peut signaler tous les processus du nœud ; nsenter -t 1 entre dans l'hôte
hostNetwork: trueUtilise la pile réseau du nœud : services locaux, endpoint de métadonnées cloud, écoute du trafic
hostIPC: truePartage l'espace IPC du nœud
hostPath sur /Tout le système de fichiers du nœud : identifiants du kubelet, volumes des autres pods, chroot
hostPath sur /var/run/docker.sock, containerd.sock, crio.sockParle au runtime de conteneurs : lance des conteneurs hors de Kubernetes
hostPath sur /etc, /root, /var/lib/kubeletConfiguration de l'hôte, clés SSH, identifiants du kubelet et secrets des pods

Les bonnes pratiques RBAC de Kubernetes notent que le droit de créer des workloads ou des PersistentVolumes peut inclure la création de volumes hostPath, donc l'accès au système de fichiers de l'hôte. Le profil Baseline des Pod Security Standards interdit tous les réglages ci-dessus pour cette raison.

Ce que montre le log d'audit

Un DaemonSet fictif, réduit à l'essentiel :

{
  "verb": "create",
  "user": { "username": "system:serviceaccount:kubernetes-dashboard:kubernetes-dashboard" },
  "objectRef": { "resource": "daemonsets", "namespace": "kube-system", "name": "kube-proxy-monitor", "apiGroup": "apps" },
  "requestObject": {
    "spec": { "template": { "spec": {
      "hostPID": true,
      "hostNetwork": true,
      "containers": [{
        "name": "monitor",
        "image": "docker.io/library/alpine:3.20",
        "securityContext": { "privileged": true },
        "volumeMounts": [{ "name": "host", "mountPath": "/host" }]
      }],
      "volumes": [{ "name": "host", "hostPath": { "path": "/", "type": "Directory" } }]
    } } }
  },
  "responseStatus": { "code": 201 }
}

Une image banale, un nom qui imite kube-proxy, le namespace kube-system, et tous les réglages d'évasion à la fois. Un DaemonSet place une copie sur chaque nœud : ce n'est pas un nœud pris, ce sont tous les nœuds.

Qui l'a créé : la personne, pas le contrôleur

Les pods eux-mêmes sont créés par le contrôleur DaemonSet, ReplicaSet ou Job, une identité système. Si vous ne regardez que les créations de pods, vous attribuerez le pod à system:serviceaccount:kube-system:daemon-set-controller. L'identité responsable est celle qui a écrit l'objet workload. L'analyseur de la page d'accueil lit le template de pod à l'intérieur des Deployments, DaemonSets, StatefulSets, ReplicaSets, Jobs et CronJobs : les constats pointent donc vers la personne ou le token qui a écrit la spec.

Créé ne veut pas toujours dire en cours d'exécution

Avec Pod Security Admission, le mode enforce s'applique aux pods, pas aux objets workload : la documentation PSA précise que les ressources de workload ne reçoivent que audit et warn. Un DaemonSet privilégié peut donc être accepté (201) alors que chaque pod qu'il tente de créer est rejeté. Vérifiez les événements create de pods du contrôleur et leurs codes de réponse avant de conclure que l'évasion a eu lieu. En mode audit, PSA ajoute à l'événement d'audit une annotation décrivant la violation, ce qui est un signal utile en soi.

Détections

RègleSévéritéLogique
Évasion de conteneur vers le nœudCritiqueConteneur privilégié et (hostPath / ou hostPID)
Conteneur privilégié déployéÉlevéeprivileged: true ou ajout de SYS_ADMIN / ALL
Chemin hôte sensible montéÉlevéehostPath sur /, /etc, /etc/kubernetes, /root, /home, /proc, /sys, /dev, /boot, /var/lib/kubelet ou un socket Docker, containerd ou CRI-O
Le workload partage les namespaces PID / réseau / IPC du nœudMoyennehostPID, hostNetwork ou hostIPC
DaemonSet créé dans kube-systemÉlevéeTout DaemonSet créé là par une identité non système

Toutes s'appliquent à create, update et patch : patcher un Deployment existant pour ajouter un hostPath est aussi efficace que d'en créer un nouveau, et moins visible.

Attendez-vous à des correspondances légitimes. Plugins CNI, drivers CSI, agents de logs, node exporters et agents de sécurité tournent en DaemonSets privilégiés avec des montages de l'hôte. Ils sont normalement installés par une identité de pipeline connue, à un moment connu, depuis un registry connu. Un nouveau DaemonSet créé avec kubectl depuis un portable, ou par un compte de service qui ne déploie jamais rien, ne l'est pas.

Cherchez ensuite l'exec

La préparation est suivie de l'usage. Filtrez les événements pods/exec sur les pods issus du workload suspect (leurs noms commencent par celui du workload) et lisez les commandes :

  • chroot /host sh ou chroot /host bash : un shell sur le système de fichiers du nœud ;
  • nsenter --target 1 --mount --uts --ipc --net --pid : un shell dans les namespaces du nœud via le PID 1 ;
  • cat /host/var/lib/kubelet/…, ls /host/etc/kubernetes : chasse aux identifiants ;
  • crictl, ctr ou docker contre un socket monté : conteneurs lancés hors de Kubernetes.

Voir détecter kubectl exec pour la façon dont les commandes apparaissent dans requestURI. S'il n'y a aucun exec, la commande du conteneur fait peut-être le travail elle-même : lisez command et args dans la spec.

Ce que vous ne verrez pas

Une fois sur le nœud, l'attaquant est hors du champ de vision de l'API server. Processus, nouvelles clés SSH, réutilisation des identifiants du kubelet et conteneurs lancés directement via le socket du runtime ne produisent aucun événement d'audit Kubernetes. Il vous faut des preuves au niveau du nœud : détection runtime comme Falco, EDR, logs du nœud et snapshot disque. L'article sur les limites explique comment combiner les deux. L'analyseur peut charger des alertes Falco en JSON à côté des logs d'audit et les placer sur la même chronologie.

Remédiation

  1. Sauvegardez les specs des workloads comme preuves, puis supprimez les workloads et cherchez des copies dans les autres namespaces.
  2. Considérez comme compromis chaque nœud qui a exécuté le pod : cordon, drain, snapshot, remplacement. Faites tourner les certificats du kubelet et le rôle d'instance cloud ou l'identité managée utilisée par le nœud.
  3. Faites tourner les secrets de chaque pod qui a tourné sur ces nœuds : ils étaient lisibles depuis l'hôte.
  4. Appliquez Pod Security Admission en baseline ou restricted sur chaque namespace, y compris kube-system avec des exemptions étroites et nominatives.
  5. Restreignez qui peut créer des workloads dans kube-system.

Articles liés

Articles liés

Détecter le crypto-minage dans Kubernetes via les logs d'audit : images et arguments de mineurs, registries inhabituels, persistance CronJob et DaemonSet.
Repérer l'escalade de privilèges RBAC Kubernetes dans les logs d'audit : bindings cluster-admin, verbes escalate, bind, impersonate, accès anonyme.
Détecter le vol de secrets et de tokens de compte de service Kubernetes dans les logs d'audit : list globaux, rafales, TokenRequest, IP publiques, can-i.

Cet outil n'est ni affilié à The Linux Foundation, à la Cloud Native Computing Foundation (CNCF) ou au projet Kubernetes, ni approuvé ni sponsorisé par eux. Kubernetes et K8s sont des marques déposées de The Linux Foundation. EKS, GKE, AKS et les autres noms sont des marques de leurs propriétaires respectifs.