Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/percivalll/copy-fail-cve-2026-31431-kubernetes-poc
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónSeguridad en la NubePapers e InvestigaciónAprendizaje y EducaciónEscape de Contenedores
GitHubpercivalll/copy-fail-cve-2026-31431-kubernetes-poc

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

PoC: escape de contenedor completamente no privilegiado que permite la ejecución de código a nivel de nodo en Kubernetes mediante la corrupción de la caché de páginas de CVE-2026-31431 + capas de imagen compartidas. Validado en Alibaba Cloud ACK, Amazon EKS y Google GKE.

Ver Repositorio
18428hace 3 mesesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Copy Fail (CVE-2026-31431) — PoC de escape de contenedor en Kubernetes

Una prueba de concepto que demuestra cómo un contenedor completamente no privilegiado puede lograr ejecución de código a nivel de nodo en Kubernetes explotando el bug de corrupción de la caché de páginas del kernel Linux CVE-2026-31431 mediante capas de imagen de contenedor compartidas.

La primitiva de ataque central es: cualquier DaemonSet privilegiado que comparta capas de imagen con un contenedor controlado por el atacante puede ser utilizado como arma para el escape de contenedor. Este PoC usa kube-proxy como un ejemplo concreto, pero la técnica se generaliza a cualquier carga de trabajo privilegiada del clúster.

Validado en Alibaba Cloud ACK, Amazon EKS y Google GKE: un pod no privilegiado escribe [*] success en el sistema de archivos del host a través del DaemonSet privilegiado kube-proxy:

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

Aviso legal: Este repositorio se publica únicamente con fines educativos y defensivos. Úsalo exclusivamente en sistemas que poseas o para los que tengas autorización explícita de pruebas.

Antecedentes

CVE-2026-31431 («Copy Fail») es una vulnerabilidad del kernel Linux en la ruta de Copy-on-Write (CoW) de la caché de páginas. Una condición de carrera de splice en AF_ALG permite que un proceso no privilegiado corrompa las páginas de la caché de páginas de un archivo de solo lectura. La corrupción persiste en la caché de páginas del kernel y es visible para todos los procesos que posteriormente lean o ejecuten el archivo, incluidos los procesos de otros contenedores o del host.

Para obtener más detalles sobre la vulnerabilidad original, consulta copy.fail.

Principio del ataque

El ataque explota tres propiedades que suelen coexistir en los clústeres de Kubernetes:

  1. Corrupción de la caché de páginas del kernel (CVE-2026-31431) — un proceso no privilegiado puede sobrescribir las páginas cacheadas en memoria de cualquier archivo que pueda abrir en modo de solo lectura.
  2. Compartición de capas de imagen — los runtimes de contenedores (containerd, CRI-O) usan sistemas de archivos overlay donde las capas de imagen idénticas se asignan a las mismas páginas de la caché de páginas entre contenedores.
  3. DaemonSets privilegiados — muchos clústeres ejecutan DaemonSets con privilegios elevados (privileged: true, hostNetwork: true, capabilities amplias, etc.) que periódicamente ejecutan binarios de su imagen.

Cuando estas condiciones confluyen, un pod no privilegiado puede corromper un binario en una capa de imagen compartida, y un DaemonSet privilegiado en el mismo nodo ejecutará sin saberlo el binario corrupto con sus privilegios elevados, logrando una ejecución de código completa a nivel de nodo.

El objetivo de la vulnerabilidad NO se limita a kube-proxy. Cualquier DaemonSet privilegiado (agentes de monitoreo, plugins CNI, recopiladores de logs, agentes de seguridad, etc.) cuya imagen de contenedor comparta capas con una imagen controlada por el atacante es un objetivo viable.

Cómo funciona

La cadena de ataque consta de tres etapas: corrupción de la caché de páginas, propagación entre contenedores y ejecución privilegiada.

1. Corrupción de la caché de páginas mediante la condición de carrera de splice en AF_ALG

El subsistema AF_ALG (crypto) del kernel expone una interfaz basada en sockets para operaciones criptográficas en el espacio de usuario. El exploit abusa de una condición de carrera en la forma en que el kernel maneja splice() desde un archivo hacia un socket AF_ALG:

  1. Abre el binario objetivo en modo solo lectura.
  2. Crea un socket AF_ALG AEAD vinculado a authencesn(hmac(sha256),cbc(aes)).
  3. Envía un pequeño fragmento del payload a través del socket AF_ALG con MSG_MORE, indicando al kernel que espere más datos.
  4. Usa splice() para pasar el contenido del archivo objetivo desde un fd → pipe → socket AF_ALG.
  5. Debido al bug de CoW, el kernel escribe los bytes del payload del atacante en las páginas de la caché de páginas del archivo objetivo en lugar de aislarlas correctamente.

El exploit repite esto para cada ventana de 4 bytes hasta que todas las páginas cacheadas del binario objetivo quedan sobrescritas con un payload personalizado.

No se necesita permiso de escritura sobre el archivo. El archivo en disco no cambia; solo se corrompe la caché de páginas en memoria.

2. Propagación entre contenedores mediante la compartición de capas de imagen

