Copy Fail – CVE-2026-31431
(copy.fail)- Un usuario local sin privilegios puede encadenar
authencesn,AF_ALGysplice()para lograr una escritura de 4 bytes en la page cache de un archivo legible, y con eso escalar hasta privilegios de root - Funciona tal cual en múltiples distribuciones Linux con un único script de Python de 732 bytes, sin offsets por kernel ni condiciones de carrera, y el mismo exploit permite obtener una root shell
- El alcance incluye a la mayoría de las principales distribuciones Linux con kernels sin parchear, y la exposición ha sido amplia desde 2017 hasta el momento del parche debido a que
AF_ALGviene habilitado por defecto - En hosts multitenant, clústeres de Kubernetes / contenedores, runners de CI y Cloud SaaS que ejecutan código de usuario, una cuenta normal o un solo pod puede terminar convirtiéndose en root del host, por lo que el parcheo debe ser prioritario
- La respuesta principal es aplicar un parche del kernel que incluya el commit mainline
a664bf3d603d; antes de eso, es importante desactivaralgif_aeady bloquearAF_ALGpara cargas de trabajo no confiables
Resumen de la vulnerabilidad
- Un solo fallo lógico lineal puede encadenarse con
authencesn,AF_ALGysplice()para terminar en una escritura de 4 bytes en la page cache, permitiendo una escalada local de privilegios - Funciona de forma idéntica en distribuciones Linux publicadas desde 2017 con un único script de Python de 732 bytes, sin ventanas de carrera ni offsets específicos por kernel
- El mismo binario de exploit obtiene una root shell en varias distribuciones sin modificaciones
- Solo se necesita una cuenta local sin privilegios; no hace falta acceso de red, funciones de depuración del kernel ni primitivas adicionales preinstaladas
Alcance del impacto
- La mayoría de las principales distribuciones Linux que usan kernels sin parchear entran en el rango afectado
- En la configuración por defecto,
AF_ALGde la API criptográfica del kernel está habilitado en prácticamente todas las distribuciones mainstream, dejando exposición directa desde 2017 hasta el parche - Las distribuciones verificadas directamente fueron Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 14.3 y SUSE 16
- Debian, Arch, Fedora, Rocky, Alma, Oracle y sistemas embebidos también se ven afectados si usan un kernel vulnerable
Entornos que necesitan parche prioritario
- En hosts Linux multitenant, varios usuarios comparten el mismo kernel, así que una cuenta arbitraria puede convertirse directamente en root
- En clústeres de Kubernetes / contenedores, la page cache se comparte a nivel de todo el host, por lo que un solo pod puede tomar control del nodo y cruzar límites entre tenants
- En runners de CI y granjas de build, código no confiable de un PR ejecutado con permisos normales puede volverse root en el runner
- En Cloud SaaS que ejecuta código de usuario, un contenedor o script subido por un tenant puede terminar en root del host
- Los servidores de un solo tenant tienen más bien un perfil de LPE interna y pueden combinarse con RCE web o credenciales comprometidas
- En laptops y workstations de un solo usuario la urgencia es menor, pero la ejecución local de código puede convertirse de inmediato en elevación a root
PoC publicada y forma de uso
- La PoC se publicó para que los equipos defensivos puedan validar sistemas y confirmar parches de proveedores
copy_fail_exp.pyusa únicamente las bibliotecas estándar de Python 3.10+os,socketyzlib- El objetivo por defecto es
/usr/bin/suy se puede pasar otro binario setuid enargv[1] - Modifica el binario setuid dentro de la page cache; el cambio no sobrevive a un reinicio, pero la root shell obtenida sí funciona realmente
- Issue tracker
Mitigación
- Lo primero es aplicar un parche del kernel y actualizar a un kernel de la distribución que incluya el commit mainline
a664bf3d603d - Ese parche revierte la optimización in-place de
algif_aeadintroducida en 2017 para evitar que páginas de la page cache entren en una scatterlist de destino escribible - Antes del parche, se recomienda desactivar el módulo
algif_aeadecho "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.confrmmod algif_aead 2>/dev/null || true
- En contenedores, sandboxes y CI que ejecutan cargas no confiables, incluso si ya están parcheados, hace falta bloquear la creación de sockets
AF_ALGcon seccomp
Impacto de desactivarlo
- En la mayoría de los sistemas, casi no hay impacto medible
dm-crypt / LUKS,kTLS,IPsec/XFRM, TLS dentro del kernel, builds por defecto de OpenSSL/GnuTLS/NSS, SSH y la criptografía del keyring del kernel no se ven afectados- Estos usan directamente la API criptográfica del kernel y no pasan por la ruta
AF_ALG
- Estos usan directamente la API criptográfica del kernel y no pasan por la ruta
- Si en OpenSSL se habilitó explícitamente el motor
afalg, algunas rutas de offload criptográfico embebido y aplicaciones que hagan bind directo a socketsaead/skcipher/hashsí pueden verse afectadas- Puede verificarse con
lsof | grep AF_ALGoss -xa
- Puede verificarse con
- Aunque se desactive
AF_ALG, los objetivos que nunca lo usaron no se vuelven más lentos, y los que sí lo usaban vuelven a bibliotecas criptográficas normales en userspace
Qué lo diferencia de un LPE típico en Linux
- A diferencia de un LPE común en Linux, no tiene condición de carrera ni requiere offsets por distribución
- También se presenta con una confiabilidad de 100% en un solo intento, y cubre un período largo de 2017 a 2026 en lugar de una franja estrecha de versiones
- Con apenas 732 bytes y usando solo la biblioteca estándar de Python, no necesita payload compilado ni dependencias extra
- La ruta de escritura evade el VFS y la página corrompida no se marca como dirty, así que nada se escribe en disco
- Como la page cache se comparte en todo el host, funciona no solo como un LPE simple sino también como una primitiva de escape de contenedor
Principio de funcionamiento y características de detección
- Un usuario local sin privilegios puede escribir 4 bytes controlables en la page cache de archivos legibles de un sistema Linux y usar eso para obtener root
- El objetivo no es el archivo real en disco sino la page cache en memoria; si se modifica la copia cacheada de
/usr/bin/su, desde la perspectiva deexecvees como cambiar el binario mismo - Como no hay cambios en disco, inotify no se activa, y tras reiniciar o expulsar la caché vuelve a cargarse el archivo original
- Herramientas de hash comunes como
sha256sum, AIDE y Tripwire leen la page cache medianteread(), así que mientras la corrupción siga en caché pueden diferir del hash de referencia - Cuando la caché se expulsa o el sistema reinicia, el hash vuelve a coincidir con el original, y en una imagen forense de disco solo queda el archivo sin modificar
- En IMA appraisal enforcing mode, si está habilitada la medición en cada lectura, el binario corrompido puede detectarse en el momento de
execveantes de ejecutarse
Diferencias frente a otras vulnerabilidades
- Pertenece a la misma familia que Dirty Pipe, en el sentido de que corrompe la page cache desde userspace sin privilegios y permite escribir sobre binarios setuid sin cambios en disco para obtener root
- El mecanismo es distinto: Dirty Pipe abusaba de pipe buffer flags, mientras que Copy Fail abusa de una AEAD scratch write que cruza límites de scatterlist encadenadas
- Dirty Pipe requería kernels 5.8 o superiores con cierto parche, pero Copy Fail cubre la ventana de 2017 a 2026
- A diferencia de Dirty Cow, no hace falta ganar una carrera COW basada en TOCTOU ni intentarlo varias veces ni desestabilizar el sistema
Detalles adicionales
/usr/bin/suno es obligatorio; cualquier binario setuid-root legible por el usuario puede servir, comopasswd,chsh,chfn,mount,sudoopkexec- No es una vulnerabilidad remota; primero se necesita ejecución local de código con privilegios de usuario normal
- Si un RCE web cae sobre una cuenta de servicio sin privilegios, o se combina con un acceso SSH inicial o un PR malicioso en un runner de CI, puede terminar en root
- El parche revierte la optimización in-place de
algif_aeadpara volver a separarreq->srcyreq->dsten scatterlists distintas - Las páginas de la page cache quedan solo en la fuente de solo lectura, y el único destino escribible para la operación criptográfica pasa a ser el buffer de usuario
Cronología pública y materiales de seguimiento
- Reportada al equipo de seguridad del kernel Linux el 2026-03-23
- Confirmación inicial el 2026-03-24
- Parche propuesto y revisado el 2026-03-25
- Parche integrado al mainline el 2026-04-01
- Asignación de CVE-2026-31431 el 2026-04-22
- Divulgación pública el 2026-04-29 en https://copy.fail/
- Análisis técnico en el blog de Xint
- Incluye root cause, diagramas de scatterlist, cronología 2011→2015→2017 y walkthrough del exploit
- La Parte 2, centrada en escape de contenedores en Kubernetes, se publicará más adelante
Información relacionada con Xint Code
- Fue encontrado de forma asistida por IA; el punto de partida fue una investigación humana sobre cómo
splice()entrega páginas de la page cache al subsistema crypto y sobre la posibilidad de que el origen de páginas en scatterlist fuera una clase de bugs poco explorada - Después, Xint Code amplió esa auditoría a todo el subsistema
crypto/de Linux en alrededor de una hora, y el hallazgo más severo de ese resultado fue Copy Fail - Xint Code
- Write-up del blog de Xint
- En el mismo escaneo también se encontraron otros bugs de alto riesgo, que siguen bajo coordinated disclosure
1 comentarios
Opiniones de Hacker News
Desde la perspectiva de alguien que trabaja con el código crypto del kernel de Linux, los exploits de AF_ALG que aparecen periódicamente son realmente frustrantes
AF_ALG entró al kernel hace mucho tiempo sin suficiente revisión, su estructura es demasiado compleja y además abre una enorme superficie de ataque a programas de userspace sin privilegios
Encima, es casi innecesario. En userspace ya existe su propio código criptográfico, y el código crypto del kernel originalmente era para usos internos del kernel como dm-crypt
Incluso authencesn en este exploit es en esencia un detalle de implementación interno de IPsec, así que exponerlo como una API genérica de cifrado/descifrado para userspace me parece que fue un error desde el principio
Si administras la configuración del kernel de Linux, recomiendo fuertemente desactivar todas las opciones CONFIG_CRYPTO_USER_API_*
Solo con eso, este bug y una buena parte de los bugs pasados y futuros de AF_ALG no habrían sido explotables
Si algún programa de userspace se rompe, lo correcto sería ayudar a migrarlo a código crypto de userspace, y de hecho ya hubo casos que cambiaron así
Desde el principio, AF_ALG no parecía tener mucha utilidad más allá de los exploits
Tal vez antes este tipo de API para userspace era más o menos tolerable, pero con syzbot o la detección de bugs asistida por LLM que existe hoy, ya es difícil seguir sosteniéndolo
Se plantea que permite usar desde userspace aceleradores de hardware accesibles solo en modo kernel, que deja pasar claves al kernel sin mantenerlas mucho tiempo en la memoria de la aplicación, y que en entornos con memoria limitada, como sistemas embebidos, puede reducir la huella frente a una librería crypto de userspace
No sé si eso sea una justificación suficientemente buena, pero al menos sí hay una razón
Linus es conocido por ser bastante exigente con lo que acepta en el kernel, así que la historia detrás de una API así debe ser interesante
Permite manejar hashes y cifrado mediante llamadas normales a
read(2)/write(2)Parece que hubo algo de confusión en el proceso de divulgación
Los vendors no están tratando esta vulnerabilidad como algo grave, y por eso varias distribuciones siguen sin parchearla
En https://access.redhat.com/security/cve/cve-2026-31431 aparecía como "Moderate severity" y "Fix deferred", y las páginas de seguimiento de Debian, Ubuntu y SUSE se veían parecidas
Pero upstream no comunicó claramente que esto fuera una vulnerabilidad, y Linus y Greg tampoco suelen darle demasiado peso conceptual a esa clasificación dentro del kernel
Aun así, como permite escalación local a root, en general suena correcto tratarlo como de alta prioridad
https://ubuntu.com/security/cves/about#priority
Es una lástima que en el texto principal no se indique enseguida qué versiones del kernel son vulnerables y en cuáles ya quedó parcheado
Más aún porque es un módulo builtin y no se puede sacar fácilmente con
rmmodBuscando si el kernel 6.19.14 de Fedora 44 era vulnerable, encontré este mensaje en la lista linux-cve-announce: https://lore.kernel.org/linux-cve-announce/2026042214-CVE-2026-31431-3d65@gregkh/T/#u
Ahí dice que quedó corregido con esos commits en 6.18.22, 6.19.12 y 7.0, así que sirve como referencia
Si quieres comprobar que se aplicó la mitigación recomendada y que el módulo
algif_aeadquedó bloqueado mediante la configuración de modprobe, no hace falta ejecutar entero ese shell ofuscadoCon unas pocas líneas de Python como esta puedes verificar de forma legible si el módulo realmente llega a cargarse
python3 -c 'import socket; s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0); s.bind(("aead","authencesn(hmac(sha256),cbc(aes))")); print("algif_aead probably successfully loaded, mitigation not effective; remove again with: rmmod algif_aead")'Si la mitigación quedó bien aplicada,
modprobe algif_aeadtambién debería fallar con errorSeguro que nadie está ejecutando agentes de IA totalmente autónomos con permisos de usuario normal en sistemas operativos afectados
Si se combina con inyección de prompts zero-day, podría ser bastante catastrófico
curl | shen un estándar de facto para instalar cosas en la industriaLPE significa local privilege escalation
Hay demasiadas siglas en seguridad y, aunque por contexto se puede deducir, igual habría sido mejor escribirlo completo la primera vez
Aun así, si el texto apunta a un público más amplio, estoy de acuerdo en que conviene definirla explícitamente
Además, todo este texto parece generado por IA
Esto da un poco de risa
La página dice que funciona en RHEL 14.3, pero esa versión no existe
RHEL va actualmente por la serie 10.x, así que sentí que me había subido a una TARDIS
A veces aparece algo como
gcc (GCC) 14.3.1 20250617 (Red Hat 14.3.1-2), y en los ejemplos de abajo se ven rastros parecidoshttps://github.com/anthropics/claude-code/issues/40741
https://docs.oracle.com/en/database/oracle/tuxedo/22/otxig/software-requirements-red-hat-enterprise-linux-10-64-bit.html
6.12.0-124.45.1.el10_1, y eso claramente es un kernel de RHEL 10Este tipo de error tipográfico más bien lo comete una persona
Los números largos copiados y pegados salen bien, y los fáciles se equivocan al teclearlos a mano
Hubo cierta prisa al recopilar la información para explicar el problema y sí, también había una intención de marketing
Así que se colaron algunos errores menores; gracias por señalarlo
https://access.redhat.com/articles/red-hat-enterprise-linux-release-dates
Y después de llegar al "Talk to our security experts" al final de la página, hasta me dieron ganas de preguntar si ese experto en seguridad se llamaba Claude
En RHEL 9/10, algif_aead no era un módulo sino builtin, así que no se podía descargar
Como alternativa, encontré una forma de bloquear AF_ALG mediante systemd, aunque requiere un drop-in por cada servicio expuesto
También hay un playbook de Ansible para cubrir los principales,
sshdyuser@https://gist.github.com/m3nu/c19269ef4fd6fa53b03eb388f77464da
initcall_blacklist=algif_aead_initcomo parámetro de arranque del kernel y luego reiniciarHaciéndolo así, el exploit dejó de funcionar
Me preocupa qué pasaría con otras rutas de ejecución como
cronjoboslurmjob, y estaría bien una forma de hacer que todos los procesos lo hereden a nivel systemd, en vez de configurarlo por servicio individualParece que este exploit funciona reemplazando un binario SUID para hacer que corra como PID 0
Pero el sitio afirma que también permite escapar de Kubernetes / clusters de contenedores y de CI runners & build farms, aunque no veo una explicación real que sustente escape de contenedores ni, en particular, escape de user namespace
Lo probé en Podman rootless y, como era de esperarse, no logró salir del contenedor
También dicen que "convierte en root a todas las distribuciones Linux lanzadas desde 2017", pero las pruebas reales son solo cuatro y en Alpine no funcionó
Ya lo adelantaron con:
"Next: "From Pod to Host," how Copy Fail escapes every major cloud Kubernetes platform."https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=72548b093ee3
Pero la posibilidad real de explotación dependerá de si se trata de una versión major reciente o de un kernel de mantenimiento de una rama vieja
Aun así, corrí el PoC directamente en una instancia 24.04 y la vulnerabilidad sí parece real, además de lo bastante seria
Pero el número de distribuciones afectadas parece mucho menor que lo que afirman, y está bastante lejos de eso de todas las distribuciones desde 2017
Por ejemplo, si mi interpretación es correcta, Ubuntu tiene algo de impacto incluso en 16.04 EOL, pero el grueso del impacto real parece estar en kernels de vendors que empezaron a distribuirse recientemente, como
linux-gcpylinux-oracle-6.7, o sea la línea 6.17Pero harían falta pasos adicionales, y Alpine también podría ser vulnerable en lo esencial aunque solo requiera ajustar el script
Al final esto no es un exploit universal y acabado, sino un PoC
La página en sí se siente algo vibecoded y también tiene pinta de anuncio, pero la vulnerabilidad es real y el nivel de riesgo parece alto
Explica por qué hoy llegó una actualización de seguridad grande, así que voy a subir la prioridad de actualizar
Encuentran y ayudan a corregir bugs reales, o sea hacen una contribución significativa al ecosistema OSS, y al mismo tiempo venden su propia herramienta de seguridad
Pero bueno, hoy en día casi nadie arma páginas web a mano, y si además son desarrolladores del kernel, menos todavía