资讯动态

DNS缓存投毒原理与防御:信任缺陷下的解析劫持及排查指南

发布时间:2026/10/17 17:55:26 来源:尧图企业网站定制
1. 从一次Web攻击说起先抛一个真实场景。某公司的办公网络突然大面积反映无法访问企业内部门户IT排查了一圈防火墙正常、服务器负载正常、内网连通性正常但无论怎么ping解析域名总是指向一个奇怪的IP。最后发现问题出在内网DNS服务器上——缓存里被塞进了一条伪造的解析记录把公司内部的业务域名指向了攻击者控制的服务器。这就是DNS缓存投毒一个听着挺专业、其实离我们非常近的攻击手段。它不是靠破解密码也不是靠植入病毒而是利用DNS协议设计上的信任缺陷“骗”一台DNS服务器把错误的结果当成正确的缓存下来之后所有通过这台服务器解析该域名的客户端都会被带到攻击者想去的地方。这篇文章不打算堆概念会从DNS解析的基本原理开始把缓存投毒的底层机制掰开揉碎讲清楚攻击者到底是怎么让一台DNS服务器“信了假话”以及作为普通用户、运维人员、安全从业者该怎么发现和防御这类攻击。适合谁读网站运维、网络管理员、安全测试人员以及对网络协议感兴趣的开发者。即便你只是写业务代码理解了DNS缓存投毒的原理也能在排查各种诡异的“网络突然不好”问题时多一条思路。2. DNS解析链路与缓存机制2.1 递归查询与迭代查询在聊投毒之前得先把DNS的工作链路梳理清楚。当你访问一个域名时操作系统会向配置的DNS服务器发起一次递归查询意思就是说“帮我查一下这个域名对应的IP查到告诉我。”DNS服务器收到递归查询后自己会去完成整个解析过程。它先查自己的缓存没有的话就去问根域名服务器根服务器会告诉它“这个域名的顶级域服务器在哪”它接着问顶级域服务器顶级域服务器会说“这个域名的权威服务器在哪”最后它问权威服务器权威服务器才会给出最终的IP地址。这种从根到顶级域再到权威域的逐级询问叫迭代查询。递归查询和迭代查询的区别可以这样理解递归查询是你委托中介办一件事你只等最终结果迭代查询是中介亲自跑各个部门每个部门只告诉它下一步该去找谁。2.2 缓存存在的意义每一次完整迭代都涉及多次网络往返如果每个客户端每次访问都要这么来一遍根服务器、顶级域服务器会被海量请求压垮。所以DNS服务器会把解析结果缓存下来设置一个TTLTime To Live存活时间在TTL之内再次收到相同域名的查询时直接返回缓存结果不再向上游询问。TTL是缓存投毒里极其关键的一个参数。它决定了伪造记录能在缓存里待多久。如果攻击者注入了一条TTL设得很长的记录比如86400秒那就是整整一天意味着这条假记录会在DNS服务器上持续生效24小时。这也是为什么缓存投毒的攻击效果往往“药效”持久。2.3 一个容易被忽略的信任模型DNS协议在设计之初默认了一个前提网络上传输的DNS报文是可信的。它没有内置任何身份验证机制DNS服务器要求对方“你对我说什么我就信什么”。这就好比一个银行柜台任何穿工牌的人报出客户账号柜员就直接把钱转给对方没核对签名、没验证工牌的合规性。理解了这层信任关系就能明白缓存投毒的核心矛盾一台DNS服务器必须接受来自网络的响应但它又无法可靠地判断这个响应是否真正来自它刚才询问的权威服务器。攻击者要做的就是让自己伪造的响应看起来足够“像真的”让DNS服务器认错人。3. 缓存投毒的底层机制拆解3.1 五元组校验DNS服务器的“验身份”逻辑DNS服务器收到一个响应报文时会做几个简单的校验全部通过才会接受并写入缓存。这套校验逻辑业内一般称为“五元组”。源IP地址响应必须来自它刚才查询的那个服务器地址源端口响应必须来自它发出查询时目标使用的端口也就是53目的IP响应必须发往本机目的端口响应必须发往它发出查询时使用的源端口DNS报文中的Transaction ID事务ID响应里的ID必须和查询里的ID一致攻击者不知道客户端源端口和事务ID这两个值往往是随机的。早期DNS实现里事务ID只有16位即65536种可能如果攻击者能同时预测端口那么猜中概率就是1/65536看起来很低但在高速网络上以洪水方式猛猜几秒钟就能尝试数万次。3.2 传统投毒ID猜解加端口预测最早的缓存投毒攻击攻击者会向受害DNS服务器大量发送伪造响应事务ID从0开始逐个尝试同时猜测源端口。在BIND 9.5之前的时代不少DNS服务器的源端口固定或变化范围很小攻击者只需要暴力遍历事务ID命中概率相当可观。只要有一个伪造响应通过校验DNS服务器就会接受它并把附带在Answer区的恶意解析记录写入缓存。这种方式放在今天已经很难奏效因为现代DNS服务器普遍实现了源端口随机化和事务ID随机化随机空间大大增加。但历史教训值得记住任何一个“随机值”如果随机空间不够大或者实现上有规律可循都会变成可预测的防御盲区。3.3 坎伯恩攻击把毒下在权威服务器上传统方法瞄的是递归服务器而坎伯恩攻击Camber Attack以研究者名字命名换了个目标它把恶意数据注入到权威服务器的响应里让递归服务器在正常查询过程中被动“中毒”。具体思路是攻击者先注册一个自己的域名在自家权威服务器上配置一条特殊的NS记录把某个受害域名的权威服务器指向攻击者控制的服务器。当递归服务器来查询攻击者域名的相关信息时攻击者的权威服务器在响应中附加了额外的权威区信息声称受害域名的权威服务器是攻击者控制的机器并附上对应的附加区记录。递归服务器在处理这种响应时因为Additional区里的信息看起来“顺带提供了一些可能有用的内容”如果没有严格的区域数据校验就可能把这些信息缓存下来。之后当它被询问受害域名的解析记录时它会直接去问攻击者控制的假权威服务器攻击者想返回什么IP就返回什么IP。坎伯恩攻击的精髓在于它不需要猜ID不需要发洪水只需要利用递归服务器对“来自已信任权威服务器的追加信息”的天然信任把投毒过程伪装成一次正常解析。3.4 SAD DNS利用UDP端口随机化的盲区近几年被大量讨论的SAD DNS攻击针对的是一个更底层的设计问题——UDP的IP分片缓存机制。当UDP响应报文被分片时第一个分片包含传输层头部后续分片不包含。部分操作系统在重组分片之前会先把分片缓存起来而这个缓存的标识只基于源IP、目的IP和ID字段不包含源端口和目的端口。攻击者可以通过一系列精心构造的分片报文污染接收端的碎片重组缓存让位于被污染分片之后的伪造DNS响应数据“拼”进一个合法的DNS事务里。SAD DNS这种攻击方式的巧妙之处在于它绕过了源端口随机化这个被视为安全基石的机制把战场拉到了协议栈的分片重组层。它用实例证明了一件事网络协议栈里的每一个缓存都有可能成为投毒的媒介。3.5 类比总结把上述几种方式放在一起看可以梳理出一条共性逻辑缓存投毒的本质是攻击者对DNS信任链上某一环的欺骗。要么猜随机值硬闯传统ID猜解要么利用附加信息的信任漏洞坎伯恩要么钻协议栈实现的空子SAD DNS。这就像一个小区保安放人进门逻辑是“只要你有门禁卡就能进”。有的攻击者暴力试密码把所有可组合的数字都试一遍有的攻击者让保安信任的业委会主任打了个招呼就混进去了还有的攻击者发现只要陪一个真正的业主走进去保安根本不会检查你手上有没有卡。4. 攻击者如何构造一条恶意DNS响应4.1 伪造响应的必备字段要构造一条能骗过DNS服务器的响应需要把响应报文伪装成一次正常应答。DNS报文结构核心包含Header头部、Question问题区、Answer回答区、Authority权威区和Additional附加区。关键操作有这么几个事务ID必须和查询一致这要靠猜或者靠协议栈漏洞确定源端口要和查询的目标端口一致也就是53查询的问题区要和原查询匹配也就是域名、类型、类别需要一致Answer区塞入攻击者想让受害者解析到的IP设置合适的TTL尽量延长伪造结果的生命周期把AA标志位Authoritative Answer权威应答设为1让服务器认为这个响应来自权威源4.2 为什么问题区的匹配至关重要早期DNS实现中服务器对响应和查询是否匹配的校验很宽松只核对ID和IP不仔细检查问题区。攻击者可以发送一个域名不同但ID恰好猜中的响应服务器在特定实现下也会接受。现代DNS服务器普遍强制要求问题区和查询完全一致这一类修改过的实现已经很难奏效但这也催生了另外一种思路——攻击者开始利用“域名重叠”或“搜索域追加”等方式让看似完全匹配的查询在语义上被曲解。4.3 一个关键细节胶水记录胶水记录Glue Record是在父区中提供的子区权威服务器的IP地址目的是让递归服务器在查询子区时不用再额外做一次IP解析。胶水记录本身是为了性能而设计的优化机制但同时也成了投毒的重灾区。攻击者如果在权威域的响应中附加一条精心构造的胶水记录声称某权威服务器的IP是恶意地址递归服务器就可能将这个信息缓存下来。所以在部署DNS服务时胶水记录的过滤和校验是不可省略的一环。一个响应中携带的附加信息如果不是原查询直接需要的应当谨慎对待。4.4 实操示例用dig手动模拟一次不正常的响应这里不鼓励大家去实践攻击但可以用dig命令观察DNS响应报文的组成理解缓存写入的逻辑。比如执行dig 8.8.8.8 example.com A norecurse返回结果里会显示Status、ANSWER SECTION、AUTHORITY SECTION、ADDITIONAL SECTION对应了响应报文里的回答区、权威区、附加区。当你理解了每个区块的内容再看安全公告和攻击分析时就能明白攻击者到底把恶意内容塞在了哪个区块。防御视角下的自查方法是找一台你能控制查询行为的DNS服务器按照一个已知正常结果发起查询抓包对比再换一台不受信任的DNS服务器发起同样查询对比结果是否一致。不一致时就要高度怀疑上游被污染。5. 实战场景与影响范围5.1 公共WiFi下的局域网投毒在很多公共网络场景中攻击者不需要攻击上游DNS服务器直接把目标锁定在受害者本机或局域网内。攻击者可以冒充网关向局域网内所有设备发送伪造的DNS响应——前提是攻击者和受害者在同一个二层网络内。因为设备发出的DNS查询是广播给网关的攻击者可以抢先发送伪造响应源IP设为真实的DNS服务器IP端口设为53IPID设为推测值在合法响应到达之前到达受害者设备。谁先到谁说了算。这就是为什么在不信任的公共网络上访问敏感站点会存在被劫持的风险。5.2 上游DNS服务器被针对性投毒规模更大的攻击意图往往是控制一个区域的DNS出口。当某个运营商或企业的递归DNS服务器被投毒成功影响范围立刻覆盖该服务器服务的所有终端用户。典型的例子是某个热门的更新域名被污染后所有走这台DNS服务器的设备在解析软件更新服务器时都会拿到恶意IP继而下载到被篡改的更新包。这种攻击一旦得手清理成本远高于攻击成本。即便运维发现了缓存记录异常只要根因没找到攻击者还可以反复投毒。TTL越长修复窗口越短影响越大。5.3 影响范围评估的三条主线评估一次缓存投毒事件的影响范围通常看三条线时间维度伪造记录的TTL有多长决定了“药效”持续多久空间维度受影响的递归服务器服务了多少用户和多少域名业务维度被投毒的域名是否涉及身份认证、支付回调、软件分发等高危环节三条主线中业务维度往往最致命。很多人的第一反应是“不就是解析到了一个错误IP吗刷新一下就好”但在软件自动更新场景里一次错误解析带来的可能就是全网的恶意代码分发。6. 检测方法与排查技巧6.1 终端侧排查先确认是不是DNS问题当用户报告“打不开网站”或“访问的页面不对”时第一步是确认是不是DNS解析被污染。最简单的排查方法是用nslookup或dig对比多个公共DNS的解析结果nslookup example.com 8.8.8.8 nslookup example.com 223.5.5.5如果不同的DNS服务器给出的解析结果不一致或者解析结果与域名实际所属IP明显不符比如一个知名电商域名解析到了一个IDC机房的IP这通常意味着某个环节发生了污染。更细致的排查是做一条dig example.com trace看清楚从根到权威每一级返回了什么哪一级出现了异常响应。这一步能帮你锁定污染发生在权威侧还是递归侧。6.2 服务器侧排查检查缓存中是否出现异常映射对于运维人员定期巡检核心域名的缓存映射很有必要。做法是记录一份关键域名的正常解析清单包括IP归属和解析关系用脚本定时对比当前DNS服务器的解析结果发现异常立即告警。一旦发现缓存被污染处理步骤是清空对应域名的缓存记录部分DNS服务器支持按域清理缓存确认记录被清空后换用干净的公共DNS手动验证真实解析结果抓包定位污染来源判断是本机被攻击还是上游服务器被投毒如果是本地递归服务器被投毒检查服务器是否开放了递归服务、是否限制了来源IP、是否开启了DNSSEC验证6.3 网络抓包把恶意响应揪出来如果是安全分析人员抓包是最直观的排查手段。在DNS服务器或客户端上抓取UDP 53端口流量tcpdump -i eth0 udp port 53 -w dns_capture.pcap抓到报文后重点看三点源IP是否为待查询的权威服务器IP响应报文中的Answer区IP是否可信TTL是否异常超大正常域名的TTL通常在几分钟到几小时之间突然出现几天甚至几十天的TTL高度可疑需要提醒的是抓包分析要配合业务正常时期的基线数据。如果没有基线孤立地看一个响应很难判断是否异常。所以建议在日常运维中就定期保存一份核心域名的正常解析基线。7. 防御思路与加固方案7.1 开启DNSSEC验证DNSSEC是目前对抗缓存投毒最有效的正统手段。它的原理是通过链式签名的方式让解析结果带上数字签名递归服务器可以逐级验证这个签名是否由上级权威源签发。链式验证的逻辑可以类比为根区签了顶级域的密钥顶级域签了权威域的密钥权威域签了具体的解析记录。递归服务器在拿到一条解析记录时可以沿着签名链一直验证到根确保这条记录确实来自可信来源而不是中途被人篡改或伪造。DNSSEC部署的难点在于需要域名所有者、权威服务器运营商、递归服务器运营商三端配合。域名没有开启DNSSEC签名递归服务器即使支持也无法验证递归服务器不支持验证域名签了名也无法让最终用户受益。7.2 0x20编码方案0x20编码是一种轻量级的缓解技术核心思想是利用DNS域名大小写编码来增加随机空间。DNS域名在语义上是大小写不敏感的Example.com和example.com是同一个域名但DNS报文在传输时保留原始大小写。递归服务器在发出查询时随机打乱域名的大小写形式转发或应答时必须完全匹配这种大小写模式才能通过校验。攻击者如果不知道查询中域名的大小写模式即使事务ID和端口全部猜中也无法构造出一模一样的大小写变体。这相当于在原来随机化的基础上又额外增加了一层高熵校验让猜中概率进一步降低。0x20编码不需要改动协议只需要递归服务器和权威服务器配合保持大小写写状态即可实际部署成本很低值得优先考虑。7.3 端口随机化和查询随机化不能省源端口随机化已经是现代DNS服务器的标配但需要注意随机化的质量。有的系统虽然实现了随机端口但随机数发生器熵不足或者端口范围过窄依然会被攻击者压缩猜测空间。配合事务ID随机化、0x20编码三者共同撑起查询的不可预测性。检查方式在大型DNS服务器上跑测试观察连续发出的查询中源端口和事务ID的分布是否均匀。如果出现明显的规律性、聚集性就要检查随机源是否有问题。7.4 管理面收敛递归服务和权威服务分离很多企业为了省事一台DNS服务器既做递归又做权威这个做法在安全性上存在不小隐患。递归服务需要向外部世界发起查询、接收响应攻击面天然暴露权威服务只需要对特定记录提供应答不应当接收来自任意来源的递归查询。建议架构是递归服务器与权威服务器物理或逻辑上分离递归服务器的查询来源白名单收紧到内网网段权威服务器只应答自己权威负责的域名记录配置不为外来递归请求服务。这条经验强调了好几次因为很多投毒事件都源于服务器配置不当——开启了本不需要的递归服务给了攻击者可乘之机。7.5 建立监控与应急响应流程防御不能只靠静态配置要建立持续的监控机制。常见的有效做法包括对核心域名的解析结果做基线监控发现IP变化立即核查对DNS服务器的日志进行审计检查错误响应和大量重复请求的异常模式部署蜜罐域名Honeypot Domain即一个无人访问但被监听的域名如果有来自DNS日志的查询记录出现说明有人在尝试解析这个域名很可能是在探测或者投毒应急响应流程建议提前演练不要等到被投毒了才临时讨论。固定住几个实操做法如何快速清缓存、如何切换备用DNS出口、如何确认根因、如何修复配置漏洞。8. 一些容易被忽视的细节做了较长时间的DNS相关工作几个小发现值得单独拿出来说。第一缓存投毒不总是全量生效。有些攻击瞄准的是特定用户的特定查询有些攻击构造的响应只针对某些域名测试验证时如果用错误的目标域名去复测根本测不出问题。排查时要尽可能还原受害者当时的具体查询条件。第二公网解析和内部域名解析要分开管理。内网域名如果是通过公网权威服务解析的会把内网结构间接暴露出去也会放大投毒影响面。内网域名应当使用内网专用权威服务和内网递归服务尽量不要和公网解析链路共用同一套设施。第三TTL不是越大越好。从性能角度看TTL大可以减少重复查询压力从安全角度看TTL越大一旦被投毒影响时间越长。业务侧如果允许建议将动态性要求不高的域名设为中等TTL15分钟到30分钟既保证缓存效率又缩短受污染记录的存活窗口。第四清理缓存时要注意“连带污染”。DNS缓存里不同记录之间可能存在相互引用关系一条附加区记录被清理后与之关联的权威区信息可能仍然残留在缓存中。清理后要多查几个关联域名确认没有残留。第五把DNS和HTTPS证书的校验结合着看。TLS证书具备域名身份校验能力缓存投毒虽然能把域名指向恶意IP但恶意服务器在提供HTTPS服务时依然需要一张可信的证书才能通过浏览器校验。对高价值业务来说强制使用HSTS并启用证书固定可以在DNS层面被攻破后增加第二道防线。当然这并不能防御所有场景但能显著提高攻击门槛。DNS缓存投毒这个课题技术上的核心其实并不复杂一个基于明文UDP协议、默认信任对端、随机化空间有限的分布式系统必然要面对“如何确认消息发送者身份”的挑战。了解攻击手法不是为了让谁变得危险而是为了让防御者有更准确的心智模型——当你知道了攻击者可以怎么欺骗一台DNS服务器再回头看自己的配置文件和监控策略很多之前忽略的漏洞就会变得清晰起来。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