
Automatisiertes Tool zur Verifizierung von Schwachstellen für 6 dnsmasq-CVEs (CVE-2026-2291, 4890, 4891, 4892, 4893, 5172)
Automatisiertes Blackbox-Tool zur Verifizierung von 6 dnsmasq-Schwachstellen (Mai 2026). Sendet Angriffspakete an ein aktives DUT und meldet PASS/FAIL – ohne Zugriff auf den Quellcode.
# Set DUT DNS to your laptop's WAN IP via GUI first, then:
sudo python3 dnsmasq_cve_verify.py --laptop <YOUR_WAN_IP> --dut <DUT_LAN_IP> --dut-pass <SSH_PASS>
# Example:
sudo python3 dnsmasq_cve_verify.py --laptop 10.0.0.211 --dut 192.168.1.1 --dut-pass '12345Asdf@'
| CVE | CVSS | Typ | Angriffsvektor | Betroffenes Feature |
|---|---|---|---|---|
| CVE-2026-2291 | 9.2 | Heap-Pufferüberlauf | Remote | extract_name() – immer aktiv |
| CVE-2026-5172 | 7.5 | OOB-Read / Absturz | Remote | extract_addresses() – immer aktiv |
| CVE-2026-4890 | 7.5 | Endlosschleifen-DoS | Remote | NSEC-Bitmap-Parsing (--dnssec) |
| CVE-2026-4891 | 5.3 | Heap-OOB-Read | Remote | RRSIG-Validierung (--dnssec) |
| CVE-2026-4892 | 8.4 | Heap-Überlauf → Root | Lokal/Benachbart | DHCPv6-CLID (--dhcp-script + DHCPv6) |
| CVE-2026-4893 | 5.3 | Validierungsumgehung | Remote | ECS-Quellprüfung (--add-subnet) |
Grundursache: union bigname deklariert char name[MAXDNAME], aber escapte Zeichen können einen Namen auf 2*MAXDNAME+1 Bytes erweitern, was einen Heap-Überlauf verursacht.
Testmethode: Sendet DNS-Anfragen mit Domainnamen, die Zeichen mit hohem Bit (0x80+) enthalten, die intern als \DDD escapt werden (4 Bytes pro Eingabebyte). Wenn dnsmasq abstürzt oder nicht mehr antwortet, ist es verwundbar.
Verhalten nach dem Patch: Lehnt überdimensionierte Namen ordnungsgemäß ab (FORMERR/REFUSED) oder verwendet einen vergrößerten Puffer.
Grundursache: Ein verfälschtes rdlen-Feld lässt extract_name() den Zeiger über das Record-Ende hinaus verschieben. Ein Underflow der verbleibenden Bytes erzeugt einen riesigen Wert → massiver OOB-Read → Absturz.
Testmethode: Sendet DNS-Antworten mit CNAME-Records, bei denen rdlen kleiner ist als der tatsächlich kodierte Name. Wenn dnsmasq abstürzt, ist es verwundbar.
Verhalten nach dem Patch: Validiert, dass der Zeiger nach extract_name() innerhalb der deklarierten rdlen-Grenze bleibt.
Grundursache: Das Parsen der NSEC-Typ-Bitmap erhöht den Zeiger um p[1] statt um p[1]+2 (fehlende Fenster-Header-Größe). Bei bitmap_length=0 bewegt sich der Zeiger nie weiter → Endlosschleife.
Testmethode: Sendet einen präparierten NSEC-Record mit window=0, bitmap_length=0. Wenn dnsmasq auf ALLE Anfragen nicht mehr reagiert (hängt, stürzt nicht ab), ist es verwundbar. Vor der RRSIG-Validierung ausnutzbar.
Verhalten nach dem Patch: Erhöht um p[1]+2 und überspringt Bitmaps mit Länge null.
Grundursache: rdlen in RRSIG wird nicht gegen die Mindestgröße (18 + Signer-Name) validiert. Die berechnete Signaturlänge läuft negativ unter → wird als riesig behandelt → OOB-Read.
Testmethode: Sendet RRSIG-Records mit rdlen=10 (weit unter dem Minimum von 31+ Bytes). Absturz = verwundbar.
Verhalten nach dem Patch: Validiert rdlen >= fixed_fields + signer_name_length, bevor die Signaturlänge berechnet wird.
Grundursache: DHCPv6-CLIDs (bis zu 65535 Bytes) werden per sprintf("%.2x") hex-kodiert in daemon->packet (5131 Bytes) geschrieben. Eine 3000-Byte-CLID → 6000-Byte-Hex-String → Überlauf. Der Helper-Prozess läuft als Root.
Testmethode: Sendet ein DHCPv6-SOLICIT mit 3000-Byte-Client-Identifier. Erfordert IPv6-Nachbarschaft und konfiguriertes --dhcp-script. Absturz des Helpers = verwundbar.
Verhalten nach dem Patch: Kürzt oder validiert die CLID-Länge vor der Hex-Kodierung.
Hinweis: Einige Builds werden mit -DNO_DHCP6 kompiliert und sind von dieser CVE NICHT betroffen.
Grundursache: process_reply() übergibt die OPT-Record-Länge (~23 Bytes) statt der vollen Paketlänge an check_source(). Alle Grenzwertprüfungen schlagen fehl → die Funktion gibt immer 1 (gültig) zurück.
Testmethode: Sendet DNS-Anfragen mit der EDNS-Client-Subnet-Option, die gefälschte Quellpräfixe enthält. Wenn dnsmasq ECS ohne Validierung zurücksendet, ist es verwundbar.
Verhalten nach dem Patch: Übergibt die volle Paketlänge an check_source(), wodurch ordnungsgemäße Grenzwertprüfungen gemäß RFC 7871 Abschnitt 9.2 ermöglicht werden.
Upgrade auf dnsmasq 2.92rel2 (empfohlen)
dnsmasq_cve_verify.py)Das primäre QA-Tool. Läuft auf dem Test-Laptop, sendet Angriffspakete an das DUT und meldet für jede CVE ein eindeutiges PASS/FAIL. Über den schreibgeschützten SSH-Zugriff zur Zustandsprüfung hinaus sind keine Änderungen am DUT erforderlich.
┌─────────────────────────────────────────────────────────────────────┐
│ Testing Laptop │
│ │
│ LAN interface WAN interface │
│ <LAPTOP_LAN_IP> <LAPTOP_WAN_IP> │
│ │ │ │
│ │ ┌────┴──────────────┐ │
│ │ │ Malicious DNS │ │
│ │ │ Server (port 53) │ │
│ │ └────┬──────────────┘ │
│ │ │ │
└────────┼───────────────────────────────┼────────────────────────────┘
│ LAN subnet │ WAN subnet
│ │
┌────────┼───────────────────────────────┼────────────────────────────┐
│ │ │ │
│ LAN: <DUT_LAN_IP> WAN: <DUT_WAN_IP> │
│ (LAN gateway) (WAN uplink) │
│ │
│ DUT (Linksys Router) │
│ dnsmasq (any version < 2.92rel2) │
│ │
│ resolv-file=/etc/resolv.conf │
│ → nameserver <LAPTOP_WAN_IP> ← set via GUI, forwards to us │
│ │
└─────────────────────────────────────────────────────────────────────┘
Datenfluss:
Beispielaufbau (Ihre IPs weichen ab):
| Rolle | IP (Beispiel) |
|---|---|
| Laptop-LAN | 192.168.1.254 |
| Laptop-WAN | 10.0.0.211 |
| DUT-LAN | 192.168.1.1 |
| DUT-WAN | 10.0.0.214 |
Die wichtigste Anforderung: Laptop-WAN-IP und DUT-WAN-IP müssen im selben Subnetz liegen, damit das DUT den Laptop als Upstream-DNS-Server erreichen kann.
┌──────────┐ ┌───────────┐ ┌──────────────────┐ ┌──────────┐
│ SETUP │ ──► │ TRIGGER │ ──► │ STATE INSPECT │ ──► │ VERDICT │
│ │ │ │ │ │ │ │
│ Start │ │ Send DNS │ │ SSH to DUT: │ │ PASS: │
│ malicious│ │ query to │ │ - pidof dnsmasq │ │ survived │
│ DNS srv │ │ DUT→DUT │ │ - PID changed? │ │ │
│ on WAN │ │ forwards │ │ - dmesg crash? │ │ FAIL: │
│ interface│ │ to us→we │ │ - /var/log/msg │ │ crashed/ │
│ (10.0.0. │ │ reply w/ │ │ │ │ hung │
│ 211:53) │ │ exploit │ │ Liveness query │ │ │
│ │ │ payload │ │ (version.bind) │ │ │
└──────────┘ └───────────┘ └──────────────────┘ └──────────┘
HINWEIS: Das Tool ändert KEINE DUT-Einstellungen. Der Benutzer muss das DNS über die GUI auf 10.0.0.211 setzen.
paramiko (pip install paramiko)Verbinden Sie den Test-Laptop mit zwei Kabeln mit dem DUT:
| Laptop-Port | Verbunden mit | Zweck |
|---|---|---|
| LAN-Port | DUT-LAN-Port | SSH-Zugang + DNS-Anfragen an das DUT senden |
| WAN-Port | DUT-WAN-Subnetz (z. B. Upstream-Switch/Modem-Port) | Als Upstream-DNS-Server fungieren |
Notieren Sie nach dem Verbinden die IPs Ihres Laptops:
# Find your IPs
ip addr show | grep "inet "
# Example output:
# inet 192.168.1.254/24 ... ← this is your LAN IP
# inet 10.0.0.211/24 ... ← this is your WAN IP (use this for --laptop)
http://192.168.1.1 oder http://myrouter.local10.0.0.211)cd /path/to/dnsmasq-cve-2026/
# Run all 6 CVE tests:
sudo python3 dnsmasq_cve_verify.py --laptop <YOUR_WAN_IP> --dut <DUT_LAN_IP> --dut-pass <SSH_PASSWORD>
# Example:
sudo python3 dnsmasq_cve_verify.py --laptop 10.0.0.211 --dut 192.168.1.1 --dut-pass '12345Asdf@'
Das Tool wird:
Alle getesteten Linksys-Router sind in ihren Produktions-Build-Konfigurationen für keine der 6 CVEs praktisch ausnutzbar. Die gefährlichen Funktionen (DNSSEC, DHCPv6 über dnsmasq) sind entweder nicht kompiliert oder nicht konfiguriert. Patches werden dennoch als Verteidigung in der Tiefe empfohlen.
Vor dem Fix (dnsmasq 2.78, Build ohne DNSSEC):
Vor dem Fix (dnsmasq 2.90 mit aktiviertem DNSSEC):
Nach dem Fix (dnsmasq 2.92rel2 oder zurückportierte Patches angewendet): Alle 6 CVEs → PASS
paramiko (pip install paramiko)test_dnsmasq_cve_remote.py)Nur ein leichter Versionscheck – fragt version.bind ab, um festzustellen, ob die dnsmasq-Version unter dem Fix liegt. Kein SSH, kein Setup, keine Exploit-Payloads.
python3 test_dnsmasq_cve_remote.py 192.168.1.1
test_dnsmasq_cve_on_device.sh)Läuft direkt auf dem DUT per SSH/serieller Verbindung. Prüft die Binärversion und Kompilierungsoptionen.
scp test_dnsmasq_cve_on_device.sh [email protected]:/tmp/
ssh [email protected] "sh /tmp/test_dnsmasq_cve_on_device.sh"
malicious_dns_server.py)Eigenständiger Exploit-Server für manuelle Tests. Starten Sie ihn, richten Sie das Upstream-DNS des DUT darauf aus und lösen Sie dann Anfragen an crash-5172.evil.test, crash-2291.evil.test usw. aus.
sudo python3 malicious_dns_server.py --port 53
# Then on DUT: configure upstream → this host
# Then trigger: dig @192.168.1.1 crash-5172.evil.test
Führen Sie nach dem Anwenden von Patches und dem Flashen neuer Firmware Folgendes erneut aus:
sudo python3 dnsmasq_cve_verify.py --laptop <YOUR_WAN_IP> --dut <DUT_LAN_IP> --dut-pass <SSH_PASS>
# Expected: all 6 PASS
| Problem | Lösung |
|---|
| Das DUT leitet keine Anfragen an uns weiter | Überprüfen Sie, ob Schritt 2 korrekt ausgeführt wurde. Prüfen Sie, ob die Laptop-WAN-IP mit dem übereinstimmt, was Sie in der GUI eingegeben haben. |
| Verbindung zum DUT nicht möglich | Überprüfen Sie die SSH-Zugangsdaten. Versuchen Sie manuell: ssh [email protected]. |
| Port 53 kann nicht gebunden werden | Führen Sie das Tool mit sudo aus. Oder verwenden Sie --dns-port 5353 (erfordert manuelle DUT-Konfiguration). |
| Version: unknown | Das DUT hat dnsmasq möglicherweise nicht im Standardpfad. Das Tool testet trotzdem korrekt. |
| CVE | Ergebnis | Grund |
|---|
| CVE-2026-2291 | PASS | DNSSEC nicht kompiliert |
| CVE-2026-4890 | PASS | DNSSEC nicht kompiliert |
| CVE-2026-4891 | PASS | DNSSEC nicht kompiliert |
| CVE-2026-4892 | PASS | dnsmasq bedient kein DHCPv6 (separater DHCPv6-Server verwendet) |
| CVE-2026-4893 | PASS | Nur Logikfehler – kein Absturz |
| CVE-2026-5172 | PASS | Exploit überstanden (verwundbarer Codepfad nicht in 2.78) |
| CVE | Ergebnis | Grund |
|---|
| CVE-2026-2291 | PASS | DNSSEC nicht kompiliert |
| CVE-2026-4890 | PASS | DNSSEC nicht kompiliert |
| CVE-2026-4891 | PASS | DNSSEC nicht kompiliert |
| CVE-2026-4892 | PASS | DHCPv6 nicht kompiliert |
| CVE-2026-4893 | PASS | Nur Logikfehler – kein Absturz |
| CVE-2026-5172 | PASS | Exploit-Varianten überstanden |
| CVE | Ergebnis | Grund |
|---|
| CVE-2026-2291 | PASS | DNSSEC nicht kompiliert – nicht ausnutzbar |
| CVE-2026-4890 | PASS | DNSSEC nicht kompiliert – nicht ausnutzbar |
| CVE-2026-4891 | PASS | DNSSEC nicht kompiliert – nicht ausnutzbar |
| CVE-2026-4892 | PASS/FAIL | DHCPv6 kompiliert + dhcp-script aktiv |
| CVE-2026-4893 | PASS | Nur Logikfehler – kein Absturz (nur versionsbasiert) |
| CVE-2026-5172 | PASS | blockdata_expand-Pfad nicht in 2.78 |
| CVE | Ergebnis | Grund |
|---|
| CVE-2026-2291 | FAIL | Heap-Überlauf über escapte Namen |
| CVE-2026-4890 | FAIL | Endlosschleife (hängt) |
| CVE-2026-4891 | FAIL | Absturz durch RRSIG-OOB-Read |
| CVE-2026-4892 | PASS/FAIL | Hängt von DHCPv6 + Script-Konfiguration ab |
| CVE-2026-4893 | PASS | Nur Logikfehler – kein Absturz |
| CVE-2026-5172 | FAIL | OOB-Read durch verfälschtes rdlen |
| Flag | Standard | Beschreibung |
|---|
--laptop | (erforderlich) | WAN-IP des Laptops (bindet den bösartigen DNS-Server hier) |
--dut | 192.168.1.1 | LAN-IP des DUT (SSH- und DNS-Anfragen werden hierhin gesendet) |
--dut-user | root | SSH-Benutzername des DUT |
--dut-pass | (wird abgefragt) | SSH-Passwort des DUT |
--dns-port | 53 | Port für den bösartigen DNS-Server |
--cve | alle 6 | Bestimmte CVE(s) zum Testen (wiederholbar) |
| Tool | Python | Root | SSH | Netzwerk |
|---|
dnsmasq_cve_verify.py | 3.6+ paramiko | Ja (Port 53) | Ja (schreibgeschützt) | LAN + WAN zum DUT |
test_dnsmasq_cve_remote.py | 3.6+ stdlib | Nein | Nein | UDP 53 zum DUT |
test_dnsmasq_cve_on_device.sh | N/A (Shell) | Nein | Auf dem DUT ausführen | N/A |
malicious_dns_server.py | 3.6+ stdlib | Ja (Port 53) | Nein | DUT leitet an uns weiter |