Los runtimes de contenedores usan sistemas de archivos overlay. Cuando dos contenedores comparten la misma capa de imagen, el kernel atiende sus lecturas de archivos desde las mismas páginas de la caché de páginas.

El atacante construye su imagen PoC FROM la misma imagen base que el DaemonSet privilegiado objetivo. Debido a que ambos contenedores comparten el mismo lower-dir del overlay, los binarios de la capa compartida se asignan a páginas idénticas de la caché de páginas.

Cuando el contenedor PoC no privilegiado corrompe la caché de páginas de un binario, la corrupción es inmediatamente visible para el contenedor privilegiado del mismo nodo, sin ninguna comunicación entre contenedores.

3. Ejecución privilegiada por el DaemonSet objetivo

Cuando el DaemonSet privilegiado ejecuta a continuación cualquier binario corrupto (dentro de su ciclo normal de operación), el kernel carga las páginas corruptas de la caché de páginas. El payload del atacante se ejecuta con todos los privilegios del DaemonSet, lo que potencialmente incluye:

  • Root completo en el nodo
  • Todas las capabilities
  • Acceso a los namespaces del host (network, PID, mount)

El payload de este PoC (payload/payload.c) simplemente monta el sistema de archivos raíz del host y escribe un archivo marcador en /root/res como prueba de la ejecución de código a nivel de nodo.

Diagrama del flujo de ataque

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

Entornos de nube validados

El PoC se ha validado con éxito en las siguientes plataformas Kubernetes gestionadas:

Alibaba Cloud ACK

PropiedadValor
PlataformaAlibaba Cloud Container Service for Kubernetes (ACK)
Kubernetesv1.35.2
Kernel del nodo6.6.88-4.2.alnx4.x86_64
kube-proxyregistry-cn-*.ack.aliyuncs.com/acs/kube-proxy:v1.35.2-aliyun.1
Imagen baseregistry.k8s.io/kube-proxy:v1.35.2 (upstream)
Dispositivo raíz/dev/vda3 (ext4)

Resultado del PoC ACK

Amazon EKS

PropiedadValor
PlataformaAmazon Elastic Kubernetes Service (EKS)
Kubernetesv1.35.4
Kernel del nodo6.12.79-101.147.amzn2023.x86_64
kube-proxy***.dkr.ecr.***.amazonaws.com.cn/eks/kube-proxy:v1.35.3-eksbuild.2
Imagen basepublic.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-iptables:2026-03-11-1773190710.2023
Dispositivo raíz/dev/nvme0n1p1 (xfs)

Resultado del PoC EKS

Google GKE

PropiedadValor
PlataformaGoogle Kubernetes Engine (GKE)
Kubernetesv1.35.3-gke.1234000
SO del nodoContainer-Optimized OS (COS) 125, BUILD_ID 19216.220.72
Kernel del nodo6.12.68+ x86_64
kube-proxyus-central1-artifactregistry.gcr.io/gke-release/gke-release/kube-proxy:v1.35.3-gke.1234000
Imagen baseIgual que kube-proxy (imagen de Artifact Registry gestionada por el proveedor GKE)
Dispositivo raíz/dev/dm-0 (ext2, de solo lectura); /dev/sda1 (ext4, partición de estado escribible)
Ruta del marcador/mnt/stateful_partition/copyfail-res

Resultado del PoC GKE

En los tres casos, un pod PoC no privilegiado escribió correctamente el archivo marcador [*] success en el sistema de archivos del host, lo que demuestra la ejecución de código a nivel de nodo a través del DaemonSet privilegiado kube-proxy.

Para las guías completas (análisis de capas de imagen, pasos de compilación, despliegue):

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

kube-proxy como ejemplo concreto

Este PoC usa kube-proxy como objetivo porque es uno de los DaemonSets privilegiados más comunes en los clústeres de Kubernetes. Se proporcionan tres variantes:

  • Predeterminada (ACK / upstream): construida FROM registry.k8s.io/kube-proxy:v1.35.2 (ver Dockerfile)
  • EKS: construida FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-iptables:2026-03-11-1773190710.2023 (ver Dockerfile.eks)
  • GKE: construida FROM us-central1-artifactregistry.gcr.io/gke-release/gke-release/kube-proxy:v1.35.3-gke.1234000 (ver Dockerfile.gke)

Todas las variantes corrompen binarios como /usr/sbin/ipset, /usr/sbin/nft, /usr/sbin/xtables-legacy-multi y /usr/sbin/xtables-nft-multi.

Advertencias importantes:

  • kube-proxy solo invoca ipset cuando está configurado en modo ipvs. El modo predeterminado (iptables) no usa ipset. Consulta kubernetes/enhancements#5495 para conocer el plan de deprecación de ipvs.
  • Algunas distribuciones de Kubernetes gestionadas (p. ej., ciertos proveedores de nube) ejecutan kube-proxy como un contenedor no privilegiado, lo que limita el impacto del escape.
  • El PoC apunta a múltiples binarios (ipset, nft, xtables-legacy-multi, xtables-nft-multi) para cubrir diferentes modos de proxy, pero el que se invoquen o no depende de la configuración del clúster.

