搜索

多个厂商dns消息解压远程拒绝服务漏洞

发表于 2026-10-17 06:19:22 来源:烟消火灭网

DNS消息解压机制里藏着一个能直接打崩递归服务器的多个洞坑。攻击者只需要发一个几十字节的厂商程拒查询包,就能让BIND、消息解Knot Resolver、压远Unbound这些主流DNS服务端在解析压缩指针时陷入无限循环或内存耗尽,绝服最终进程崩溃、多个洞服务中断。厂商程拒这个漏洞的消息解编号和具体厂商补丁时间线各家不同,但根子都在同一处:压缩指针的压远偏移量没有做边界校验。

先解释一下DNS消息压缩是绝服怎么回事。DNS协议为了省带宽,多个洞允许在报文里用指针引用之前出现过的厂商程拒域名。指针是消息解两个字节,高两位是压远11,剩下14位表示从报文起始位置算起的绝服偏移。解析器读到指针后,跳转到那个偏移继续读域名,如果读到的又是指针,就再跳。正常报文里指针指向的是已经解析过的、靠前的域名,所以不会死循环。但恶意构造的报文可以让指针A指向指针B,指针B又指回指针A,或者指针指向自身,解析器就卡在循环里出不来了。

更隐蔽的一种情况是压缩指针指向报文中间某个字节,那个字节恰好也长得像指针。攻击者不需要构造完美的循环,只要让解析器不断跳转、不断分配缓冲区去拼接域名,内存就会持续增长。BIND 9.16之前的版本在处理这类消息时,每次跳转都会把域名片段追加到临时缓冲区,循环几百次后内存飙升,进程被OOM killer干掉。Knot Resolver的C语言实现里有个指针计数器,但计数器溢出后没有及时终止,同样会耗尽资源。

我去年在一个内部DNS测试环境里复现过这个漏洞。用Python的scapy构造一个查询,问题段里的域名先放一个指向偏移12的指针,偏移12处再放一个指向偏移12的指针——就是一个自引用。发给本地的Unbound 1.13,进程CPU立刻跑满,strace显示它在一段代码里反复调用memmove,堆栈完全一样,没有任何退出条件。三秒后Unbound被系统杀掉,日志里只留下一行“out of memory”。这个攻击包总共38字节,放大效应惊人。

厂商的修复方式分两类。一类是加跳转次数上限,比如BIND在指针解析循环里塞了一个计数器,超过128次就判定为恶意报文,直接返回FORMERR。另一类是加偏移量校验,要求每个指针指向的位置必须小于当前读取位置,强制指针只能向前引用,这样从数学上就杜绝了循环。Knot Resolver选了后者,代码里多了几个if判断,性能损耗可以忽略。但有些老版本的dnsmasq只做了简单的深度限制,攻击者用多个指针嵌套还是能绕过。

实际影响面比想象的大。递归解析器通常部署在运营商、企业出口和公共DNS服务里,一旦被打崩,下游所有用户都上不了网。2016年那波DNS放大攻击用的是ANY查询,这次压缩指针漏洞不需要伪造源IP,攻击者直接和递归服务器建立TCP连接就能打——因为TCP下的DNS消息同样有压缩指针。Cloudflare的1.1.1.1在漏洞披露后紧急打了补丁,但很多中小ISP的BIND还停在旧版本,因为升级需要重启服务,他们宁愿在防火墙里加规则过滤畸形报文。

如果你维护DNS服务,现在就检查版本。BIND看9.16.32和9.18.6之后的版本,Unbound看1.16.2之后,Knot Resolver看5.5.3之后。不想升级的话,在递归服务器前面放一个DNS代理做报文规范化,把压缩指针全部展开成完整域名再转发,也能挡住大部分攻击。但最省事的还是升级——那些补丁代码加起来不到五十行,却能让你少一次半夜被叫起来重启服务的经历。

随机为您推荐
友情链接
版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright © 2016 Powered by 多个厂商dns消息解压远程拒绝服务漏洞,烟消火灭网   sitemap

回顶部