JianrongXiao-Linksys/dnsmasq-cve-2026

GitHub: JianrongXiao-Linksys/dnsmasq-cve-2026

dnsmasq漏洞自动化验证工具

Stars: 0 | Forks: 0

# dnsmasq CVE-2026 QA 验证工具 用于验证 6 个 dnsmasq 漏洞(2026 年 5 月)的自动化黑盒工具。 向实时 DUT 发送攻击数据包并报告 PASS/FAIL — 无需访问源代码。 ## 快速开始 ``` # 设置 DUT DNS 为笔记本电脑的 WAN IP,首先通过 GUI 进行,然后: sudo python3 dnsmasq_cve_verify.py --laptop --dut --dut-pass # 示例: sudo python3 dnsmasq_cve_verify.py --laptop 10.0.0.211 --dut 192.168.1.1 --dut-pass '12345Asdf@' ``` ## 测试的 CVE | CVE | CVSS | 类型 | 攻击向量 | 受影响功能 | |-----|------|------|---------------|-----------------| | CVE-2026-2291 | 9.2 | 堆缓冲区溢出 | 远程 | `extract_name()` — 总是激活 | | CVE-2026-5172 | 7.5 | OOB 读取 / 崩溃 | 远程 | `extract_addresses()` — 总是激活 | | CVE-2026-4890 | 7.5 | 无限循环 DoS | 远程 | NSEC 位图解析 (`--dnssec`) | | CVE-2026-4891 | 5.3 | 堆 OOB 读取 | 远程 | RRSIG 验证 (`--dnssec`) | | CVE-2026-4892 | 8.4 | 堆溢出 → root | 本地/相邻 | DHCPv6 CLID (`--dhcp-script` + DHCPv6) | | CVE-2026-4893 | 5.3 | 验证绕过 | 远程 | ECS 源检查 (`--add-subnet`) | ## 每个测试如何工作 ### CVE-2026-2291(关键 — extract_name 中的堆溢出) **根本原因:** `union bigname` 声明 `char name[MAXDNAME]`,但转义字符可以将名称扩展到 `2*MAXDNAME+1` 字节,导致堆溢出。 **测试方法:** 发送包含具有高位字符(0x80+)的域名 DNS 查询,这些域名在内部被 `\DDD` 转义(每输入字节 4 字节)。如果 dnsmasq 崩溃或停止响应,则表示存在漏洞。 **修复后的行为:** 优雅地拒绝过大的名称(FORMERR/REFUSED)或使用扩大的缓冲区。 ### CVE-2026-5172(高 — extract_addresses 中的 OOB 读取) **根本原因:** 伪造的 `rdlen` 字段让 `extract_name()` 指针超出记录末尾。剩余字节数下溢产生巨大值 → 巨大的 OOB 读取 → 崩溃。 **测试方法:** 发送具有 `rdlen` 小于实际编码名称的 CNAME 记录的 DNS 响应。如果 dnsmasq 崩溃,则表示存在漏洞。 **修复后的行为:** 确保 `extract_name()` 之后指针保持在声明的 rdlen 边界内。 ### CVE-2026-4890(高 — DNSSEC NSEC 无限循环) **根本原因:** NSEC 类型位图解析通过 `p[1]` 而不是 `p[1]+2`(缺少窗口头大小)。`bitmap_length=0` 时,指针永远不会前进 → 无限循环。 **测试方法:** 发送具有 `window=0, bitmap_length=0` 的定制 NSEC 记录。如果 dnsmasq 停止响应所有查询(挂起,而不是崩溃),则表示存在漏洞。在 RRSIG 验证之前可利用。 **修复后的行为:** 通过 `p[1]+2` 前进并跳过零长度位图。 ### CVE-2026-4891(中 — RRSIG 堆 OOB 读取) **根本原因:** RRSIG 中的 `rdlen` 未与最小大小(18 + 签名者名称)进行验证。计算的签名长度下溢为负 → 被视为巨大值 → OOB 读取。 **测试方法:** 发送具有 `rdlen=10`(远低于最小 31+ 字节)的 RRSIG 记录。崩溃 = 漏洞。 **修复后的行为:** 在计算签名长度之前验证 `rdlen >= fixed_fields + signer_name_length`。 ### CVE-2026-4892(高 — DHCPv6 CLID 本地 root) **根本原因:** DHCPv6 CLIDs(最多 65535 字节)通过 `sprintf("%.2x")` 转换为 `daemon->packet`(5131 字节)。3000 字节 CLID → 6000 字节十六进制字符串 → 溢出。辅助进程以 root 运行。 **测试方法:** 发送具有 3000 字节客户端标识符的 DHCPv6 SOLICIT。需要 IPv6 相邻性和配置的 `--dhcp-script`。辅助进程崩溃 = 漏洞。 **修复后的行为:** 在十六进制编码之前截断或验证 CLID 长度。 **注意:** 一些构建使用 `-DNO_DHCP6` 编译,不受此 CVE 影响。 ### CVE-2026-4893(中 — ECS 源验证绕过) **根本原因:** `process_reply()` 将 OPT 记录长度(约 23 字节)传递给 `check_source()`,而不是完整的数据包长度。所有边界检查失败 → 函数始终返回 1(有效)。 **测试方法:** 发送包含欺骗源前缀的 EDNS 客户端子网选项的 DNS 查询。如果 dnsmasq 不验证地回显 ECS,则表示存在漏洞。 **修复后的行为:** 将完整数据包长度传递给 `check_source()`,启用根据 RFC 7871 第 9.2 节进行适当的边界检查。 ## 补救措施 **升级到 dnsmasq 2.92rel2**(推荐) - 源:https://thekelleys.org.uk/dnsmasq/dnsmasq-2.92rel2.tar.xz - 上游补丁:https://thekelleys.org.uk/dnsmasq/CVE/ ## 自动化缺陷验证工具 (`dnsmasq_cve_verify.py`) 主要的 QA 工具。在 **测试笔记本电脑** 上运行,向 DUT 发送攻击数据包, 并对每个 CVE 报告清晰的 PASS/FAIL。无需对 DUT 进行任何修改,只需 用于状态检查的只读 SSH 访问。 ### 网络拓扑 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ Testing Laptop │ │ │ │ LAN interface WAN interface │ │ │ │ │ │ │ │ │ ┌────┴──────────────┐ │ │ │ │ Malicious DNS │ │ │ │ │ Server (port 53) │ │ │ │ └────┬──────────────┘ │ │ │ │ │ └────────┼───────────────────────────────┼────────────────────────────┘ │ LAN subnet │ WAN subnet │ │ ┌────────┼───────────────────────────────┼────────────────────────────┐ │ │ │ │ │ LAN: WAN: │ │ (LAN gateway) (WAN uplink) │ │ │ │ DUT (Linksys Router) │ │ dnsmasq (any version < 2.92rel2) │ │ │ │ resolv-file=/etc/resolv.conf │ │ → nameserver ← set via GUI, forwards to us │ │ │ └─────────────────────────────────────────────────────────────────────┘ Data flow: 1. Tool sends DNS query to DUT LAN IP (port 53) 2. DUT's dnsmasq can't resolve locally → forwards upstream to LAPTOP_WAN_IP 3. Our malicious server on WAN interface replies with exploit payload 4. DUT's dnsmasq processes the malicious response → crash/hang/survive 5. Tool checks DUT state via SSH (read-only) ``` **示例设置(您的 IP 地址将不同):** | 角色 | IP(示例) | |------|--------------| | 笔记本电脑 LAN | 192.168.1.254 | | 笔记本电脑 WAN | 10.0.0.211 | | DUT LAN | 192.168.1.1 | | DUT WAN | 10.0.0.214 | 关键要求:**笔记本电脑 WAN IP 和 DUT WAN IP 必须在同一个子网中**, 因此 DUT 可以作为上游 DNS 服务器到达笔记本电脑。 ### 它是如何工作的 ``` ┌──────────┐ ┌───────────┐ ┌──────────────────┐ ┌──────────┐ │ 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) │ │ │ └──────────┘ └───────────┘ └──────────────────┘ └──────────┘ NOTE: Tool does NOT modify DUT settings. User must set DNS to 10.0.0.211 via GUI. ``` ### QA 测试程序 #### 先决条件 - 带有两个网络接口的测试笔记本电脑(LAN + WAN) - Python 3.6+,已安装 `paramiko`(`pip install paramiko`) - 对 DUT 的 SSH 访问(root 凭证) - DUT 管理GUI可访问 #### 第 1 步:物理连接 使用两根电缆将测试笔记本电脑连接到 DUT: | 笔记本电脑端口 | 连接到 | 目的 | |------------|-------------|---------| | LAN 端口 | DUT LAN 端口 | SSH 访问 + 向 DUT 发送 DNS 查询 | | WAN 端口 | DUT WAN 子网(例如,上游交换机/调制解调器端口) | 作为上游 DNS 服务器 | 连接后,注意您的笔记本电脑 IP 地址: ``` # 查找您的 IP ip addr show | grep "inet " # 示例输出: # inet 192.168.1.254/24 ... ← 这是您的 LAN IP # inet 10.0.0.211/24 ... ← 这是您的 WAN IP(用于 --laptop) ``` #### 第 2 步:通过 GUI 将 DUT DNS 设置为笔记本电脑 1. 打开浏览器并转到 DUT 管理页面: - 例如,`http://192.168.1.1` 或 `http://myrouter.local` 2. 使用管理员凭据登录 3. 导航到:**连接** → **互联网设置** → **编辑**(位于 IPv4 旁边) 4. 在 **DNS** 下:选择 **静态 DNS** 5. 将 **DNS 1** 设置为您的笔记本电脑的 **WAN IP**(例如,`10.0.0.211`) 6. 点击 **应用** 7. 等待 5-10 秒以使设置生效 #### 第 3 步:运行工具 ``` cd /path/to/dnsmasq-cve-2026/ # 运行所有 6 个 CVE 测试: sudo python3 dnsmasq_cve_verify.py --laptop --dut --dut-pass # 示例: sudo python3 dnsmasq_cve_verify.py --laptop 10.0.0.211 --dut 192.168.1.1 --dut-pass '12345Asdf@' ``` 该工具将: 1. 通过 SSH 连接到 DUT(只读) 2. 在您的笔记本电脑的 WAN IP 上启动恶意 DNS 服务器 3. 验证 DUT 是否将 DNS 查询转发到它 4. 为每个 CVE 发送漏洞有效载荷 5. 检查 dnsmasq 是否崩溃或挂起 6. 每个 CVE 报告 PASS/FAIL #### 第 4 步:读取结果 - **PASS** = DUT 安全(功能未激活,或生存了攻击) - **FAIL** = dnsmasq 崩溃或挂起(漏洞!) - **ERROR** = 无法连接或 DUT 未转发 #### 第 5 步:恢复 DUT DNS 1. 返回 DUT 管理GUI 2. **连接** → **互联网设置** → **编辑** 3. 在 **DNS** 下:选择 **自动(来自 ISP)** 或删除静态条目 4. 点击 **应用** #### 故障排除 | 问题 | 解决方案 | |---------|-----| | “DUT 未将查询转发给我们” | 验证步骤 2 是否正确完成。检查笔记本电脑 WAN IP 是否与您在 GUI 中输入的匹配。 | | “无法连接到 DUT” | 验证 SSH 凭证。尝试:`ssh root@192.168.1.1` 手动。 | | “无法绑定端口 53” | 使用 `sudo` 运行。或者使用 `--dns-port 5353`(需要手动 DUT 配置)。 | | “版本:未知” | DUT 可能没有在标准路径中安装 dnsmasq。工具仍然可以正确测试。 | ## 测试结果(2026-05-31) ### dnsmasq 2.78 平台(总体:PASS) | CVE | 结果 | 原因 | |-----|--------|--------| | CVE-2026-2291 | PASS | DNSSEC 未编译 | | CVE-2026-4890 | PASS | DNSSEC 未编译 | | CVE-2026-4891 | PASS | DNSSEC 未编译 | | CVE-2026-4892 | PASS | dnsmasq 不提供 DHCPv6(使用单独的 DHCPv6 服务器) | | CVE-2026-4893 | PASS | 逻辑错误 — 无崩溃 | | CVE-2026-5172 | PASS | 生存了漏洞(2.78 中的漏洞代码路径不存在) | ### dnsmasq 2.90 平台(总体:PASS) | CVE | 结果 | 原因 | |-----|--------|--------| | CVE-2026-2291 | PASS | DNSSEC 未编译 | | CVE-2026-4890 | PASS | DNSSEC 未编译 | | CVE-2026-4891 | PASS | DNSSEC 未编译 | | CVE-2026-4892 | PASS | DHCPv6 未编译 | | CVE-2026-4893 | PASS | 逻辑错误 — 无崩溃 | | CVE-2026-5172 | PASS | 生存了漏洞变体 | ### 结论 所有 Linksys 路由器
标签:逆向工具