
Una implementación en Bash de copyfail (CVE-2026-31431)
Sin condición de carrera. Sin offsets. Sin binario precompilado en el que confiar a ciegas.
Una implementación en bash del CVE-2026-31431 (Copy Fail). El script compila un pequeño helper en C inline en tiempo de ejecución. La capa bash se encarga de la detección de arquitectura, la descompresión del payload y la selección del objetivo; la capa C realiza la interacción real con el kernel (sockets AF_ALG, splice, sendmsg) a la que bash no puede llegar por sí solo.
Ver copy.fail para el desglose técnico completo.
El fallo está en algif_aead, la interfaz de sockets AF_ALG AEAD del kernel. Una optimización in-place de 2017 permite que las páginas de la page cache terminen en la scatterlist de destino escribible de una operación de descifrado authencesn. Si le pasas la entrada correcta mediante splice(), obtienes una escritura determinista de 4 bytes en la page cache de cualquier archivo legible, incluidos los binarios setuid que no te pertenecen.
Sobrescribe /usr/bin/su con shellcode de 4 bytes a la vez, ejecútalo y obtén una shell root. Sin ventana de condición de carrera, sin símbolos específicos del kernel, sin reintentos.
chmod +x copyfail.sh
# Check if the system is vulnerable before doing anything
./copyfail.sh -c
# Run the exploit (must be non-root)
./copyfail.sh
# Specify a different setuid target
./copyfail.sh -t /usr/bin/passwd
# List all setuid-root candidates on the system
./copyfail.sh -s
El exploit sobrescribe solo la page cache en memoria; el archivo en disco no se toca. Un reinicio lo restaura todo. Si quieres limpiar de inmediato:
# Inside your root shell
/usr/bin/su --version # still works from disk if page cache is evicted
# Or just reboot
Si usaste -t con algo distinto de su, pasa lo mismo. Solo page cache; el disco está limpio.
gcc para compilar el helper C inlinepython3 para descomprimir el payload de shellcode (una línea, sin paquetes necesarios)algif_aead, authencesn, hmac, cbcSi el algoritmo no está disponible:
sudo modprobe algif_aead authencesn hmac cbc
Algunas distribuciones incluyen un bloqueo en /etc/modprobe.d/ como solución temporal. Elimínalo si está presente:
sudo rm /etc/modprobe.d/disable-algif{_,-}aead.conf 2>/dev/null
floor: torvalds/linux 72548b093ee3 August 2017, v4.14
(AF_ALG iov_iter rework that introduced
the file-page write primitive via splice
into the AEAD scatterlist)
ceiling: torvalds/linux a664bf3d603d April 2026, mainline
(reverts the 2017 in-place optimization;
source and destination scatterlists are
now separate, page-cache pages can no
longer end up as writable crypto output)
Entre esos dos commits: todas las distribuciones importantes que no aplicaron el backport de la corrección. Ubuntu, RHEL, SUSE, Amazon Linux y Debian fueron confirmados como vulnerables en el momento de la divulgación. Los backports de las distribuciones comenzaron a llegar alrededor del 2026-04-29. Para comprobar un kernel específico, busca a664bf3d603d (o su backport de la distribución) en el changelog.
| Arquitectura | Estado |
|---|---|
| x86_64 | ✓ |
| aarch64 | ✓ |
| i386 / i686 | ✓ |
| armv7l | ✓ |
Permanente: actualiza tu kernel.
Solución temporal (bloquea el socket AF_ALG; no afecta a IPsec/XFRM, que usa la API criptográfica del kernel directamente):
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
sudo rmmod algif_aead 2>/dev/null
Contenedores: añade un perfil de seccomp que bloquee la creación de sockets AF_ALG y establece allowPrivilegeEscalation: false en tu contexto de seguridad del pod. Esto habilita no_new_privs, lo que impide que el kernel honre los bits setuid en execve().
La versión en bash no gana en dependencias, pero es un único script que puedes leer de principio a fin antes de ejecutarlo. El helper en C se genera y compila en tiempo de ejecución a partir de un heredoc; no hay ningún binario que auditar por separado.
Solo para pruebas de seguridad e investigación autorizadas. No ejecutes esto en sistemas que no poseas o para los que no tengas permiso escrito explícito para probar.
| Python | Go | Bash |
|---|
| Dependencia | python3 | ninguna (binario estático) | gcc + python3 |
| Binario precompilado | no | sí | no |
| Archivo único | sí | no | sí |
| Paso de compilación | no | no | sí (inline, automático) |