
Sonda remota de caja negra que detecta CVE-2026-98432, un use-after-free de ireq_opt en TCP IPv4 de Linux, mediante eco diferencial de opciones en SYN-ACK, además de verificación estática de vmlinux.
Hola. CVE-2026-98432 es un Use-After-Free explotable de forma remota en el kernel de Linux. Algunos informes afirman que laboratorios de IA lo explotaron tras ~45 min mediante Multi-Path TCP (MPTCP). La vulnerabilidad está en realidad en la propia pila TCP de IPv4; simplemente resulta que MPTCP es la única forma remotamente práctica de alcanzar la ruta de código vulnerable. Aun así, lo de los ~45 min merece un escrutinio muy profundo.
ireq_opt y la primera desreferencia.Seguramente existan kernels de Linux personalizados que usan MPTCP con opciones de direccionamiento por paquete que probablemente hagan que esta vulnerabilidad sea "alcanzable" en el sentido más puro. En la práctica, casi con total seguridad no estás ejecutando una configuración de kernel así, y tampoco eres tan desafortunado como para que alguien esté lo bastante cerca en latencia y sea lo bastante persistente como para colarse por ese hueco.
El factor principal que hace que la explotación sea siquiera remotamente práctica son las VM virtualizadas/sobrevendidas, con PREEMPT_RT, threadirqs, etc... algo sobre lo que un atacante no tiene ningún control ni influencia, salvo que disponga de algún acceso privilegiado/autenticado adicional. Tengo amigos en el sector que probablemente conozcan algún truco que me haría cambiar de opinión, pero yo no conozco ninguno, la IA se quedó en blanco y, como mínimo, ese "truco", si existe, no es ampliamente conocido.
Deberías parchear tus servidores, pero probablemente sin entrar en pánico. Todo lo demás en este repositorio, incluidas las líneas siguientes, está generado por IA, pero yo dirigí la sesión y he revisado los artefactos en busca de exactitud.
A continuación:
Una sonda remota de caja negra que demuestra la presencia de CVE-2026-98432
(use-after-free de ireq_opt / inet_opt en TCP de IPv4 de Linux) con evidencia
a nivel de paquete — no mediante la coincidencia de versiones del kernel.
Se detiene en el use-after-free: demuestra que el kernel leyó memoria liberada y lo dejó dicho en el cable. No elude KASLR, no secuestra el flujo de control ni ejecuta código.
Solo para pruebas autorizadas. La sonda de carrera puede desestabilizar un objetivo; un kernel bloqueado es un resultado plausible. Úsala solo en hosts de tu propiedad o para los que tengas permiso por escrito para probar.
La corrección es e3f33b0a1d89d738e2b913dab519226eaf76e15b
(ipv4: free inet_opt and ireq_opt after an RCU grace period), un cambio de dos líneas
de kfree() a kfree_rcu() en inet_sock_destruct() y
tcp_v4_reqsk_destructor().
tcp_v4_init_req() almacena las opciones IP reflejadas del SYN (Record Route /
Timestamp) en ireq->ireq_opt.tcp_v4_syn_recv_sock() transfiere el puntero al socket hijo en lugar
de copiarlo.ireq->ireq_opt bajo
rcu_read_lock() y lo usa en ip_options_build().Ese último punto es el detector: el kernel devuelve los bytes obsoletos de la opción al emisor.
Corrección de alcance: el registro del CVE es TCP de IPv4 genérico. Solo el blog de Anthropic lo vincula a un "multipath TCP listener"; ningún texto de CVE/NVD/Red Hat/Debian/Ubuntu menciona MPTCP. La sonda prueba primero TCP simple.
Tres patas independientes, de la más débil a la más fuerte:
| Tramo | Qué muestra | Artefacto |
|---|---|---|
| Estático (fijado por build-id) | la forma del código del kernel en ejecución: kfree simple en ambos destructores = vulnerable; kvfree_call_rcu = parcheado | verify-local, tabla a continuación |
| Oráculo sintético | el detector de red se activa cuando un respondedor devuelve memoria de slab reutilizada | scripts/validate_synthetic.sh → CONFIRMED VULNERABLE |
| Dinámico, a nivel de kernel (laboratorio KVM) | KASAN reporta el slab-use-after-free real en ip_options_build, con las pilas del commit; un kernel con kfree_rcu y tráfico idéntico permanece limpio | evidence/guest-inst-vuln6-KASAN.log, evidence/guest-inst-patched2-CONTROL.log |
| Visible en la red, kernel real (laboratorio sin KASAN) | el SYN-ACK en la red transportaba el bloque de opciones rociado (42 04 be ef…) en lugar del timestamp devuelto; el control con kfree_rcu permaneció limpio | evidence/race-stage1-wire-uaf.json, evidence/race-control-kfree_rcu.json |
El tramo dinámico es un invitado 7.0.14 creado a propósito (KASAN + una
extensión de ventana mediante parámetro de arranque) con direccionamiento de CPU por paquete: el SYN retransmitido se
procesa en una vCPU, el ACK/transferencia en una segunda, y el
accept()+close() de la víctima en una tercera, de modo que la sobrescritura es rutinaria en lugar de
accidental. El propio kernel reportó:
BUG: KASAN: slab-use-after-free in ip_options_build
Read of size 16 ... by task swapper/0 (cpu0, softirq)
__asan_memcpy <- ip_options_build <- ip_build_and_send_pkt
<- tcp_v4_send_synack <- tcp_rtx_synack <- tcp_check_req <- tcp_v4_rcv
Freed by task 1 (victim, cpu3):
kfree <- inet_sock_destruct <- __sk_destruct <- inet_release <- __x64_sys_close
object: kmalloc-96, 16 bytes in (struct ip_options at the rcu_head offset)
más 30 registros READ-AFTER-FREE del lado del lector (lectura 71–322 µs después del free,
optlen=40, sombra KASAN 0xfb). El control parcheado (kfree_rcu, verificado
en el archivo objeto) ejecutó la misma carrera y retención: 0 KASAN, 0 read-after-free.
Esa es la vulnerabilidad, no una conjetura de versión.
El lector no es un bucle largo. tcp_v4_send_synack() carga ireq->ireq_opt
y lo pasa a ip_build_and_send_pkt()/ip_options_build(), cuyo memcpy
es la lectura de use-after-free; la carga y la lectura están a unas pocas instrucciones de distancia
(decenas a cientos de nanosegundos). El lado del free — la destrucción del hijo tras el
accept()+close() de la víctima — es mucho más tardío: solo el ciclo de close medido
es de 61–92 µs, y la latencia ACK→destrucción añade el despertar entre CPUs.
Así que los dos eventos no son simplemente raros juntos; están separados por ~90 µs por construcción, y la lectura termina mucho antes del free. El experimento de temporización natural lo cuantifica: con el mismo kernel instrumentado, sin estiramiento de ventana, ~140k intentos de carrera y una rotación concurrente de half-open,
stats: frees=180223 overlaps=0 raf=0 KASAN: 0