Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
copy-fail-CVE-2026-31431 — Fallo de copia: 732 bytes a root en todas las principales distribuciones de Linux. | Kitploit
Herramientas/GitHubGitHub/rio128128/copy-fail-cve-2026-31431
Escalada de PrivilegiosSeguridad de ContenedoresFrameworks de ExploitsAnálisis de VulnerabilidadesExplotaciónPruebas de PenetraciónSeguridad en la NubeRed TeamingExplotación de Binarios

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
GitHubrio128128/copy-fail-cve-2026-31431

copy-fail-CVE-2026-31431

Fallo de copia: 732 bytes a root en todas las principales distribuciones de Linux.

Ver Repositorio
25hace 5 mesesAún no revisado

CVE-2026-31431 — Copy Fail

732 bytes. Cualquier distro. Root.

Una falla lógica lineal en la plantilla criptográfica authencesn del kernel de Linux permite a un usuario local sin privilegios realizar una escritura precisa y controlada de 4 bytes en la caché de páginas de cualquier archivo legible, incluidos los binarios setuid. Sin condiciones de carrera. Sin reintentos. Sin recompilación. Root en todas las principales distribuciones de Linux publicadas desde 2017.

📄 Informe técnico  ·  🔗 Parche del kernel  ·  🛡️ CVSS: Crítico


Distribuciones probadas

DistroVersión del kernel
Ubuntu 24.04 LTS6.17.0-1007-aws
Amazon Linux 20236.18.8-9.213.amzn2023
RHEL 10.16.12.0-124.45.1.el10_1
SUSE 166.12.0-160000.9-default

Las cuatro fueron comprometidas con el mismo script de Python de 732 bytes, sin modificación.


Qué hace que esto sea diferente

PropiedadDetalle
DeterministaFalla lógica lineal: sin condiciones de carrera, sin ventanas de sincronización, sin reintentos
PortátilMismo script, mismos bytes, funciona en todas las distros y arquitecturas probadas
DiminutoScript de Python de 732 bytes que usa solo la biblioteca estándar (os, socket, zlib). Requiere Python 3.10+ para os.splice
SigilosoLa página corrupta nunca se marca como sucia. Las sumas de verificación en disco no cambian; solo se modifica la caché de páginas en memoria
Transversal a contenedoresLa caché de páginas se comparte en todo el sistema a través de los límites de los contenedores: esto también es una primitiva de escape de nodos de Kubernetes (ver Parte 2)

Causa raíz

La configuración: páginas de caché en un scatterlist escribible

AF_ALG expone el subsistema criptográfico del kernel al espacio de usuario sin privilegios. splice() transfiere datos de archivos a una tubería por referencia, pasando las páginas de la caché directamente, sin copiarlas. Cuando un usuario hace splice de un archivo a un socket AEAD AF_ALG, el scatterlist de entrada del socket contiene referencias en vivo a las páginas cacheadas del kernel de ese archivo.

En algif_aead.c, la optimización in-place de 2017 copió AAD y texto cifrado del scatterlist TX al búfer RX, pero encadenó las páginas de la etiqueta de autenticación por referencia usando sg_chain(), y luego estableció req->src = req->dst:

SGL de entrada: [ AAD | CT | Tag ]
                              ^
                              └─ sg_chain() → todavía apunta a páginas de caché

SGL de salida:  [ AAD | CT ] ──→ [ Tag (páginas de caché) ]
              (búfer RX)        (encadenado desde SGL TX)

req->src ──┐
           ├──→ mismo scatterlist combinado
req->dst ──┘

Las páginas de caché de splice() ahora estaban dentro de un scatterlist de destino escribible, separadas de la región de escritura legítima solo por un límite de desplazamiento. Nada en la API garantizaba que los algoritmos permanecieran dentro de los límites.

El disparador: la escritura fuera de límites de authencesn

authencesn es un envoltorio AEAD utilizado por IPsec para soporte de Número de Secuencia Extendido (ESN) de 64 bits. Para reorganizar los bytes ESN para el cálculo HMAC, usa el búfer de destino del llamador como espacio de trabajo, incluida una escritura en el desplazamiento assoclen + cryptlen, que se encuentra más allá del límite de la etiqueta de autenticación:

