Poison Over Forwarders攻击复现报告
Poison Over Forwarders 攻击复现报告
一、摘要
本报告详细记录了对[USENIX Security 2020]《Poison Over Troubled Forwarders: A Cache Poisoning Attack Targeting DNS Forwarding Devices》中所述攻击的复现过程。该攻击是一种针对 DNS 转发设备的新型缓存投毒技术,它巧妙地利用了IP协议层面的分片与重组机制,从而绕过了传统的、依赖于传输层(如源端口随机化)的DNS安全防御措施。
我们通过 Docker 构建了一个包含易受攻击的 DNS 转发器(dnsmasq
)、攻击者控制的权威服务器和攻击者客户端的隔离网络环境。实验中,攻击者首先向转发器注入一个精心构造的、伪造的 IP 第二分片,然后触发一个对攻击者域名的查询,诱使其权威服务器返回一个超大的、会被合法分片的DNS响应(实验复现中采用的是超长CNAME链)。转发器在重组IP包时,错误地将合法的第一个分片与伪造的第二个分片结合,最终导致其 DNS 缓存被植入指向攻击者指定域名(例如victim.cn
)的恶意 IP 地址。实验结果成功验证了该攻击的可行性与巨大危害。
二、原理分析
“Poison Over Forwarders” 攻击的核心,是滥用DNS转发器处理 IP 分片响应时的脆弱性,不依赖于猜测事务ID或源端口,而是利用IP层的特性,转化为只需要合理猜测IPID即可
攻击者与目标DNS转发器(
10.0.0.2
)处于同一局域网内。这是论文中的主要威胁模型之一,适用于开放 Wi-Fi 或受感染的内网主机场景攻击者向 DNS 转发器发送一个伪造的 IP 数据包。这个包是 DNS 响应的第二个分片。其内容包含了最终想要投毒的恶意记录(例如
victim.cn A 9.9.9.9
)。此分片的 IP 头部包含了一个可预测的 IPID,这是后续与合法分片匹配的关键攻击者向 DNS 转发器发起一个正常的 DNS 查询,请求解析其自己控制的域名(例如
random-uuid.example.com
)DNS 转发器将该查询转发至上游,最终到达攻击者控制的权威服务器(
10.0.0.3
)。该权威服务器被设计为返回一个超大的 DNS 响应(通过构造一个极长的 CNAME 记录链实现)。这个响应的大小超过了网络路径的 MTU(通常为 1500 字节),因此它在离开上游服务器时必须被分片DNS 转发器接收到来自权威服务器的第一个分片,这个分片的 IPID 与攻击者先前注入的恶意分片 IPID 完全相同,根据 IP 协议,转发器会查找具有相同 IPID 的分片进行重组。由于恶意的第二个分片已在其重组缓存中,转发器便将合法的 Fragment 1(包含查询头部和部分 CNAME 链)与伪造的 Fragment 2(包含恶意 DNS 记录)拼接在一起。
重组后的数据包在转发器看来是一个完整且合法的 DNS 响应。由于
dnsmasq
等软件默认按记录而非按响应进行缓存,它会解析这个被篡改过的包,并将其中恶意的victim.cn A 9.9.9.9
记录存入缓存。
必要条件:
- IPID 可预测:攻击者必须能够预测或猜中上游服务器发出的合法分片的 IPID。在我们的实验环境中,通过将服务部署在同一网络并使用简单的 IPID 生成逻辑,极大地简化了这一挑战
- 转发器处理分片:目标转发器必须支持并处理分片的 DNS 响应,而不是直接丢弃
- 按记录缓存:转发器必须支持按记录缓存。如果按响应缓存,由于查询的是
example.com
而非victim.cn
,投毒将不会生效 - 无响应校验:转发器在缓存前不会对 CNAME 链的最终结果进行重新验证
三、实验复现
1. 实验环境
我们使用 docker-compose
搭建了包含三个核心服务的网络环境:
服务 | IP 地址 | 角色 | 作用 |
---|---|---|---|
forwarder |
10.0.0.2 |
受害者DNS转发器 | 运行一个配置为转发模式的 dnsmasq 服务,将所有未知查询转发至 10.0.0.3 。 |
auth |
10.0.0.3 |
攻击者权威服务器 | 模拟一个权威 DNS 服务器,收到特定查询后返回超大的、会被分片的响应。 |
attacker |
10.0.0.4 |
攻击者客户端 | 运行 attack.py 攻击脚本,协调发送恶意分片和触发合法查询的整个过程。 |
2. 实验思路
进入
attacker
容器,执行攻击脚本,脚本会自动执行攻击逻辑:计算并构造恶意的第二个分片,然后向转发器查询一个随机子域名来触发攻击。由于实验环境的 IPID 固定为1,攻击通常在第一次尝试时就能成功。观察到如下输出,表示攻击成功:[*] Triggering attack with query: '5b4c3bfd.example.com'...
...
[+] >>> SUCCESS! <<< Cache for 'victim.cn' POISONED with '9.9.9.9'.在攻击成功后,我们从
attacker
容器向forwarder
(10.0.0.2
)查询被投毒的域名victim.cn
,以验证其缓存是否已被污染,我们得到了如下响应,ANSWER SECTION
中victim.cn
的 IP 地址已被成功篡改为恶意的9.9.9.9
,证明缓存投毒成功。; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @10.0.0.2 victim.cn
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63430
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;victim.cn. IN A
;; ANSWER SECTION:
victim.cn. 3152 IN A 9.9.9.9
;; SERVER: 10.0.0.2#53(10.0.0.2) (UDP)
3. 遇到的困难与挑战
- UDP 校验和修复:在构造伪造的第二个分片时,必须确保当它与第一个合法分片重组后,整个 UDP 数据包的校验和是正确的。本次复现代码采用了一个较为简陋的思路(指定域名较短有效,例如
acc.net
、a.com
)。通过局部原理与贪心算法思路,修改 CNAME 链中末端特定子域名的部分字符并修复校验和 - IPID 预测:在真实世界的攻击中,预测上游服务器的 IPID 是最大的挑战。本实验通过简化的环境(固定 IPID)绕过了这个问题,但在实际攻击中,攻击者需要采用论文中提到的 IPID 探测和预测技术。但值得一提的是,实验环境实际支持IPID预测,但是预测的方式是通过权威服务器与攻击者进行交互完成的,即权威服务器记录下使用的IPID,然后攻击者可以持续了解IPID并依赖滑动窗口做出适当预测。
四、其他转发器
本实验依赖于dnsmasq
的“傻瓜式”转发服务,对于其他一些DNS服务器其实本身并不奏效
dnsmasq(2.82)
:本实验修改了dnsmasq
源码的部分参数,让其支持解析长CNAME链(详见Dockerfile文件)BIND9(9.16.45)
:不支持解析超过16长度的CNAME链(但是已解析的会缓存,9.19以后似乎修复),且似乎应该是硬编码的,暂时没有在源码找到相关宏或者参数Unbound(1.19.0)
:不支持解析超过12长度的CNAME链(已解析的不缓存,返回SEVFAIL),同时坚持递归确认,而不是傻瓜式转发
五、结论
本次实验成功复现了“Poison Over Forwarders”攻击,直观地展示了攻击者如何利用 IP 分片机制来绕过传统 DNS 防御,实现对 DNS 转发器的缓存投毒。这证明了即使在源端口随机化已广泛部署的今天,DNS 生态系统在协议栈的更底层依然存在安全风险。
为了防御此类攻击,论文和业界提出了多种缓解措施:
- 按响应缓存: 转发器将整个 DNS 响应(包括所有记录)作为一个整体与原始查询进行缓存。当查询其他域名时,即使该域名存在于缓存的响应中,也不会被返回。这是最直接有效的防御手段之一,也是部分厂商(如 ASUS)采纳的修复方案。
- 响应验证: 转发器可以像一个完整的递归解析器一样,对响应中的 CNAME 链进行重新查询验证。但这会显著增加其负载,违背了其作为轻量级转发器的初衷。(如 BIND 在转发模式下会执行此类检查)