
Ferramenta automatizada de verificação de defeitos para 6 CVEs do dnsmasq (CVE-2026-2291, 4890, 4891, 4892, 4893, 5172)
Ferramenta automatizada de caixa-preta para verificar 6 vulnerabilidades do dnsmasq (maio de 2026). Envia pacotes de ataque para um DUT ativo e reporta PASS/FAIL — sem necessidade de acesso ao código-fonte.
# Defina o DNS do DUT para o IP WAN do seu laptop via GUI primeiro, depois:
sudo python3 dnsmasq_cve_verify.py --laptop <YOUR_WAN_IP> --dut <DUT_LAN_IP> --dut-pass <SSH_PASS>
# Exemplo:
sudo python3 dnsmasq_cve_verify.py --laptop 10.0.0.211 --dut 192.168.1.1 --dut-pass '12345Asdf@'
| CVE | CVSS | Tipo | Vetor de Ataque | Recurso Afetado |
|---|---|---|---|---|
| CVE-2026-2291 | 9.2 | Estouro de buffer no heap | Remoto | extract_name() — sempre ativo |
| CVE-2026-5172 | 7.5 | Leitura fora dos limites / falha | Remoto | extract_addresses() — sempre ativo |
| CVE-2026-4890 | 7.5 | DoS por loop infinito | Remoto | Parsing de bitmap NSEC (--dnssec) |
| CVE-2026-4891 | 5.3 | Leitura fora dos limites no heap | Remoto | Validação RRSIG (--dnssec) |
| CVE-2026-4892 | 8.4 | Estouro de heap → root | Local/Adjacente | CLID DHCPv6 (--dhcp-script + DHCPv6) |
| CVE-2026-4893 | 5.3 | Bypass de validação | Remoto | Verificação de origem ECS (--add-subnet) |
Causa raiz: union bigname declara char name[MAXDNAME], mas caracteres de escape podem expandir um nome para 2*MAXDNAME+1 bytes, causando estouro de heap.
Método de teste: Envia consultas DNS contendo nomes de domínio com caracteres de bit alto (0x80+) que são escapados internamente como \DDD (4 bytes por byte de entrada). Se o dnsmasq falhar ou parar de responder, está vulnerável.
Comportamento corrigido: Rejeita nomes superdimensionados de forma graciosa (FORMERR/REFUSED) ou usa um buffer ampliado.
Causa raiz: Um campo rdlen falsificado permite que extract_name() avance o ponteiro além do fim do registro. O underflow dos bytes restantes produz um valor enorme → leitura fora dos limites massiva → falha.
Método de teste: Envia respostas DNS com registros CNAME onde rdlen é menor que o nome realmente codificado. Se o dnsmasq falhar, está vulnerável.
Comportamento corrigido: Valida que o ponteiro permaneça dentro do limite declarado de rdlen após extract_name().
Causa raiz: O parsing do bitmap de tipos NSEC avança por p[1] em vez de p[1]+2 (falta o tamanho do cabeçalho da janela). Com bitmap_length=0, o ponteiro nunca avança → loop infinito.
Método de teste: Envia um registro NSEC malicioso com window=0, bitmap_length=0. Se o dnsmasq parar de responder a TODAS as consultas (trava, não falha), está vulnerável. Explorável ANTES da validação RRSIG.
Comportamento corrigido: Avança por p[1]+2 e ignora bitmaps de comprimento zero.
Causa raiz: rdlen em RRSIG não é validado contra o tamanho mínimo (18 + nome do assinante). O comprimento calculado da assinatura sofre underflow para negativo → tratado como enorme → leitura fora dos limites.
Método de teste: Envia registros RRSIG com rdlen=10 (muito abaixo do mínimo de 31+ bytes). Falha = vulnerável.
Comportamento corrigido: Valida rdlen >= fixed_fields + signer_name_length antes de calcular o comprimento da assinatura.
Causa raiz: CLIDs DHCPv6 (até 65535 bytes) são codificados em hexadecimal via sprintf("%.2x") em daemon->packet (5131 bytes). CLID de 3000 bytes → string hex de 6000 bytes → estouro. O processo auxiliar é executado como root.
Método de teste: Envia DHCPv6 SOLICIT com Client Identifier de 3000 bytes. Requer adjacência IPv6 e --dhcp-script configurado. Falha do auxiliar = vulnerável.
Comportamento corrigido: Trunca ou valida o comprimento do CLID antes da codificação hexadecimal.
Nota: Alguns builds são compilados com -DNO_DHCP6 e NÃO são afetados por este CVE.
Causa raiz: process_reply() passa o comprimento do registro OPT (~23 bytes) em vez do comprimento total do pacote para check_source(). Todas as verificações de limites falham → a função sempre retorna 1 (válido).
Método de teste: Envia consultas DNS com a opção EDNS Client Subnet contendo prefixos de origem falsificados. Se o dnsmasq devolver o ECS sem validação, está vulnerável.
Comportamento corrigido: Passa o comprimento total do pacote para check_source(), permitindo verificações de limites adequadas conforme a RFC 7871, Seção 9.2.
Atualize para dnsmasq 2.92rel2 (recomendado)
dnsmasq_cve_verify.py)A principal ferramenta de QA. É executada no laptop de teste, envia pacotes de ataque ao DUT e reporta PASS/FAIL claro para cada CVE. Nenhuma modificação do DUT é necessária além de acesso SSH somente leitura para inspeção de estado.
┌─────────────────────────────────────────────────────────────────────┐
│ Laptop de Teste │
│ │
│ Interface LAN Interface WAN │
│ <LAPTOP_LAN_IP> <LAPTOP_WAN_IP> │
│ │ │ │
│ │ ┌────┴──────────────┐ │
│ │ │ Servidor DNS │ │
│ │ │ Malicioso (porta 53)│ │
│ │ └────┬──────────────┘ │
│ │ │ │
└────────┼───────────────────────────────┼────────────────────────────┘
│ Sub-rede LAN │ Sub-rede WAN
│ │
┌────────┼───────────────────────────────┼────────────────────────────┐
│ │ │ │
│ LAN: <DUT_LAN_IP> WAN: <DUT_WAN_IP> │
│ (gateway LAN) (uplink WAN) │
│ │
│ DUT (Roteador Linksys) │
│ dnsmasq (qualquer versão < 2.92rel2) │
│ │
│ resolv-file=/etc/resolv.conf │
│ → nameserver <LAPTOP_WAN_IP> ← definido via GUI, encaminha para nós │
│ │
└─────────────────────────────────────────────────────────────────────┘
Fluxo de dados:
1. A ferramenta envia consulta DNS ao IP LAN do DUT (porta 53)
2. O dnsmasq do DUT não consegue resolver localmente → encaminha para LAPTOP_WAN_IP
3. Nosso servidor malicioso na interface WAN responde com o payload de exploração
4. O dnsmasq do DUT processa a resposta maliciosa → falha/trava/sobrevive
5. A ferramenta verifica o estado do DUT via SSH (somente leitura)
Exemplo de configuração (seus IPs serão diferentes):
| Papel | IP (exemplo) |
|---|---|
| LAN do laptop | 192.168.1.254 |
| WAN do laptop | 10.0.0.211 |
| LAN do DUT | 192.168.1.1 |
| WAN do DUT | 10.0.0.214 |