
Mitigación temporal para CVE-2026-98432 (use-after-free en ireq_opt de TCP IPv4 de Linux): descartar TCP IPv4 con opciones IP, deshabilitar MPTCP. Scripts probados + verificación. EN/KO.
Este repositorio contiene scripts que descartan paquetes TCP IPv4 que transportan opciones IP en un host Linux. En hosts sin etiquetado CIPSO de SELinux/Smack NetLabel, CVE-2026-98432 (un use-after-free en TCP IPv4 del kernel de Linux) no puede activarse sin dichos paquetes. Es una mitigación temporal, no una corrección. No se probó contra un exploit real (no existe un PoC público), y ningún proveedor la respalda. Si tu distribución ya incluye un kernel corregido, instálalo, y ejecuta revert.sh si aplicaste esto. Si no lo incluye, comprueba que la mitigación se aplica a tu host y luego aplícala y verifícala con los pasos siguientes (unos 10 minutos). El autor es un administrador individual, no un proveedor.
uname -r con las versiones estables corregidas: 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3 (commit de corrección e3f33b0a1d89d738e2b913dab519226eaf76e15b). Un kernel de distribución puede incluir la corrección con un número de versión diferente, así que consulta también el tracker de tu proveedor.cat /sys/kernel/security/lsm. Si aparece SELinux o Smack y usas NetLabel con una asignación CIPSOV4, esta mitigación no cubre esa ruta.nft. OpenWrt tiene su propia ruta (ver Archivos). Los hosts sin systemd, salvo OpenWrt, no están cubiertos.Gravedad: el CNA del kernel asigna CVSS 9.8. Red Hat, Oracle y SUSE asignan 8.1, y Amazon asigna 7.0. Anthropic describió públicamente un exploit remoto de root contra servidores Linux con un listener MPTCP (2026-10-27). No se reportó explotación en la naturaleza hasta el 2026-10-29.
Estado de las distribuciones a fecha de 2026-10-29/30 (una instantánea, así que consulta a tu proveedor):
| Distribución | Estado |
|---|---|
| Ubuntu (todas las versiones soportadas) | sin kernel corregido |
| RHEL 8/9/10 | sin kernel corregido |
| Proxmox VE | el changelog de pve-kernel no tenía entrada para este CVE el 2026-10-30 |
| Debian, Oracle Linux UEK, algunos SUSE, algunos Amazon Linux | correcciones disponibles |
Ejecuta sudo ./mitigate.sh. Es idempotente (ejecutarlo de nuevo recarga el conjunto de reglas). Instala los archivos listados en Archivos, y termina si no eres root, si falta nft o si falta systemd.
Compara la salida con la referencia de abajo. La primera línea debe ser:
svc=active enabled=enabled mptcp=0
Las dos reglas van a continuación, una en la tabla inet y otra en la tabla bridge.
Si un servicio escucha con MPTCP, reinícialo. net.mptcp.enabled=0 solo afecta a los sockets nuevos, por lo que un listener MPTCP ya abierto sigue siendo MPTCP hasta que se reinicie su servicio. El sysctl es por network namespace, y mitigate.sh lo establece solo para el namespace del host.
Si el host ejecuta contenedores LXC o Docker, continúa con Contenedores.
El exploit publicado se dirigía a listeners MPTCP. La carrera en sí no requiere MPTCP (inferencia a partir de la descripción del fix). No está establecido si un host sin MPTCP puede comprometerse por completo.
El SYN-ACK del objetivo hace eco de las opciones IP. Un cliente que a su vez ejecuta esta mitigación descarta ese SYN-ACK, por lo que check-blocked.py informa "blocked" incluso cuando el objetivo no está mitigado. Medido en un host: tras revert.sh en el objetivo, check-blocked.py desde un cliente mitigado seguía imprimiendo ipopt FAIL TimeoutError, mientras que verify-synack.sh mostraba ipopt synack=5.
Elige una herramienta:
python3 check-blocked.py <host> <port> (no se necesita root). Se conecta dos veces: en plano y luego con una opción IPv4 Record Route establecida mediante la opción de socket IP_OPTIONS.sudo ./verify-synack.sh <ip> <port> en cualquier cliente (se necesitan root, tcpdump y python3 en el cliente). Envía un SYN plano y un SYN con opciones IP desde puertos de origen fijos y cuenta los SYN-ACK del objetivo con tcpdump.Luego compara la salida con la tabla de esa herramienta.
check-blocked.py (desde un cliente sin la mitigación):
| Salida | Significado |
|---|---|
plain CONNECTED | el TCP normal funciona |
ipopt FAIL TimeoutError | el SYN con opciones IP fue descartado, como se pretende |
verify-synack.sh:
| Salida | Significado |
|---|---|
plain: CONNECTED synack=N | ipopt: TimeoutError synack=0 | el objetivo está mitigado |
ipopt ... synack>=1 | el objetivo no está mitigado (se respondió al SYN con opciones IP) |
Resultado a nivel de kernel (un host Proxmox VE, kernel 7.0, 2026-10-30): con la mitigación desactivada, la ruta de código vulnerable se ejecutó una vez por ruta, sobre WireGuard y de LXC a LXC. Con ella activada, el SYN agotó el tiempo de espera y la ruta se ejecutó 0 veces. La muestra es de 2 rutas en 2 estados en un host. El método de trazado está en docs/ANALYSIS.md (en inglés).
El estado de nftables es por network namespace, por lo que las reglas del host por sí solas no protegen los namespaces de los contenedores. Medido en contenedores LXC: con solo las reglas del host, un SYN con opciones IP desde dentro de un contenedor hacia su propio 127.0.0.1 o su propia IP se conectaba. Los contenedores comparten el kernel del host, por lo que el código dentro de cualquier contenedor podría alcanzar la ruta vulnerable de esta manera.
sudo ./inject-netns.sh en el host. Carga el mismo ruleset en cada contenedor LXC en ejecución (mediante pct/lxc-info, Proxmox) y en cada contenedor Docker en ejecución (los contenedores con red del host se omiten).| Salida | Significado |
|---|---|
ok lxc:<id> o ok docker:<id> | ruleset cargado en el namespace de ese contenedor |
injected=N failed=M | totales, M debería ser 0 |
La inyección no es persistente. Se pierde cuando un contenedor se reinicia, así que vuelve a ejecutar el script tras los reinicios. Los contenedores Docker anidados dentro de un contenedor LXC necesitan que el script se ejecute dentro de ese contenedor LXC (no medido).
Resultado medido: en 5 hosts Proxmox, se inyectaron 64 namespaces de contenedores con 0 fallos. Tras la inyección, la misma prueba agotó el tiempo de espera y el contador de descartes del namespace del contenedor aumentó.
El síntoma de que esta mitigación interfiere es una conexión TCP que se cuelga (agota el tiempo de espera) en lugar de ser rechazada, junto con un contador creciente en la salida de:
nft list ruleset | grep counter
| Comando | Efecto |
|---|---|
systemctl stop cve-2026-98432-mitigation | se desactiva de inmediato, vuelve a activarse al reiniciar |
systemctl disable --now cve-2026-98432-mitigation | se desactiva ahora y en todos los reinicios |
Compatibilidad medida en los hosts probados: las reglas residen en sus propias tablas y coexistieron con Docker, ufw, reglas NAT de iptables-legacy y el enrutamiento de NetBird (WireGuard). Las conexiones TCP normales siguieron funcionando en todas las rutas probadas. Los contadores de descarte se mantuvieron en los recuentos de paquetes de prueba durante el funcionamiento normal (ningún tráfico legítimo coincidió) a lo largo de una ventana de observación corta (horas, no días).
Inferencia, no medida: un nftables.service cuya configuración contenga flush ruleset eliminaría las tablas al recargarse. Verifique esto y vuelva a ejecutar mitigate.sh después de dicha recarga.