Hickory DNS 39 个 CVE 集中公开:DNSSEC 验证可被绕过,Rust 项目该查版本了

Rust 生态里最主流的 DNS 实现 Hickory DNS 被一次性公开 39 个 CVE,CVE 记录在 2026 年 11 月 8 日集中建档,分配方为 VulnCheck。最高一条 CVE-2026-123587 评分为 8.9,问题出在 DNSSEC 验证逻辑上:解析器判断 NSEC 记录是否回绕时,会去比较响应里的 SOA,而这个 SOA 即使验证失败也被接受。其余条目覆盖 DNSSEC 绕过、查询放大与成批的拒绝服务问题,受影响版本一直延伸到 0.26.1,修复版本 0.26.2 已于 9 月 3 日发布。

事件概述

漏洞分布在四个 crate 中:hickory-proto(协议解析)、hickory-resolver(解析器)、hickory-recursor(递归解析)与 hickory-net(DNSSEC 验证)。项目在 GitHub 上有约 5,488 个 star,是 Rust 生态里做 DNS 客户端、DNS 服务器、DoH/DoQ 网关的主流选择,也被不少平台内嵌进服务发现与出口代理。

时间线值得注意:0.26.2 发布于 2026 年 9 月 3 日,0.26.3 于 9 月 10 日跟进,而 39 个 CVE 直到 11 月 8 日才集中建档,中间隔了约两个月。这意味着「升级过的项目不受影响」这句话成立的前提,是依赖树里真的没有旧版本——间接依赖恰恰是最容易被忽略的地方。

DNSSEC 验证绕过:四类根因

39 条里有相当一部分不是崩溃,而是「验证通过但结论是假的」,这类问题比 DoS 更值得警惕。

  • CVE-2026-123605(8.7):验证器拿 RRSIG 去比对 DNSKEY 时,只用 Signer’s Name 字段里的名字取钥匙,没有校验这个名字是否就是 RRset 所在的 zone。攻击者用自己控制的域名的合法密钥,就能为任意区域的记录签出「有效」的 RRSIG。
  • CVE-2026-123587(8.9):NSEC 回绕判定依赖响应中的 SOA,且该 SOA 未经验证就会被接受。攻击者把一条真实 NSEC 与一个伪造 SOA 组合,即可让「该名字不存在」的结论成立。
  • CVE-2026-123596 与 CVE-2026-123595(均 8.7):NSEC 与 NSEC3 处理器把父侧的祖先委派记录当作 zone cut 之下的「不存在证明」,链路上的攻击者可以据此伪造 NXDOMAIN,把流量导向自己的服务器。
  • CVE-2026-123580(8.7):NSEC3 比对时只看哈希标签,不确认记录是否属于正确区域,来自其他区域的 NSEC3 也能被采信。

这四类的共同点是「验证逻辑只校验了密码学,没有校验上下文」。RRSIG 是真的、哈希是对的,但它证明的东西并不是解析器以为的东西。DNSSEC 的信任模型要求签名密钥必须属于被签名数据所在区域,只要这一层绑定缺失,整条信任链就退化成「谁都能签」。

拒绝服务与放大

另一大块是可用性问题,其中几条对外网服务构成直接威胁:

  • CVE-2026-123570(8.7):按报文头里的 ANCOUNT/NSCOUNT/ARCOUNT 预分配记录向量,一个伪造响应即可让内存按攻击者给的数字膨胀。
  • CVE-2026-123575 至 123577(均 8.7):DoH 的 HTTP/2、DoQ 与请求体读取缺少超时与长度上限,攻击者只发长度前缀不收尾,就能长期占用连接与预分配缓冲。
  • CVE-2026-123586(8.7):两个互为权威、又都没有 glue 记录的 zone 可以制造循环引用,把递归解析器变成放大器。
  • CVE-2026-123608(8.7):名字压缩的二次时间复杂度,构造多记录报文即可打满 CPU。

对国内使用场景的实际影响

Hickory DNS 在国内的直接用户不算多,但它的位置很关键。一类是自建的 DoH/DoQ 网关,放在公网出口给内网客户端提供加密解析,这类服务同时暴露在「验证绕过」与「DoS」两类风险下;另一类是内嵌在网络组件里的解析器,例如服务发现、Sidecar 代理、边缘网关,这些项目往往把 hickory 当作传递依赖引进来,升级时只跟主项目版本,不会单独检查它。还有一类是做安全工具与指纹识别的项目,用它的协议栈去解析响应报文。

判断是否踩中很简单:Cargo.lock 里搜 hickory,看解析出来的版本号是否低于 0.26.2。低于就要动,不论这个依赖是直接写的还是被传进来的。几个细节值得注意:hickory-proto 的修复线并不统一,个别条目按 0.26.1 计算;hickory-recursor 全版本都在受影响范围内,写的是「所有版本」,只能靠替换 crate 解决;升级后建议清一次本地缓存与持久化 zone 数据,避免旧的验证结论继续被复用。

修复建议

  • 升级到 0.26.3 或至少 0.26.2。注意部分条目(如 123608、123607)的修复线落在 0.26.1,统一升到 0.26.3 最省事。
  • 用 cargo tree -i hickory-proto 之类命令反查依赖树,重点看间接依赖:直接依赖写了新版本、传递依赖仍锁在旧版本的情况非常常见,Cargo.lock 里搜 hickory 是最快的核对方式。
  • 面向公网的 DoH/DoQ 服务,先在网关层补上请求体长度与空闲超时限制,不要等升级窗口。
  • 使用 Hickory 做验证型递归解析的场景,升级后清空缓存再重启,避免旧的可疑结论继续命中。
  • 若短期内无法升级,尽量避免让解析器直接面对不可信上游;把上游收敛到可信递归,并对响应做一致性校验。

参考来源