Si kube-proxy no es privilegiado en tu clúster, el principio del ataque sigue siendo válido: solo necesitas identificar otro DaemonSet privilegiado que comparta capas de imagen con una imagen base a partir de la cual puedas construir.

Generalización a otros objetivos

Para adaptar este PoC a otro DaemonSet privilegiado:

  1. Identifica un DaemonSet privilegiado que se ejecute en el clúster (agentes de monitoreo, plugins CNI, recopiladores de logs, etc.).
  2. Construye tu imagen PoC FROM la misma imagen base que usa ese DaemonSet.
  3. Identifica los binarios de la capa compartida que el DaemonSet ejecutará durante su funcionamiento normal.
  4. Corrompe la caché de páginas de esos binarios con el exploit.

Estructura del repositorio

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

Requisitos previos

  • Go 1.25+
  • Un compilador cruzado para el payload nolibc (predeterminado: x86_64-linux-gnu-gcc)
  • Docker / Buildx
  • Un clúster de Kubernetes con un DaemonSet privilegiado que comparta capas de imagen con la imagen del PoC (el ejemplo predeterminado apunta a kube-proxy)
  • imagePullPolicy: IfNotPresent en el DaemonSet objetivo (el valor predeterminado de Kubernetes)
  • Kernel Linux anterior al parche de CVE-2026-31431

Compilación

ACK / Kubernetes upstream

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

Para objetivos 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

Para nodos arm64:

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

Uso

Desplegar el 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

El Deployment crea un único pod no privilegiado. Este pod:

  1. Ejecuta /bin/copyfail para corromper la caché de páginas de los binarios objetivo en la capa de imagen compartida.
  2. Permanece en reposo (sleep) de forma indefinida para que el pod siga ejecutándose y pueda ser observado.

Verificar el escape

La próxima vez que el DaemonSet privilegiado objetivo ejecute un binario corrupto (en kube-proxy, esto suele ocurrir en cuestión de segundos debido a su bucle de reconciliación), verifica el nodo:

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 presencia del archivo marcador en el sistema de archivos del host demuestra que el código suministrado por el atacante se ejecutó con privilegios a nivel de nodo, desde el contexto del contenedor del DaemonSet privilegiado.

Limpieza

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>

Personalizar el payload

El payload predeterminado (payload/payload.c) es un programa únicamente de validación que escribe un archivo marcador. Para crear un payload personalizado:

  1. Edita payload/payload.c. El programa se compila contra nolibc (la biblioteca C mínima del kernel) para obtener un binario estático y sin dependencias.
  2. Ejecuta make payload para compilar de forma cruzada.
  3. El payload compilado se incrusta en el binario Go mediante //go:embed.

Versiones afectadas

  • Kernel Linux: todas las versiones anteriores al parche de CVE-2026-31431.
  • Kubernetes: cualquier versión que use un kernel de nodo sin parchear. La vulnerabilidad está en el kernel, no en Kubernetes en sí. Kubernetes solo proporciona el contexto de ejecución (capas de imagen compartidas + DaemonSets privilegiados) que eleva el impacto de una corrupción local de la caché de páginas a un escape completo de contenedor.

Mitigación

  • Parchea el kernel. Este es el arreglo definitivo.
  • Habilita el aislamiento de capas de imagen. Algunos runtimes admiten instantáneas de sistema de archivos por contenedor que impiden la compartición de la caché de páginas.
  • Minimiza los DaemonSets privilegiados. Reduce la cantidad de cargas de trabajo que se ejecutan con privilegios elevados; utiliza el principio de mínimo privilegio.
  • Elimina las capabilities innecesarias de los DaemonSets que no requieran estrictamente privileged: true.
  • Restringe la programación de pods para evitar que las cargas de trabajo no confiables terminen en nodos que ejecutan DaemonSets privilegiados con imágenes base compartidas.
  • Usa imágenes base distintas para las cargas de trabajo privilegiadas y reduce así la probabilidad de compartir capas con contenedores no confiables.

Ejemplos de mitigación

  • Regla de mitigación integrada en vArmor: copy-fail-mitigation bloquea el vector de explotación al impedir que los contenedores creen sockets AF_ALG. La regla está disponible a través de los enforcers de AppArmor y BPF.
  • Mitigación eBPF para Kubernetes: iwanhae/copyfail-ebpf-k8s proporciona un ejemplo de mitigación para Kubernetes basado en eBPF para CVE-2026-31431.

Créditos

  • Descubrimiento y divulgación de CVE-2026-31431: Theori / Xint
  • Payload C multiplataforma: Tony Gies (LGPL-2.1-or-later OR MIT)
  • nolibc: selftests del kernel Linux (tools/include/nolibc/)

Licencia

El código del exploit en Go de este repositorio se proporciona tal cual, con fines de investigación.

El payload (payload/payload.c) se deriva de copy-fail-c y tiene doble licencia: LGPL-2.1-or-later O MIT. Consulta LICENSE-LGPL y LICENSE-MIT.

Descargar herramienta