
Guia e script de verificação somente leitura para CVE-2026-98432, um use-after-free no TCP IPv4 do Linux: detecta o status do patch do kernel, aplica uma solução paliativa via iptables e verifica após a correção.
Atacável pela rede, sem login e sem ação do usuário. O bug está no código do kernel que trata cada conexão TCP IPv4 recebida.
Este guia mostra como verificar um servidor, protegê-lo até que um kernel corrigido esteja disponível e fazer a limpeza depois. Os comandos abaixo foram usados em servidores Ubuntu 22.04 e 24.04.
O status neste documento é de 2026-10-30. O status dos patches muda rapidamente, então sempre verifique o rastreador de segurança da sua própria distribuição.
e3f33b0a1d89Em palavras simples: uma solicitação de conexão (SYN) pode carregar opções IPv4, extras raramente usados no cabeçalho do pacote, como Record Route ou Timestamp. Quando uma chega, o kernel mantém uma cópia dessas opções. Se o atacante reenviar o SYN no momento exato, uma CPU pode liberar essa cópia enquanto outra ainda a está usando para montar a resposta. Isso é um use-after-free em ip_options_build(), e pode derrubar o servidor ou corromper a memória do kernel.
Existe um segundo gatilho quando o servidor migra solicitações de conexão pendentes entre sockets (net.ipv4.tcp_migrate_req=1, ou um programa BPF_SK_REUSEPORT_SELECT_OR_MIGRATE). Essa configuração está desativada por padrão.
| Prioridade do Ubuntu | Alta |
| CVSS, CNA do kernel | 9.8 Crítico: rede, sem autenticação, sem interação do usuário |
| CVSS, Red Hat | 8.1, porque a Red Hat considera a corrida mais difícil de acertar |
| Afetados | Kernels desde 4.4 |
| IPv6 | Não afetado pelo problema principal |
| Exploração | Nenhuma relatada na natureza, e não está no catálogo CISA KEV. Um exploit remoto de root contra servidores com um listener de multipath TCP (MPTCP) foi relatado, mas não publicado. |
Quem está exposto: qualquer servidor com uma porta TCP acessível via IPv4, seja SSH, HTTP, HTTPS ou qualquer outra coisa.
| Distribuição | Status | Corrigido em |
|---|---|---|
| Kernel upstream | ✅ Corrigido | 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3 |
| Debian 12 / 13 | ✅ Corrigido | 6.1.190-1 (ou linux-6.12 6.12.113-1~deb12u1) / 6.12.113-1 |
| Ubuntu 26.10 / 26.04 / 24.04 / 22.04 | ❌ Correção em andamento, não lançada | Planejado: 7.3.0-10.10 / 7.0.0-43.43 / 6.8.0-149.149 / 5.15.0-203.213 |
| Ubuntu 20.04 / 18.04 / 16.04 | ❌ Vulnerável | Apenas via Ubuntu Pro (ESM), se tanto |
| RHEL 8 / 9 / 10 | ❌ Relatado como "correção adiada" | Nenhum |
| Oracle Linux (UEK) | ✅ Corrigido | ELSA-2026-500397 / 500398 / 500399 |
| Amazon Linux 2023 | ⚠️ Parcialmente corrigido | kernel6.18 e kernel6.12 corrigidos; kernel padrão e AL2 pendentes |
| SUSE | ⚠️ Parcialmente corrigido | openSUSE Leap 16.0 corrigido; SLES em andamento |
Os kernels de nuvem do Ubuntu (-aws, -azure, -gcp, -oracle) têm seus próprios números de versão. Os kernels das distribuições fazem backport das correções, então não compare uma versão de distro como 5.15.0-xxx com os números upstream.
Isto apenas lê e informa. Não instala, altera nem reinicia nada. Cole em um terminal no servidor:
sudo bash -s <<'EOF'
CVE=CVE-2026-98432; FIX="free inet_opt and ireq_opt"; KR=$(uname -r)
. /etc/os-release
echo "== $PRETTY_NAME | running kernel: $KR"; echo " build: $(uname -v)"
echo "== Installed kernels (if one is newer than the running kernel, you need a reboot)"
ls -1v /boot/vmlinuz-* 2>/dev/null | sed 's|/boot/vmlinuz-| |'
[ -f /var/run/reboot-required ] && echo " !! reboot required"
echo "== Is the fix in the RUNNING kernel's changelog?"
if command -v dpkg >/dev/null; then
dpkg-query -W -f=' package version: ${Version}\n' "linux-image-$KR" 2>/dev/null
zgrep -Eqs "$CVE|$FIX" /usr/share/doc/linux-*"$KR"*/changelog.Debian.gz \
&& echo " PATCHED" || echo " NOT FOUND -> likely VULNERABLE"
command -v pro >/dev/null && pro fix "$CVE" --dry-run </dev/null
elif command -v rpm >/dev/null; then
PKG=$(rpm -qf "/lib/modules/$KR/vmlinuz" "/usr/lib/modules/$KR/vmlinuz" "/boot/vmlinuz-$KR" 2>/dev/null | grep -v 'not owned' | head -1)
echo " package: ${PKG:-unknown}"
rpm -q --changelog "$PKG" 2>/dev/null | grep -Eq "$CVE|$FIX" \
&& echo " PATCHED" || echo " NOT FOUND -> likely VULNERABLE"
if command -v zypper >/dev/null; then zypper -n -q lp -a --cve="$CVE" </dev/null
elif command -v dnf >/dev/null; then dnf -q updateinfo list --all --cve="$CVE" </dev/null
elif command -v yum >/dev/null; then yum -q updateinfo list --cve="$CVE" </dev/null; fi
fi
echo "== Exposure"
sysctl net.mptcp.enabled net.ipv4.tcp_migrate_req 2>/dev/null | sed 's/^/ /'
M=$(ss -lnMH 2>/dev/null); echo " MPTCP listeners (reported root-exploit path): ${M:-none}"
echo " TCP listeners not on loopback (attack surface):"
ss -ltnH | awk '$4 !~ /^(127\.|\[::1\])/ {print " "$4}' | sort -u
EOF
Cole tudo de uma vez: o EOF final deve estar em sua própria linha, sem espaços à esquerda.
Lendo a saída:
| O que você vê | Significado | Próximo passo |
|---|---|---|
PATCHED | O kernel em execução já tem a correção | Você terminou |
NOT FOUND -> likely VULNERABLE | Não há correção no kernel em execução | Passo 2 |
!! reboot required, ou um kernel mais novo que o em execução está listado | Um kernel mais novo está instalado, mas ainda não está em execução | Passo 3 |
A fix is coming soon (Ubuntu) | O Ubuntu ainda não lançou a correção | Passo 2 agora, Passo 5 depois |
MPTCP listeners: none | O caminho de exploração de root relatado não se aplica no momento | — |
Uma porta de banco de dados ou cache, como *:3306, 0.0.0.0:6379 ou 0.0.0.0:11211 | Ela escuta em todas as interfaces | Certifique-se de que o firewall a bloqueie (veja o final do Passo 4) |
A regra abaixo descarta pacotes TCP IPv4 que carregam opções IP, que é o que um atacante precisa para acionar a falha. Clientes normais (navegadores, SSH, celulares, APIs, balanceadores de carga) nunca enviam opções IP, então o tráfego real não é afetado.
Primeiro verifique qual ferramenta de firewall o servidor usa:
systemctl is-active ufw nftables firewalld
Se nftables ou firewalld estiver active, recarregar esse firewall pode apagar esta regra. Use a variante nftables no final deste passo, ou adapte-a à sua configuração.
Instale a solução provisória. É uma pequena unit systemd, para que a regra volte após cada reinicialização:
sudo tee /etc/systemd/system/cve-2026-98432.service >/dev/null <<'EOF'
[Unit]
Description=Stopgap for CVE-2026-98432: drop IPv4 TCP packets carrying IP options
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/iptables -t raw -I PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" -m comment --comment CVE-2026-98432 -j DROP
ExecStop=/usr/sbin/iptables -t raw -D PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" -m comment --comment CVE-2026-98432 -j DROP
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload && sudo systemctl enable --now cve-2026-98432
sudo iptables -t raw -L PREROUTING -v -n
O último comando deve listar uma regra DROP com o comentário CVE-2026-98432. A coluna pkts conta os pacotes que ela bloqueou; deve permanecer em 0 ou próximo disso.
O teste u32 0>>24&0xF=6:15 lê o campo de comprimento do cabeçalho IPv4. Um cabeçalho normal tem 5 × 4 = 20 bytes. Qualquer valor maior significa que opções estão anexadas, e esse pacote é descartado. A regra fica na tabela raw, que o ufw não gerencia, portanto suas regras de firewall existentes permanecem intactas.