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
CVE-2026-31431-CopyFail-static-ELF--POC — Exploit ELF estático de 587 bytes para CVE-2026-31431, que logra escalada local de privilegios mediante la corrupción de la caché de páginas de splice en AF_ALG. Sin dependencias de libc ni de tiempo de ejecución. | Kitploit
Herramientas/GitHubGitHub/rat5ak/cve-2026-31431-copyfail-static-elf--poc
Escalada de PrivilegiosFrameworks de ExploitsAnálisis de VulnerabilidadesExplotaciónDesarrollo de PayloadsExplotación de Binarios
GitHubrat5ak/cve-2026-31431-copyfail-static-elf--poc

CVE-2026-31431-CopyFail-static-ELF--POC

Exploit ELF estático de 587 bytes para CVE-2026-31431, que logra escalada local de privilegios mediante la corrupción de la caché de páginas de splice en AF_ALG. Sin dependencias de libc ni de tiempo de ejecución.

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
Ver Repositorio
4hace 4 mesesAún no revisado

CVE-2026-31431: Copy Fail - ELF estático de 587 bytes

No encontré este bug. El crédito es para Xint Code / Theori.

Este repo es mi enfoque para hacer el exploit lo más pequeño posible: un ELF x86_64 hecho a mano que hace el LPE completo en 587 bytes. Sin libc, sin enlazador, sin runtime. Solo NASM y terquedad.

En efecto, el kernel te entrega una primitiva de escritura en el page cache de cualquier archivo legible a través de AF_ALG + splice. Apúntala al punto de entrada de un binario setuid, escribe shellcode, ejecuta el binario, root.

Para contexto sobre el tamaño: el post público original de Copy Fail incluía una versión en Python de 732 bytes. Eso es extremadamente genial, pero aún depende de que el runtime de Python esté presente. Más pequeño aún es https://kopy.fail con 524 bytes. Este, sin embargo, es un ELF estático puro: sin intérprete, sin libc, sin enlazador, sin cargador dinámico. (mi mamá dice que es genial)

CVECVE-2026-31431
Clase de bugCorrupción del page cache mediante alias de splice
Causa raízaf_alg_sendpage / splice en solicitudes AEAD crea alias de páginas del page cache en la salida crypto scatter-gather
Componentecrypto/af_alg.c + crypto/algif_aead.c
ImpactoEscribir bytes controlados en el page cache de cualquier archivo legible
RequisitosUsuario local, soporte AF_ALG/AEAD accesible, objetivo setuid legible
ExploitELF estático de 587 bytes (x86_64), archivo único, cero dependencias

El Bug

AF_ALG permite al espacio de usuario hacer criptografía del kernel a través de sockets. Para cifrados AEAD como authencesn, el kernel acepta datos mediante sendmsg con MSG_MORE, y luego puedes hacer splice de más datos desde un descriptor de archivo.

La parte maldita: cuando haces splice de un archivo, el kernel fija las páginas del page cache del archivo directamente en la lista crypto scatter-gather. La operación AEAD luego escribe su salida de vuelta en esas mismas páginas. El kernel cree que le dio a la criptografía un buffer de lectura. La criptografía cree que recibió un buffer de escritura. Nadie copia.

Los bytes que alimentas como metadatos AAD terminan visibles a través del page cache. Cualquier lectura posterior de ese archivo - por cualquier proceso, cualquier usuario, incluyendo la ejecución de suid - ve los datos corruptos. El archivo en disco no se toca. Solo cambia la vista del page cache en memoria.

Nombre

Copy Fail es la maldición de la familia page-cache/COW apareciendo con ropa de AF_ALG. Mismo linaje que Dirty COW (CVE-2016-5195) - "el kernel te dejó escribir en algo que solo deberías poder leer" - pero a través de la ruta de crypto splice en lugar de la carrera madvise/write.

Explotación

Objetivo: /bin/su en Debian Bookworm (incluyendo el rootfs de kernelCTF). El punto de entrada del ELF está en el offset de archivo 0x3910.

28 bytes de shellcode lo convierten en un dropper de shell root:

root@kitploit:~
; setuid(0) - 7 bytes
31 ff           xor edi, edi
6a 69           push 105
58              pop rax
0f 05           syscall
; execve("/bin/sh", NULL, NULL) - 21 bytes
99              cdq
31 f6           xor esi, esi
48 bb 2f 62 69 6e 2f 73 68 00   movabs rbx, "/bin/sh\0"
53              push rbx
54              push rsp
5f              pop rdi
6a 3b           push 59
58              pop rax
0f 05           syscall

