Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Copy-Fail-CVE-2026-31431-Kubernetes-PoC — PoC : évasion de conteneur totalement non privilégiée vers l'exécution de code au niveau du nœud sur Kubernetes via la corruption du page-cache CVE-2026-31431 + couches d'images partagées. Validé sur Alibaba Cloud ACK, Amazon EKS et Google GKE. | Kitploit
Outils/GitHubGitHub/percivalll/copy-fail-cve-2026-31431-kubernetes-poc
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationSécurité CloudArticles et RechercheApprentissage et ÉducationÉvasion de Conteneur
GitHubpercivalll/copy-fail-cve-2026-31431-kubernetes-poc

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Copy-Fail-CVE-2026-31431-Kubernetes-PoC

PoC : évasion de conteneur totalement non privilégiée vers l'exécution de code au niveau du nœud sur Kubernetes via la corruption du page-cache CVE-2026-31431 + couches d'images partagées. Validé sur Alibaba Cloud ACK, Amazon EKS et Google GKE.

Voir le dépôt
18428il y a 3 moisVérifié par Kitploit

Copy Fail (CVE-2026-31431) — PoC d'évasion de conteneur Kubernetes

Une preuve de concept démontrant comment un conteneur totalement non privilégié peut obtenir l'exécution de code au niveau du nœud sur Kubernetes en exploitant la vulnérabilité CVE-2026-31431 du noyau Linux (corruption du cache de pages) via des couches d'images conteneur partagées.

La primitive d'attaque de base est la suivante : tout DaemonSet privilégié partageant des couches d'images avec un conteneur contrôlé par l'attaquant peut être utilisé comme arme pour une évasion de conteneur. Ce PoC utilise kube-proxy comme exemple concret, mais la technique se généralise à toute charge de travail privilégiée du cluster.

Validé sur Alibaba Cloud ACK, Amazon EKS et Google GKE — un pod non privilégié écrit [*] success sur le système de fichiers de l'hôte via le DaemonSet privilégié kube-proxy :

Alibaba Cloud ACK (noyau 6.6.88)Amazon EKS (noyau 6.12.79)Google GKE (noyau 6.12.68)
ACKEKSGKE

Avertissement : Ce dépôt est publié à des fins exclusivement éducatives et défensives. Utilisez-le exclusivement sur des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation explicite de test.

Contexte

CVE-2026-31431 (« Copy Fail ») est une vulnérabilité du noyau Linux dans le chemin Copy-on-Write (CoW) du cache de pages. Une condition de course splice AF_ALG permet à un processus non privilégié de corrompre les pages du cache de pages d'un fichier en lecture seule. La corruption persiste dans le cache de pages du noyau et est visible par tout processus qui lit ou exécute ensuite le fichier — y compris les processus d'autres conteneurs ou de l'hôte.

Pour tous les détails sur la vulnérabilité d'origine, voir copy.fail.

Principe de l'attaque

L'attaque exploite trois propriétés qui coexistent couramment dans les clusters Kubernetes :

  1. Corruption du cache de pages du noyau (CVE-2026-31431) — un processus non privilégié peut écraser les pages en cache en mémoire de tout fichier qu'il peut ouvrir en lecture seule.
  2. Partage des couches d'images — les runtimes de conteneurs (containerd, CRI-O) utilisent des systèmes de fichiers overlay dans lesquels des couches d'images identiques correspondent aux mêmes pages du cache de pages entre les conteneurs.
  3. DaemonSets privilégiés — de nombreux clusters exécutent des DaemonSets avec des privilèges élevés (privileged: true, hostNetwork: true, des capacités étendues, etc.) qui exécutent périodiquement des binaires de leur image.

Lorsque ces conditions sont réunies, un pod non privilégié peut corrompre un binaire dans une couche d'image partagée, et un DaemonSet privilégié sur le même nœud exécutera sans le savoir le binaire corrompu avec ses privilèges élevés — aboutissant à une exécution complète de code au niveau du nœud.

La cible de la vulnérabilité n'est PAS limitée à kube-proxy. Tout DaemonSet privilégié (agents de surveillance, plugins CNI, collecteurs de journaux, agents de sécurité, etc.) dont l'image conteneur partage des couches avec une image contrôlée par l'attaquant est une cible viable.

