3 puntos por GN⁺ 4 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Un usuario local sin privilegios puede encadenar authencesn, AF_ALG y splice() 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_ALG viene 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 desactivar algif_aead y bloquear AF_ALG para cargas de trabajo no confiables

Resumen de la vulnerabilidad

  • Un solo fallo lógico lineal puede encadenarse con authencesn, AF_ALG y splice() 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_ALG de 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.py usa únicamente las bibliotecas estándar de Python 3.10+ os, socket y zlib
  • El objetivo por defecto es /usr/bin/su y se puede pasar otro binario setuid en argv[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_aead introducida 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_aead
    • echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
    • rmmod 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_ALG con 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
  • Si en OpenSSL se habilitó explícitamente el motor afalg, algunas rutas de offload criptográfico embebido y aplicaciones que hagan bind directo a sockets aead/skcipher/hash sí pueden verse afectadas
    • Puede verificarse con lsof | grep AF_ALG o ss -xa
  • 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 de execve es 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 mediante read(), 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 execve antes 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/su no es obligatorio; cualquier binario setuid-root legible por el usuario puede servir, como passwd, chsh, chfn, mount, sudo o pkexec
  • 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_aead para volver a separar req->src y req->dst en 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

 
GN⁺ 4 시간 전
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

    • Como no sabía qué era AF_ALG, busqué y encontré https://www.chronox.de/libkcapi/html/ch01s02.html, donde sí explican por qué existe
      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
    • Me pregunto cómo demonios terminó entrando al kernel
      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
    • AF_ALG es una interfaz de sockets de Linux que expone la API crypto del kernel a través de descriptores de archivo
      Permite manejar hashes y cifrado mediante llamadas normales a read(2)/write(2)
    • Lo que más me intriga es qué software se rompe al desactivar esta opción del kernel
  • 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

    • Desde que el parche entró al kernel, en la práctica atacantes y observadores ya lo conocían desde hacía semanas
      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
    • Parece que las distribuciones lo consideran de riesgo medio porque requiere acceso local en vez de ejecución remota de código
      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
    • RedHat ahora ya lo cambió a Important severity y Affected
    • Si uno sigue las propias guías de Ubuntu, esto debería ir como high priority, así que que esté marcado como medium no se ve muy consistente
  • 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 rmmod
    Buscando 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_aead quedó bloqueado mediante la configuración de modprobe, no hace falta ejecutar entero ese shell ofuscado
    Con 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_aead también debería fallar con error

  • Seguro 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

    • Mi agente ya corre como root, así que ni me entero del problema
    • Por suerte no convertimos curl | sh en un estándar de facto para instalar cosas en la industria
  • LPE 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

    • LPE es una sigla bastante conocida dentro de la comunidad de seguridad, así que no me parece gravísimo que no la hayan desarrollado
      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
    • Si escribes para un público amplio, lo básico es desarrollar primero las siglas, pero los LLM no suelen seguir bien ese tipo de guía
  • 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

    • 14.3 probablemente no es una versión de RHEL sino algo tomado de la versión de GCC de Red Hat
      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 parecidos
      https://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
    • En la misma línea también aparece 6.12.0-124.45.1.el10_1, y eso claramente es un kernel de RHEL 10
      Este 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
    • Perdón, pero eso se va a corregir
      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
    • Sí, en cuanto vi la frase "Distribuciones verificadas directamente: RHEL 14.3", la página de lanzamiento ya me sonó a AI slop
      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, sshd y user@
    https://gist.github.com/m3nu/c19269ef4fd6fa53b03eb388f77464da

    • En RHEL 9/10 también se podía usar initcall_blacklist=algif_aead_init como parámetro de arranque del kernel y luego reiniciar
      Haciéndolo así, el exploit dejó de funcionar
    • Yo pensé en algo parecido, pero bloquearlo servicio por servicio se siente como jugar al whack-a-mole
      Me preocupa qué pasaría con otras rutas de ejecución como cronjob o slurmjob, y estaría bien una forma de hacer que todos los procesos lo hereden a nivel systemd, en vez de configurarlo por servicio individual
  • Parece 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ó

    • En el sitio dijeron que pronto publicarían más detalles, así que probablemente los pasos extra o las correcciones salgan en la parte 2
      Ya lo adelantaron con: "Next: "From Pod to Host," how Copy Fail escapes every major cloud Kubernetes platform."
    • Esta vulnerabilidad permite sobrescribir bytes en memoria de archivos que se pueden leer, así que sí es fácil imaginar formas de escapar en distintos entornos
    • La afirmación de todas las distribuciones desde 2017 parece basarse en que esta vulnerabilidad entró con un commit de la segunda mitad de 2017
      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
    • Este texto se perjudicó bastante a sí mismo en términos de credibilidad
      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-gcp y linux-oracle-6.7, o sea la línea 6.17
    • Incluso dentro de un contenedor rootless, si logras subir hasta UID 0 real, luego ya podría venir el escape
      Pero 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

    • Sí, esto es una publicidad bastante evidente, pero personalmente no me parece mala publicidad
      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
    • Esta gente probablemente ya tendría trabajo de sobra incluso sin publicidad
      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