La primitiva AEAD solo te da 4 bytes por operación: un fragmento de 32 bits del AAD aterriza en el offset del splice. 28 bytes de shellcode ÷ 4 = 7 viajes a través de la pila criptográfica del kernel. Cada iteración:

  1. socket(AF_ALG) + bind con authencesn(hmac(sha1),cbc(aes))
  2. setsockopt para establecer la clave y el tamaño de la etiqueta de autenticación
  3. accept para obtener el fd de solicitud
  4. sendmsg con MSG_MORE - el iov de 8 bytes contiene 4 bytes de relleno AAD + 4 bytes de shellcode
  5. splice desde /bin/su a través de un pipe hacia el fd de solicitud (posiciona las páginas del page cache)
  6. recvfrom - dispara el procesamiento AEAD, corrompe el page cache
  7. Cierra todo (crítico: el estado AF_ALG obsoleto corrompe los splices posteriores)

Después de las 7 iteraciones, execve("/bin/su"). El kernel lo carga desde el page cache corrupto. La ejecución salta al punto de entrada sobrescrito. Shell root.

El Binario

587 bytes en total. 120 de esos son el encabezado ELF (el kernel no te cargará sin él), así que la lógica real del exploit son 467 bytes de código máquina + datos.

Aquí es donde viven las cosas en el encabezado ELF:

root@kitploit:~
Offset  Campo           Uso real
------  -----           ----------
0x00    e_ident[0:8]    magic + clase ELF (obligatorio)
0x08    e_ident[8:16]   material de clave criptográfica (el kernel ignora estos bytes)
0x28    e_shoff         cadena "/bin/su\0" (el kernel lo ignora para ET_EXEC)

El kernel solo mira e_ident[0:7], e_type, e_machine, e_entry, e_phoff, e_phnum y el propio phdr. Todo lo demás es espacio libre.

Otros trucos de tamaño:

  • Un solo PT_LOAD RWX, BSS para el sockaddr_alg de 88 bytes (el kernel lo pone a cero)
  • Todas las syscalls codificadas como push imm8 / pop rax / syscall (3 bytes cada una)
  • El contador de bucle en r14 cuenta hacia abajo de 24→0 en pasos de -4, y sirve como índice del shellcode
  • Registros elegidos para sobrevivir entre syscalls (r12=fd_objetivo, r15=fd_alg, rbp=fd_solicitud, rbx=base_shellcode) para no desperdiciar bytes recargándolos

La historia de 584→587

La primera versión funcional era de 584 bytes. Usaba mov ax, 275 para la segunda llamada a splice (2 bytes más corto que mov eax, 275). Esto apuesta a que el primer splice siempre tiene éxito: si devuelve un error negativo, los 48 bits superiores de rax permanecen establecidos, y mov ax, 275 solo sobrescribe los 16 inferiores. Entonces el número de syscall del segundo splice es basura.

En mi kernel de prueba siempre funcionó. Pero "siempre funciona en pruebas" es una mala razón para enviar un bug, y si alguien lo encuentra en un sistema donde splice devuelve EAGAIN bajo presión de memoria, el exploit simplemente hace segfault sin indicación de qué salió mal. Me comí los 3 bytes extra.

También tuve que añadir xor esi, esi antes del execve final porque recvfrom sobrescribe rsi con la dirección del buffer. Sin eso, execve recibe un puntero argv basura. Otro byte.

Compilación

root@kitploit:~
nasm -f bin -o copy_fail_v3 copy_fail_v3.asm && chmod +x copy_fail_v3

Requiere NASM. Produce el binario del exploit directamente: sin paso de enlazado.

Uso

root@kitploit:~
$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ ./copy_fail_v3
# id
uid=0(root) gid=0(root) groups=0(root)

Tarda menos de un segundo. Sin salida en caso de éxito: solo un shell root.

Kernels Afectados

Necesita CONFIG_CRYPTO_USER_API_AEAD (integrado o módulo cargado) y la ruta de splice in-place sin parchear en algif_aead. La ruta de código defectuosa se remonta a una optimización de 2017. Revisa la configuración del kernel de tu distribución y el estado del parche.

Solución

La solución elimina la ruta in-place y copia las páginas de origen del splice en lugar de crearles alias en la lista crypto scatter-gather. Se restaura el aislamiento del page cache.

No seas estúpido

Esto es un artefacto de KernelCTF/laboratorio. Ejecútalo en sistemas que te pertenecen o para los que tienes permiso explícito de prueba. Si defiendes máquinas Linux, parchea el kernel o restringe la carga del módulo AF_ALG/algif_aead.


Daniel Wade - GitHub · Twitter/X · Bluesky · nadsec.online

Descargar herramienta