Comment ça fonctionne

La chaîne d'attaque comporte trois étapes : corruption du cache de pages, propagation entre conteneurs et exécution privilégiée.

1. Corruption du cache de pages via la course AF_ALG splice

Le sous-système AF_ALG (crypto) du noyau expose une interface basée sur des sockets pour les opérations cryptographiques de l'espace utilisateur. L'exploit abuse d'une condition de course dans la façon dont le noyau gère splice() d'un fichier vers une socket AF_ALG :

  1. Ouvrir le binaire cible en lecture seule.
  2. Créer une socket AF_ALG AEAD liée à authencesn(hmac(sha256),cbc(aes)).
  3. Envoyer un petit fragment de payload à travers la socket AF_ALG avec MSG_MORE, indiquant au noyau d'attendre plus de données.
  4. splice() le contenu du fichier cible d'un fd → pipe → socket AF_ALG.
  5. En raison du bug CoW, le noyau écrit les octets du payload de l'attaquant dans les pages du cache de pages du fichier cible au lieu de les isoler correctement.

L'exploit répète cette opération pour chaque fenêtre de 4 octets jusqu'à ce que toutes les pages en cache du binaire cible soient écrasées par un payload personnalisé.

Aucune permission d'écriture sur le fichier n'est nécessaire. Le fichier sur disque reste inchangé — seul le cache de pages en mémoire est corrompu.

2. Propagation entre conteneurs via le partage des couches d'images

Les runtimes de conteneurs utilisent des systèmes de fichiers overlay. Lorsque deux conteneurs partagent la même couche d'image, le noyau sert leurs lectures de fichiers à partir des mêmes pages du cache de pages.

L'attaquant construit son image PoC FROM la même image de base que le DaemonSet privilégié ciblé. Comme les deux conteneurs partagent le même lowerdir overlay, les binaires de la couche partagée correspondent à des pages du cache de pages identiques.

Lorsque le conteneur PoC non privilégié corrompt le cache de pages d'un binaire, la corruption est immédiatement visible pour le conteneur privilégié sur le même nœud — sans aucune communication entre conteneurs.

3. Exécution privilégiée par le DaemonSet cible

Lorsque le DaemonSet privilégié exécute ensuite un binaire corrompu (au cours de son cycle de fonctionnement normal), le noyau charge les pages corrompues du cache de pages. Le payload de l'attaquant s'exécute avec tous les privilèges du DaemonSet — pouvant inclure :

  • Root complet sur le nœud
  • Toutes les capacités
  • Accès aux namespaces de l'hôte (réseau, PID, montage)

Le payload de ce PoC (payload/payload.c) monte simplement le système de fichiers racine de l'hôte et écrit un fichier marqueur dans /root/res comme preuve de l'exécution de code au niveau du nœud.

Schéma du flux d'attaque

root@kitploit:~
┌──────────────────────────┐     ┌──────────────────────────┐
│   PoC Container          │     │   Privileged DaemonSet   │
│   (unprivileged)         │     │   (e.g. kube-proxy,      │
│                          │     │    monitoring agent, etc.)│
│  1. Open target binary   │     │                          │
│     (read-only)          │     │                          │
│                          │     │                          │
│  2. AF_ALG splice race   │     │                          │
│     corrupts page cache  │     │                          │
│          │               │     │                          │
└──────────┼───────────────┘     └──────────────────────────┘
           │                                  │
           ▼                                  │
  ┌─────────────────────┐                     │
  │  Kernel Page Cache   │                     │
  │                      │◄────────────────────┘
  │  Shared-layer binary │     3. DaemonSet executes the
  │  (CORRUPTED)         │        corrupted binary
  │  contains attacker's │        → loads corrupted pages
  │  payload bytes       │        → payload runs with
  └─────────────────────┘           DaemonSet's privileges

Environnements cloud validés

Le PoC a été validé avec succès sur les plateformes Kubernetes gérées suivantes :

Alibaba Cloud ACK

Résultat du PoC ACK

Amazon EKS

Résultat du PoC EKS