scatterwalk_map_and_copy(tmp,     dst, 0,                       8, 0); // lee AAD[0..7]
scatterwalk_map_and_copy(tmp,     dst, 4,                       4, 1); // sobrescribe dst[4..7]
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen,     4, 1); // ← escribe más allá de la etiqueta

La tercera llamada escribe 4 bytes (seqno_lo) en dst[assoclen + cryptlen]. En la ruta in-place de AF_ALG, el scatterwalk cruza desde el búfer RX hacia las páginas de etiqueta encadenadas de la caché. El kernel mapea la página de caché mediante kmap_local_page y escribe directamente en la copia cacheada del archivo objetivo.

Luego el HMAC falla (el texto cifrado es fabricado), recvmsg() devuelve un error, pero la escritura de 4 bytes persiste permanentemente.

Las tres variables controladas por el atacante

VariableControlada mediante
Archivo objetivoCualquier archivo legible por el usuario actual
Desplazamiento de escrituraassoclen, desplazamiento de splice y longitud de splice
Valor de escrituraBytes 4–7 del AAD proporcionado en sendmsg() (seqno_lo)

Cómo sucedió: una cadena de nueve años

AñoEvento
2011authencesn se agregó al kernel (a5079d084f8b) para soporte ESN de IPsec. La escritura de trabajo existía pero era inofensiva: solo la capa interna xfrm la llamaba, y el AAD vivía en un scatterlist separado.
2015AF_ALG gana soporte AEAD. authencesn se convierte a la nueva interfaz AEAD (104880a6b470), introduciendo el desplazamiento de escritura assoclen + cryptlen. Aún fuera de lugar: las páginas de caché estaban en src (solo lectura). Aún no explotable.
2017Se agrega la optimización in-place a algif_aead.c (72548b093ee3). req->src = req->dst. Las páginas de etiqueta de la caché se encadenan al destino escribible. Se forma la vulnerabilidad.
2026-03-23Reportada al equipo de seguridad del kernel de Linux.
2026-04-01Parche fusionado en mainline.
2026-04-22Se asigna CVE-2026-31431.
2026-04-29Divulgación pública.

Ningún cambio individual fue incorrecto por sí solo. La vulnerabilidad vive en la intersección de los tres.


Exploit

El objetivo predeterminado es /usr/bin/su, un binario setuid-root presente en todas las distribuciones probadas.

Paso 1 — Configuración del socket
  Abrir socket AF_ALG, vincular a authencesn(hmac(sha256),cbc(aes))
  Establecer clave. Aceptar socket de solicitud. (No se requieren privilegios.)

Paso 2 — Bucle de escritura (una vez por fragmento de shellcode de 4 bytes)
  sendmsg()  →  los bytes AAD [4:8] transportan los 4 bytes a escribir (seqno_lo)
  splice()   →  páginas de caché del archivo objetivo al socket AF_ALG
  recv()     →  dispara decrypt → authencesn escribe seqno_lo en la caché de páginas
               (recvmsg devuelve error; la escritura persiste)

Paso 3 — Ejecución
  execve("/usr/bin/su")
  El kernel carga el binario desde la caché de páginas (ahora corrupta)
  El binario setuid-root ejecuta el shellcode inyectado → UID 0
a = socket.socket(38, 5, 0)                          # AF_ALG, SOCK_SEQPACKET
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
# ... establecer clave, aceptar socket de solicitud u ...
u.sendmsg([b"A"*4 + payload_chunk], [cmsg_headers], MSG_MORE)
os.splice(target_fd, pipe_wr, offset)
os.splice(pipe_rd, alg_fd, offset)
u.recv(...)                                          # dispara la escritura en la caché de páginas

Remediación

Corrección permanente

Actualice a un kernel que contenga el parche a664bf3d603d. La corrección revierte algif_aead.c a operación fuera de lugar: req->src apunta al SGL TX; req->dst apunta al búfer RX. Las páginas de caché de splice() permanecen de solo lectura. El mecanismo sg_chain() que las vinculaba al destino escribible se elimina.

Descargar herramienta