SAD DNS攻击复现报告
SAD DNS攻击复现报告
一、摘要
本报告旨在记录并分析论文 [CCS ‘20]《DNS Cache Poisoning Attack Reloaded: Revolutions with Side Channels》中所提出的 SADDNS 攻击的复现过程。SADDNS 是一种利用网络协议栈中旁路信道的 DNS 缓存投毒攻击。实验基于自研的 Cpings
高性能发包框架,通过构建一个包含攻击者、受害者 DNS 解析器(Unbound)和权威服务器的隔离网络环境,成功验证了该攻击的可行性与巨大威胁。
攻击的核心在于利用操作系统内核(特别是 Linux)中存在的全局 ICMP 速率限制这一旁路信道。攻击者通过精心设计的探测包和验证包,能够远程、高效地推断出 DNS 解析器用于上游查询的随机源端口,从而破解了现代 DNS 缓存投毒中最关键的一道防线——源端口随机化。一旦源端口被确定,攻击便退化为经典的 Kaminsky 攻击,攻击者只需暴力猜解 16 位的 Transaction ID 即可成功投毒。实验结果清晰地展示了从端口扫描、旁路信道信息推断到最终缓存投毒的全过程,直观地验证了 SADDNS 攻击的有效性。
二、原理分析
SADDNS 攻击巧妙地将攻击目标从 DNS 应用层本身转移到了其赖以运行的操作系统网络协议栈。它并非利用 DNS 软件的逻辑漏洞,而是利用了底层协议的实现特性来获取关键信息。
源端口随机化策略
- 自 Kaminsky 攻击后,DNS 解析器普遍采用源端口随机化作为核心防御措施。这使得攻击者除了需要猜测 16 位的TXID外,还需猜测约 16 位的源端口,将攻击的熵从 $2^{16}$ 提升至 $2^{32}$,使得暴力猜解在实践中几乎不可能。SADDNS 的首要目标就是消除源端口带来的不确定性
ICMP洪水防御
- Linux 等操作系统为了防止自身被 ICMP 洪水攻击耗尽资源,实现了一个全局的 ICMP 错误消息发送速率限制(例如,1000 pps),该机制反而被SADDNS攻击利用
- 当一个 UDP 包到达一个已关闭的端口时,操作系统会尝试生成一个 ICMP “Port Unreachable” 消息返回给源 IP
- 当一个 UDP 包到达一个已打开并正在监听的端口时(例如 Unbound 正在等待权威服务器响应的端口),该数据包会被上层应用接收(或因格式错误被丢弃),但操作系统不会生成 ICMP 消息
- Linux 等操作系统为了防止自身被 ICMP 洪水攻击耗尽资源,实现了一个全局的 ICMP 错误消息发送速率限制(例如,1000 pps),该机制反而被SADDNS攻击利用
攻击流程
攻击者向受害者 DNS 解析器查询一个由攻击者控制的域名(例如
nonce.attacker.com
)。这会使受害者解析器打开一个随机源端口,向上游(攻击者的权威服务器)发送查询端口扫描
- 攻击者向受害者 IP 的一个端口范围(例如 1024-1073,共 50 个端口)发送一连串(50个)UDP 探测包。这些包的源 IP 伪造的 IP
- 紧接着,攻击者从自己的真实 IP 向受害者的一个已知关闭的端口(例如端口 1)发送一个验证包
- 探测范围内无目标端口: 50 个探测包全部命中关闭端口,触发了 50 次 ICMP 生成请求,耗尽了全局 ICMP 速率限制的“令牌桶”。因此,后续的验证包虽然也命中了关闭端口,但无法生成 ICMP 消息。攻击者在其真实 IP 上收不到 ICMP 响应
- 探测范围内有目标端口: 50 个探测包中有 1 个命中了 Unbound 正在监听的开放端口,只触发了 49 次 ICMP 生成。全局速率限制未被耗尽。后续的验证包可以成功生成 ICMP 消息。攻击者在其真实 IP 上能收到 ICMP 响应
通过在不同端口范围重复上述“探测”过程,攻击者可以确定哪个范围(Block)内存在开放端口。一旦命中,便可采用二分查找法在该范围内快速、精确地定位到目标源端口
一旦源端口被锁定,攻击者便掌握了
(受害者IP, 目标端口, 权威服务器IP, 53)
这一完整的四元组。此时,唯一的未知数就是 16 位的 TXID。攻击者利用Cpings
框架的sender.c
模块,以极高的速率向受害者发送伪造的 DNS 响应,遍历所有 65536 个可能的 TXID。只要其中一个响应在真正的权威服务器响应之前到达,并且 TXID 匹配,缓存投毒即成功
三、实验复现
1. 实验环境
我们提供部分的虚拟机镜像,搭建包含三个核心角色的网络环境。
服务/角色 | IP地址 (示例) | 软件/系统 | 作用 |
---|---|---|---|
受害者解析器 | 192.168.3.144 |
saddns-server (Unbound) |
被攻击的 DNS 递归解析器,运行在易受攻击的内核版本上。 |
攻击者 | 任意 Linux 主机 | Debian + Cpings |
运行 saddns 攻击程序,执行端口扫描和缓存投毒。 |
权威服务器 | 192.168.3.135 |
auth-server (Python) |
攻击者控制的权威服务器,用于触发受害者的 DNS 查询。 |
2. 实验步骤
环境配置
- 启动受害者 Unbound 解析器,并开启调试模式以便观察日志。
在受害者主机上运行
sudo unbound -d - 启动攻击者控制的权威服务器。
在权威服务器主机上运行
python3 server.py
- 启动受害者 Unbound 解析器,并开启调试模式以便观察日志。
执行攻击
- 在攻击者主机上,编译并运行
Cpings
框架实现的saddns
攻击程序,并提供所有必要的参数在攻击者主机上运行
./saddns -i 192.168.3.144 \
-o 192.168.3.144 \
-s 192.168.3.111 \
-u 192.168.3.135 \
-d vic.example.com \
-a 192.168.3.148 \
-v - 参数说明
-i VICTIM_IP
: 受害者 IP 地址-s FAKE_IP
: 用于伪造 UDP 探测包源 IP 的地址(权威服务器 IP)-u AUTH_IP
: 攻击者控制的权威服务器的真实 IP,用于触发初始查询-d POISON_DOMAIN
: 目标投毒域名-a POISON_IP
: 想要注入的恶意 IP 地址
- 在攻击者主机上,编译并运行
投毒结果
- 在 Unbound 的调试日志中,可以看到在攻击成功时,它接收到了一个匹配的 UDP 响应,并将其内容(包含恶意记录)存入缓存。
[1755165673] unbound[1828:0] info: response for vic.example.com. A IN
[1755165673] unbound[1828:0] info: reply from <example.com.> 192.168.3.135#53
[1755165673] unbound[1828:0] info: query response was ANSWER
;; ANSWER SECTION:
vic.example.com. 65535 IN A 192.168.3.148
- 在 Unbound 的调试日志中,可以看到在攻击成功时,它接收到了一个匹配的 UDP 响应,并将其内容(包含恶意记录)存入缓存。
验证
- 攻击程序执行完毕后,使用
dig
工具向受害者解析器查询被投毒的域名,验证缓存是否被污染。dig @192.168.3.144 vic.example.com
- 查询结果清晰地显示,
vic.example.com
的 A 记录已经被成功篡改为攻击者指定的 IP192.168.3.148
,并且 TTL 值很高,意味着该污染记录将在缓存中驻留很长时间。;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 0
;; flags: qr aa ; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; QUESTION SECTION:
vic.example.com. IN A
;; ANSWER SECTION:
vic.example.com. 65521 IN A 192.168.3.148
- 攻击程序执行完毕后,使用
四、防御措施
针对 SADDNS 这种跨层攻击,防御措施也需要从多个层面入手:
操作系统内核修复
- 论文发布后,Linux 内核在 5.10 及以上版本中对此漏洞进行了修复。修复方案是将全局的 ICMP 速率限制改为每个网络命名空间独立。这意味着容器(如 Docker)等虚拟化环境将拥有独立的 ICMP 速率限制,使得攻击者无法再利用一个全局状态来推断另一个应用的信息,从而使该旁路信道失效。
DNS 应用层配置(如BIND9)
- 如果 DNS 软件在向上游发送查询时,在 UDP 套接字上调用
connect()
,该套接字将被内核绑定到特定的远程 IP 和端口。如此一来,只有来自该特定源的包才会被接受,攻击者伪造的探测包将被内核直接丢弃,无法用于扫描
- 如果 DNS 软件在向上游发送查询时,在 UDP 套接字上调用
部署 DNSSEC
- 这是抵御所有缓存投毒攻击的“黄金标准”。DNSSEC 通过数字签名来验证 DNS 数据的真实性和完整性。即使攻击者成功注入了伪造记录,启用了 DNSSEC 验证的解析器也会因签名无效而拒绝该记录,从而彻底免疫此类攻击。
五、结论
本次实验利用开发的 Cpings
框架,成功复现了 SADDNS 缓存投毒攻击。实验结果有力地证明,操作系统底层协议栈中看似无害的实现细节(如全局 ICMP 速率限制),完全可能被利用为高带宽的旁路信道,从而颠覆上层应用(如 DNS)的安全假设。SADDNS 的成功,不仅揭示了特定版本内核的严重安全隐患,也再次凸显了在全球范围内加速部署 DNSSEC 等端到端加密验证方案的紧迫性与至关重要性。