Google GKE

Résultat du PoC GKE

Dans les trois cas, un pod PoC non privilégié a écrit avec succès le fichier marqueur [*] success sur le système de fichiers de l'hôte — prouvant l'exécution de code au niveau du nœud via le DaemonSet privilégié kube-proxy.

Pour les procédures pas à pas complètes (analyse des couches d'images, étapes de compilation, déploiement) :

  • EKS : docs/eks-poc.md
  • GKE : docs/gke-poc.md

kube-proxy comme exemple concret

Ce PoC utilise kube-proxy comme cible car c'est l'un des DaemonSets privilégiés les plus courants dans les clusters Kubernetes. Trois variantes sont fournies :

  • Par défaut (ACK / amont) : construit FROM registry.k8s.io/kube-proxy:v1.35.2 (voir Dockerfile)
  • EKS : construit FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-iptables:2026-03-11-1773190710.2023 (voir Dockerfile.eks)
  • GKE : construit FROM us-central1-artifactregistry.gcr.io/gke-release/gke-release/kube-proxy:v1.35.3-gke.1234000 (voir Dockerfile.gke)

Toutes les variantes corrompent des binaires comme /usr/sbin/ipset, /usr/sbin/nft, /usr/sbin/xtables-legacy-multi et /usr/sbin/xtables-nft-multi.

Points d'attention importants :

  • kube-proxy n'invoque ipset que lorsqu'il est configuré en mode ipvs. Le mode par défaut (iptables) n'utilise pas ipset. Voir kubernetes/enhancements#5495 pour le plan de dépréciation d'ipvs.
  • Certaines distributions Kubernetes gérées (par exemple certains fournisseurs de cloud) exécutent kube-proxy en tant que conteneur non privilégié, ce qui limite l'impact de l'évasion.
  • Le PoC cible plusieurs binaires (ipset, nft, xtables-legacy-multi, xtables-nft-multi) pour couvrir différents modes de proxy, mais la question de savoir s'ils sont invoqués dépend de la configuration du cluster.

Si kube-proxy n'est pas privilégié dans votre cluster, le principe de l'attaque reste valable — il vous suffit d'identifier un autre DaemonSet privilégié qui partage des couches d'images avec une image de base à partir de laquelle vous pouvez construire.

Généralisation à d'autres cibles

Pour adapter ce PoC à un autre DaemonSet privilégié :

  1. Identifiez un DaemonSet privilégié s'exécutant sur le cluster (agents de surveillance, plugins CNI, collecteurs de journaux, etc.).
  2. Construisez votre image PoC FROM la même image de base que celle utilisée par ce DaemonSet.
  3. Identifiez les binaires de la couche partagée que le DaemonSet exécutera pendant son fonctionnement normal.
  4. Corrompez le cache de pages de ces binaires à l'aide de l'exploit.

Structure du dépôt

root@kitploit:~
.
├── cmd/copyfail/main.go          # Entry point; embeds compiled payload
├── internal/
│   ├── exploit/
│   │   ├── exploit.go            # Core exploit: AF_ALG splice race loop
│   │   └── patch.go              # Splits payload into 4-byte patch windows
│   └── alg/
│       └── alg.go                # AF_ALG AEAD socket abstraction
├── payload/
│   ├── payload.c                 # ACK/upstream payload (mount /dev/vda3 ext4)
│   ├── payload-eks.c             # EKS payload (NVMe/Xen device auto-detection)
│   ├── payload-gke.c             # GKE payload (COS/Ubuntu device auto-detection)
│   └── nolibc/                   # Kernel's tiny libc for static, no-dependency payloads
├── deploy/
│   ├── poc.yaml                  # Kubernetes Deployment manifest (ACK/upstream)
│   ├── poc-eks.yaml              # EKS Deployment manifest
│   └── poc-gke.yaml              # GKE Deployment manifest
├── Dockerfile                    # ACK/upstream: FROM registry.k8s.io/kube-proxy
├── Dockerfile.eks                # EKS: FROM eks-distro-minimal-base-iptables
├── Dockerfile.gke                # GKE: FROM gke-release/kube-proxy
├── Makefile                      # Build orchestration (includes *-eks and *-gke targets)
└── docs/
    ├── eks-poc.md                # EKS PoC full walkthrough
    ├── gke-poc.md                # GKE PoC full walkthrough
    ├── ack-poc-res.png           # ACK validation screenshot
    ├── eks-poc-res.png           # EKS validation screenshot
    └── gke-poc-res.png           # GKE validation screenshot

Prérequis

  • Go 1.25+
  • Un compilateur croisé pour le payload nolibc (par défaut : x86_64-linux-gnu-gcc)
  • Docker / Buildx
  • Un cluster Kubernetes avec un DaemonSet privilégié qui partage des couches d'images avec l'image PoC (l'exemple par défaut cible kube-proxy)
  • imagePullPolicy: IfNotPresent sur le DaemonSet cible (la valeur par défaut de Kubernetes)
  • Noyau Linux antérieur au correctif de CVE-2026-31431

Compilation

ACK / Kubernetes amont

root@kitploit:~
# Build payload + Go binary
make build

# Build Docker image
make docker-build

# Build and push to GHCR
make docker-push IMAGE=ghcr.io/<you>/copy-fail-poc TAG=latest

Amazon EKS

root@kitploit:~
# Build EKS payload + Go binary + Docker image
make docker-build-eks

# Build and push to GHCR
make docker-push-eks IMAGE=ghcr.io/<you>/copy-fail-poc

Pour les cibles arm64 (Graviton) :

root@kitploit:~
make build-eks CC=aarch64-linux-gnu-gcc GOARCH=arm64

Google GKE

root@kitploit:~
# Build GKE payload + Go binary + Docker image
make docker-build-gke

# Build and push to GHCR
make docker-push-gke IMAGE=ghcr.io/<you>/copy-fail-poc

Pour les nœuds arm64 :

root@kitploit:~
make docker-build-gke CC=aarch64-linux-gnu-gcc GOARCH=arm64 PLATFORM=linux/arm64

Utilisation

Déployer le PoC

root@kitploit:~
# ACK / upstream Kubernetes
kubectl apply -f deploy/poc.yaml

# Amazon EKS
kubectl apply -f deploy/poc-eks.yaml

# Google GKE
kubectl apply -f deploy/poc-gke.yaml

Le Deployment crée un seul pod non privilégié. Il :

  1. Exécute /bin/copyfail pour corrompre le cache de pages des binaires cibles dans la couche d'image partagée.
  2. Reste en veille indéfiniment afin que le pod reste actif pour observation.

Vérifier l'évasion

Une fois que le DaemonSet privilégié cible a exécuté un binaire corrompu (pour kube-proxy, cela se produit généralement en quelques secondes grâce à sa boucle de réconciliation), vérifiez le nœud :

root@kitploit:~
# SSH into the node, or use a privileged debug pod

# ACK / EKS (writable root filesystem)
cat /root/res
# Expected output: [*] success

# GKE COS nodes (read-only root, writable stateful partition)
cat /mnt/stateful_partition/copyfail-res
# Expected output: [*] success

La présence du fichier marqueur sur le système de fichiers de l'hôte prouve que le code fourni par l'attaquant s'est exécuté avec des privilèges au niveau du nœud — depuis le contexte du conteneur du DaemonSet privilégié.

Nettoyage

root@kitploit:~
kubectl delete -f deploy/poc.yaml      # or poc-eks.yaml / poc-gke.yaml

# On the affected node(s), remove the marker and restart the target DaemonSet:
rm -f /root/res                                     # ACK / EKS
rm -f /copyfail-res /mnt/stateful_partition/copyfail-res  # GKE COS nodes
# For kube-proxy: delete the pod to force image layer re-read
kubectl delete pod -n kube-system -l k8s-app=kube-proxy --field-selector spec.nodeName=<node>

Personnalisation du payload

Le payload par défaut (payload/payload.c) est un programme de validation uniquement qui écrit un fichier marqueur. Pour construire un payload personnalisé :

  1. Modifiez payload/payload.c. Le programme est compilé avec nolibc (la bibliothèque C minimale du noyau) pour produire un binaire statique sans dépendances.
  2. Exécutez make payload pour compiler en croisé.
  3. Le payload compilé est intégré dans le binaire Go via //go:embed.

Versions concernées

  • Noyau Linux : toutes les versions antérieures au correctif de CVE-2026-31431.
  • Kubernetes : toute version utilisant un noyau de nœud non corrigé. La vulnérabilité se trouve dans le noyau, pas dans Kubernetes lui-même. Kubernetes fournit simplement le contexte d'exécution (couches d'images partagées + DaemonSets privilégiés) qui fait passer l'impact d'une corruption locale du cache de pages à une évasion complète de conteneur.

Atténuation

  • Corriger le noyau. C'est le correctif définitif.
  • Activer l'isolation des couches d'images. Certains runtimes prennent en charge des instantanés du système de fichiers par conteneur qui empêchent le partage du cache de pages.
  • Minimiser les DaemonSets privilégiés. Réduire le nombre de charges de travail s'exécutant avec des privilèges élevés ; appliquer le principe du moindre privilège.
  • Supprimer les capacités inutiles des DaemonSets qui n'exigent pas strictement privileged: true.
  • Restreindre l'ordonnancement des pods pour empêcher les charges de travail non fiables d'atterrir sur des nœuds exécutant des DaemonSets privilégiés avec des images de base partagées.
  • Utiliser des images de base distinctes pour les charges de travail privilégiées afin de réduire les risques de partage de couches avec des conteneurs non fiables.

Exemples d'atténuation

  • Règle d'atténuation intégrée à vArmor : copy-fail-mitigation bloque le vecteur d'exploitation en empêchant les conteneurs de créer des sockets AF_ALG. La règle est disponible via les mécanismes d'application AppArmor et BPF.
  • Atténuation Kubernetes par eBPF : iwanhae/copyfail-ebpf-k8s fournit un exemple d'atténuation Kubernetes basée sur eBPF pour CVE-2026-31431.

Crédits

  • Découverte et divulgation de CVE-2026-31431 : Theori / Xint
  • Payload C multiplateforme : Tony Gies (LGPL-2.1-or-later OU MIT)
  • nolibc : selftests du noyau Linux (tools/include/nolibc/)

Licence

Le code d'exploitation Go de ce dépôt est fourni tel quel à des fins de recherche.

Le payload (payload/payload.c) est dérivé de copy-fail-c et est sous double licence LGPL-2.1-or-later OU MIT. Voir LICENSE-LGPL et LICENSE-MIT.

Télécharger l’outil
PropriétéValeur
PlateformeAlibaba Cloud Container Service for Kubernetes (ACK)
Kubernetesv1.35.2
Noyau du nœud6.6.88-4.2.alnx4.x86_64
kube-proxyregistry-cn-*.ack.aliyuncs.com/acs/kube-proxy:v1.35.2-aliyun.1
Image de baseregistry.k8s.io/kube-proxy:v1.35.2 (amont)
Périphérique racine/dev/vda3 (ext4)
PropriétéValeur
PlateformeAmazon Elastic Kubernetes Service (EKS)
Kubernetesv1.35.4
Noyau du nœud6.12.79-101.147.amzn2023.x86_64
kube-proxy***.dkr.ecr.***.amazonaws.com.cn/eks/kube-proxy:v1.35.3-eksbuild.2
Image de basepublic.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-iptables:2026-03-11-1773190710.2023
Périphérique racine/dev/nvme0n1p1 (xfs)
PropriétéValeur
PlateformeGoogle Kubernetes Engine (GKE)
Kubernetesv1.35.3-gke.1234000
OS du nœudContainer-Optimized OS (COS) 125, BUILD_ID 19216.220.72
Noyau du nœud6.12.68+ x86_64
kube-proxyus-central1-artifactregistry.gcr.io/gke-release/gke-release/kube-proxy:v1.35.3-gke.1234000
Image de baseIdentique à kube-proxy (image Artifact Registry gérée par le fournisseur GKE)
Périphérique racine/dev/dm-0 (ext2, lecture seule) ; /dev/sda1 (ext4, partition avec état inscriptible)
Chemin du marqueur/mnt/stateful_partition/copyfail-res