SAD DNS漏洞评估脚本说明

评估脚本获取measure.py源码

1. 漏洞说明

来源

[CCS ‘20]DNS Cache Poisoning Attack Reloaded: Revolutions with Side Channels

基本原理介绍

该漏洞(又称 SADDNS)是一种利用操作系统内核网络协议栈的边信道,来绕过源端口随机化这一关键防御机制,从而重新实现传统DNS缓存投毒攻击。

传统DNS投毒攻击需要猜测一个32位的组合(16位源端口 + 16位Transaction ID),这在实践中几乎不可能。SADDNS通过一种“分而治之”的策略,将这个难题分解为两个可行的步骤:

  1. 利用ICMP边信道猜测源端口

    • 当DNS解析器向外发送一个查询时,它会使用一个随机的UDP源端口(例如 34567)。
    • 攻击者为了找到这个端口,会向解析器发送大量伪造源IP的UDP探测包,覆盖一个端口范围(例如 30000-40000)。
    • 对于每一个命中关闭端口的探测包,解析器的操作系统(如Linux)会试图回复一个ICMP Port Unreachable 错误消息。
    • 然而,操作系统对ICMP错误消息的生成速率有一个全局速率限制(例如 1000条/秒)。攻击者发送的探测包足以在瞬间耗尽这个限制。
    • 核心边信道:如果解析器使用的随机源端口(34567)在攻击者探测的范围内,那么所有探测包都会触发ICMP响应,耗尽速率限制。此时攻击者用自己的真实IP再发送一个探测包,将收不到ICMP响应。
    • 反之,如果源端口(34567)恰好在攻击者探测的范围内,这个探测包会被操作系统接受并递交到上层应用,不会触发ICMP响应。这使得ICMP速率限制的“令牌桶”中会留下一个空额。此时攻击者用真实IP发送探测包,将能收到ICMP响应。
    • 通过这个微小的差异,攻击者可以迅速通过二分法等方式定位到解析器使用的确切源端口。
  2. 暴力破解Transaction ID:

    • 一旦源端口被确定,攻击者只需暴力破解剩余的16位Transaction ID。
    • 攻击者向已知的源端口发送大量伪造的DNS响应,每个响应使用不同的Transaction ID。在当前的带宽条件下,发送65536个包是完全可行的。
    • 只要其中一个伪造响应的Transaction ID命中,并且早于真实的DNS响应到达,缓存投毒即告成功。

影响目标

  • 设备/软件: 运行在存在ICMP全局速率限制这一边信道的操作系统上的DNS解析器或转发器。
  • 操作系统: Linux (Kernel 3.18及以后、5.10以前版本尤为明显),以及其他实现了类似ICMP速率限制机制的操作系统。

影响软件版本

  • 主流的且不使用connect的DNS软件(如Unbound, dnsmasq等),当它们运行在受影响的操作系统上时都可能受到波及,因为漏洞根源在操作系统层面而非DNS软件本身。

2. 漏洞监测工具实现

漏洞监测方法原理

提供的 saddns_measure.py 脚本是一个无害的、用于检测目标服务器操作系统是否存在ICMP速率限制边信道的测量工具。其原理完全基于论文中描述的“耗尽与探测”(Drain and Probe)方法。

  1. 基础ICMP响应检查: 脚本首先向目标IP的一个高位UDP端口发送一个探测包。如果目标按预期返回ICMP Port Unreachable (type 3, code 3) 消息,证明进行下一步探测的基础条件是存在的。如果目标不响应或被防火墙拦截,则无法利用该边信道。

  2. ICMP速率限制边信道探测: 这是脚本的核心。

    • 脚本在瞬间向目标IP发送一连串(默认为50个)伪造源IP的UDP包。这些包的目标端口是关闭的,旨在触发ICMP响应并耗尽目标的ICMP全局速率限制“令牌桶”。
    • 在发送完耗尽包之后,脚本立即从本机真实IP发送一个UDP探测包到同一个关闭的端口。
    • 判断
      • 如果探测包没有收到ICMP响应,说明之前的伪造包成功耗尽了目标的ICMP速率限制,导致真实探测包的ICMP响应被丢弃。这证明了侧信道存在,目标是脆弱的。
      • 如果探测包仍然收到ICMP响应,说明目标的ICMP速率限制机制不存在或行为与预期不符,无法形成可利用的边信道。

监测是否有害

。该工具只发送标准的UDP数据包并观察ICMP错误响应。它不包含任何恶意负载,不进行DNS查询,也不执行任何缓存投毒行为。它纯粹用于测量目标操作系统网络协议栈的一种特定行为。

工具输入

脚本通过命令行参数接收目标IP和网络接口。

# 命令行输入
# sudo python3 saddns_measure.py <TARGET_IP> <NETWORK_INTERFACE>

# 脚本内部配置
PROBE_PORT = 54321 # 一个高位UDP端口,假定是关闭的
DRAIN_COUNT = 50 # 用于耗尽ICMP令牌桶的伪造包数量
TIMEOUT = 0.5 # 超时时间

工具输出

彩色的文本报告,清晰地展示每个检测步骤的结果 ([PASS][FAIL]),并最后给出明确的结论:[VULNERABLE] (脆弱) 或 [NOT VULNERABLE] (不脆弱)。


3. 漏洞监测工具使用

环境部署

无需特殊的DNS或网络环境。该工具是一个纯客户端的测量脚本,可以在本地网络(L2)中对任何可达的主机进行评估。

使用环境配置

  • Python版本: Python 3.x
  • Requirements: scapy.
    pip install scapy

使用方法

  1. 确保测试机与目标主机在同一个二层网络中,以便获取目标MAC地址。
  2. 在测试机上,使用root权限运行脚本,并传入目标IP地址和本机网络接口名作为参数。
    # 假设你的DNS服务器IP是 192.168.1.1,本机网卡是 ens33
    sudo python3 saddns_measure.py 192.168.1.1 ens33

预期输出示例

[INFO] SAD DNS for: 192.168.1.1 on interface ens33
- My IP: 192.168.1.100
- My MAC: 00:0c:29:11:22:33
- Target MAC: 00:50:56:c0:00:08
[INFO] Step 1: Check for ICMP response [PASS] (Target responds)
[INFO] Step 2: Check for ICMP rate limit [PASS] (side channel exists)
[*] Closing L2 socket.

---------------------------------------------------------------------------
[*] Final Conclusion:
192.168.1.1 is [VULNERABLE] to SAD DNS
---------------------------------------------------------------------------