
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.
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) |
|---|---|---|
![]() | ![]() | ![]() |
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.
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.
El ataque explota tres propiedades que suelen coexistir en los clústeres de Kubernetes:
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.
La cadena de ataque consta de tres etapas: corrupción de la caché de páginas, propagación entre contenedores y ejecución privilegiada.
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:
authencesn(hmac(sha256),cbc(aes)).MSG_MORE, indicando al kernel que espere más datos.splice() para pasar el contenido del archivo objetivo desde un fd → pipe → socket AF_ALG.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.
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.
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:
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.
┌──────────────────────────┐ ┌──────────────────────────┐
│ 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
El PoC se ha validado con éxito en las siguientes plataformas Kubernetes gestionadas: