phlipow/DNSFlareLab
GitHub: phlipow/DNSFlareLab
DNSFlareLab 是一个用于在受控环境中复现和研究 DNS 缓存计时侧信道攻击的教育性概念验证实验室,通过测量共享 DNS 转发器缓存的响应时间差异来推断用户浏览行为。
Stars: 0 | Forks: 0
# DNSFlare 实验室 (个人 PoC)
本仓库包含我的个人 DNSFlare 实验室,旨在受控环境中重现和研究 DNS 计时侧信道行为。
参考论文:
https://www.usenix.org/system/files/usenixsecurity25-moav.pdf
## 简介:
DNS FLaRE 是一种针对 DNS 转发器缓存的 DNS 缓存计时侧信道攻击。攻击者不需要直接的网络位置或恶意软件,唯一的条件是连接到网络的任何设备打开一个由攻击者控制的网页并使其在后台保持活跃。
虽然客户端附近运行着多个缓存(浏览器缓存、操作系统级缓存、转发器缓存),但转发器缓存具有一些可被攻击者利用的属性:
- 它由同一网络中的多个设备/用户共享
- 与浏览器/操作系统缓存相比,它相对较小
- 它可以比较大的缓存更容易被刷新
这产生了可测量的 HIT/MISS 计时:
- **cache HIT:** 目标 DNS 数据已存在于转发器缓存中,因此查询路径较短
- **cache MISS:** 查询必须向上游解析,因此路径较长
该攻击将经典的刷新-重载 (flush-reload) 侧信道模式适配到 DNS 中,以重复的循环进行:
1. **Flush (刷新):** 攻击者用受控的虚假 DNS 记录填充转发器,以驱逐先前的条目
2. **Sample interval (采样间隔):** 一个等待窗口,在此期间受害者的活动可能会将目标域名重新插入到共享的转发器缓存中
3. **Reload and timing (重载和计时):** 攻击者触发对目标域名的依赖于 DNS 的浏览器请求,并测量计时以推断缓存状态
4. **Classification (分类):** 将计时结果与校准模型进行比较,以对每个域名的 HIT 或 MISS 进行分类
由于浏览器具有涉及非标准 HTTPS 端口的属性——其中会查询带有前缀的名称如 `_0._https.example.` com,因此会首先预取此记录以防止噪声并稳定计时。
为了避免重复使用浏览器 DNS 缓存,我们可以利用最初旨在减少跨站泄漏的浏览器缓存分区。通过轮换攻击者的源,我们阻止浏览器缓存提供结果,确保每次计时测量反映的是转发器缓存状态而不是浏览器缓存命中。
安全与隐私影响:
- 攻击者可以推断出在最近的时间窗口内是否可能访问了特定域名。
- 由于转发器缓存在多个设备之间共享,因此一个受害者的会话可能会泄露家庭其他成员的活动模式。
- 这可以扩展到 IoT 操作分析(从设备特定的 DNS 模式中推断活动)。
论文指出,如果目标解析器/转发器仍然暴露出易受攻击的共享缓存行为,那么 DNSSEC 和 DoH 本身并不能消除这种侧信道。
本仓库是这些概念的教育性实验室实现,旨在用于受控的安全研究和可重复性。
## 实验室结构
本实验室包含五个协同工作的主要文件:
- [Server.py](Server.py):Flask 服务器和决策逻辑
- [static/stager.js](static/stager.js):浏览器端编排器和计时收集器
- [DNSFowarder.py](DNSFowarder.py):故意设为易受攻击的 DNS 缓存转发器
- [setup.sh](setup.sh):环境设置与清理自动化
- [victim.sh](victim.sh):模拟受害者的 DNS 活动
这些组件通过以下序列进行交互,以模拟和测量计时攻击:
1. 浏览器从 [Server.py](Server.py) 加载 Flask 页面
2. 页面注入运行时配置并执行 [static/stager.js](static/stager.js)
3. stager 循环经历校准和攻击模式,测量计时,并将结果提交到 Flask 端点
4. DNS 查询通过 [DNSFowarder.py](DNSFowarder.py) 路由,这会暴露出可观察的 HIT/MISS 延迟差异
5. [victim.sh](victim.sh) 不断查询选定的域名,从而产生真实的缓存重新填充行为
### 设置环境
[setup.sh](setup.sh) 负责自动化实验室环境的配置、初始化和清理。它必须使用 root 权限 (`sudo`) 执行。
**1. 初始安装 (`--install`)**
用于首次执行。它会安装依赖项并配置系统限制:
- 下载易受攻击的 Chromium v133 快照并将其解压到 `./chrome_v133`
- 创建 Python 虚拟环境 (`.venv`) 并安装 `dnslib` 和 `flask`
- 配置 `iptables` 规则以拒绝到端口 0 的出站 TCP 连接
- 覆盖 `/etc/resolv.conf` 以强制使用本地 DNS 解析 (`nameserver 127.0.0.1`)
- 授予 [victim.sh](victim.sh) 执行权限
- 激活虚拟环境
**2. 常规执行 (无参数标志)**
用于实验室已安装但需要重新应用系统设置的情况(例如,重启或网络重置后):
- 跳过 Chromium 下载和 Python 依赖项安装
- 重新应用阻止端口 0 的 `iptables` 规则
- 重新应用 `/etc/resolv.conf` 的本地解析器覆盖
- 激活虚拟环境
**3. 清理 (`--cleanup`)**
用于在测试后将系统恢复到其原始状态:
- 停用虚拟环境
- 删除针对端口 0 的 `iptables` 规则
- 通过清除 `/etc/resolv.conf` 并重启 `NetworkManager` 来恢复标准 DNS 解析
- 删除临时的 Chromium 配置文件目录 (`/tmp/chromium-DNSFlare`)
### 概念验证:
#### 服务端 [Server.py](Server.py):
服务器的主要职责是托管 Web 界面并处理传入的校准和攻击测量数据。它利用这些指标来计算并存储每个目标的阈值,最终通过记录最终的 HIT 或 MISS 预测来结束其执行循环。
函数:
1. `index()`
- 提供 HTML + 引导程序 `window.DNSFlareConfig`
- 将服务器端配置链接到客户端脚本
- 加载在浏览器中运行攻击逻辑的 [stager.js](static/stager.js) 脚本
2. `calibrate()`
- 接收 `{target, hit, miss, iteration}` 并将值附加到 `CALIBRATION[target]['hits']` 和 `CALIBRATION[target]['misses']` 中
- 在最后一次迭代时,计算:$threshold = (median(HITs) + median(MISSes)) / 2$
2. `attack()`
- 接收 `{target, time}` 并将 `time` 与 `CALIBRATION[target]['threshold']` 进行比较
- 当 `time <= threshold` 时预测为 HIT,否则为 MISS
- 记录每次预测,在攻击阶段不重新训练阈值
#### 客户端 [stager.js](static/stager.js):
执行攻击状态机的客户端脚本。它负责生成缓存压力,测量计时差异以及将信息传输到服务器。
函数:
1. `flush()`
- 生成对 `f0..f19.s2.mov.lat` 的 fetch 请求
- 这会创建恶意的虚假 DNS 条目(每次 fetch 生成 100 条),它们会填满转发器缓存并驱逐先前的条目,包括目标域名
2. `measureTime(domain)`
- 执行准备性探测,然后测量围绕 `fetch('http://' + domain + ':0/')` 的耗时
- 测量并返回计时,完成 (COMPLETE) 侧信道过程
3. `main()`
- 执行以下流程:
- `start`
- `calibrate_miss`
- `calibrate_hit`
- `attack` (循环)
- 通过 URL 查询参数保存状态
- 向 `/calibrate` 提交校准载荷
- 向 `/attack` 提交攻击载荷
- 轮换源并无限重复
### 易受攻击的 DNS 转发器:
[DNSFowarder.py](DNSFowarder.py) 为了测试目的,被故意构建为一个易受攻击的 DNS 缓存组件。
我们的 DNS 转发器绑定到 `127.0.0.1:53` 以拦截 DNS 请求。它对 `.localhost` 域的 A 记录查询直接返回 `127.0.0.1`,而对于所有其他域名,它首先检查其内部队列缓存。在发生 cache MISS 时,它会将请求转发给上游解析器 (`8.8.8.8`),将响应对象中的 TTL 置零,并将生成的 A 记录插入其本地队列。
这个组件之所以易受攻击,是因为与每个域名分配一个缓存槽的现代转发器不同,此实现使用了基于 IP 的先进先出 (FIFO) 架构,其中每个返回的 IP 地址都会占用一个单独的槽。这种脆弱的队列管理被 PoC 适配明确利用,该适配强制使用 TCP 连接来查询虚假域名 `s2.mov.lat`。因为该域名返回 100 个 IP 地址——超过了标准 512 字节的 DNS UDP 限制——强制 TCP 确保了海量载荷被完整检索而不会被截断。因此,查询单个域名会立即淹没并刷新整个缓存,允许攻击者毫不费力地操纵缓存状态,并通过简单的响应时间观察来推断域名的存在性。
### 受害者模拟器行为:victim.sh
[victim.sh](victim.sh) 模拟定期解析目标域名的良性用户行为。
此脚本接受一个或多个域名作为参数,在无限循环中每隔几秒执行一次 `dig @127.0.0.1 ` 以定期重新填充缓存。由于攻击者脚本无法直接强制受害者访问,因此该组件对于生成外部缓存活动至关重要。通过模拟这种真实的后台用户行为,它使攻击者端的分类器能够持续观察并测量目标域名随时间推移从 MISS 到 HIT 的转变。
## 与原始工件 PoC 的差异
本实验室的实现依赖于优先考虑演示和验证目的的决策选择。以下是该模型采用的主要设计决策及相关技术权衡的概述:
1. **更简单的分类模型:** 本实验室使用针对每个目标的中位数中点阈值处理,以确保更高的可解释性、更少的依赖性和更容易的调试。然而,在嘈杂的环境中,这种方法不如丰富的统计或机器学习模型表现力强。
2. **显式的客户端状态机:** 状态控制通过 URL 查询参数集中在 static/stager.js 中,以提供更清晰的观察性和更简单的迭代。其代价是,持续的 URL 更新和显眼的浏览器编排使得执行过程变得嘈杂且极易被检测到。
3. **配置驱动的实验:** 目标和计时行为被配置为运行时参数,使得重复实验更加容易,无需修改代码。
4. **操作可观察性:** 系统日志使用带时间戳的行明确区分了校准和攻击阶段,以促进更容易的解释和可重复性。
## 结果
通过分析攻击者 (终端 1)、DNS 转发器 (终端 2) 和受害者 (终端 4) 之间的同步日志,我们可以清楚地观察到对 DNS 缓存侧信道的成功利用。该攻击完全通过计时变化正确推断出了用户活动。
### 1. 校准阶段 (19:31:37 - 19:32:13)
攻击者脚本首先分析环境以建立可靠的计时阈值
- **终端 1** 记录了目标域名的模拟缓存命中和未命中之间的计时变化
- **终端 2** 确认了机制,显示了交替出现的 `[MISS]`(从 `8.8.8.8` 获取)和 `[HIT]` 解析,其间穿插着使用 `s2.mov.lat` 域名进行的大规模缓存循环以强制刷新队列
- **计算出的阈值:** 脚本为 `vimeo.com` 确立的边界为 `14.15ms`,为 `instagram.com` 确立的边界为 `17.75ms`
### 2. 空闲攻击阶段 (19:32:22 - 19:32:56)
攻击者过渡到主动监控循环。
- **终端 4:** 受害者当前处于不活跃状态
- **终端 1:** 脚本正确预测 `vimeo.com` 和 `instagram.com` 均为 `MISS`,响应时间保持在阈值以上,由于上游查询经常达到 80-120ms 范围
### 3. 受害者访问目标 1:vimeo.com (19:32:58 - 19:33:43)
- **终端 4:** 在 `19:32:58`,受害者脚本模拟用户主动浏览 `vimeo.com`,定期查询该域名
- **终端 2:** 转发器日志显示,由于受害者的后台活动,`vimeo.com` 不断被加载到缓存中,自然地抵抗了攻击者的缓存驱逐
- **终端 1:** 在 `19:33:04`,攻击者的浏览器记录到 `vimeo.com` 的解析时间急剧下降 (3.10ms),正确预测为 `HIT`。它持续跟踪此状态,而 `instagram.com` 则正确地保持为 `MISS`
### . 受害者切换到目标 2:instagram.com (19:34:16 - 19:34:55)
- **终端 4:** 受害者终止 `vimeo.com` 会话并在 `19:34:16` 开始访问 `instagram.com`
- **终端 1:** 到 `19:34:21` 时,攻击者的计时测量准确反映了这种行为的转变。`instagram.com` 的解析时间降至 3.10ms (`HIT`),而 `vimeo.com` 由于缺乏请求而飙升回 104.50ms (`MISS`)
- **终端 2:** 转发器日志确认 `instagram.com` 现在自然存活于缓存中,而 `vimeo.com` 的请求再次导致被路由到 `8.8.8.8` 的 `MISS`
## 使用流程
这是重现 PoC 的推荐安全流程。
### 1. 准备隔离环境
- 首选 VM/沙盒
- 确保你拥有 `sudo` 权限
- 确保在测试期间没有关键生产服务依赖于本地 DNS
### 2. 克隆并安装实验室
```
git clone https://github.com/phlipow/DNSFlareLab.git DNSFlareLab
cd DNSFlareLab
sudo ./setup.sh --install
```
### 3. 启动组件
终端 1:
```
sudo ./.venv/bin/python Server.py --targets [,,...]
```
终端 2:
```
sudo ./.venv/bin/python DNSFowarder.py
```
终端 3:
```
./chrome_v133/chrome-linux/chrome \
--user-data-dir=/tmp/chromium-DNSFlare \
--test-type \
--disable-background-timer-throttling \
--ignore-certificate-errors \
--no-sandbox \
--disable-gpu \
--explicitly-allowed-ports=0 \
--disable-features=dns-over-https \
--disable-host-cache
```
在 Chromium 中,浏览到:[http://127.0.0.1](http://127.0.0.1)
终端 4:
```
./victim.sh
```
### 4. 测试后立即清理
```
sudo ./setup.sh --cleanup
```
### 6. 安全说明
- 本实验室会更改系统解析器行为和防火墙规则
- 不要使用此浏览器配置文件进行正常浏览
- 如果清理失败,在离开实验室环境之前,请手动恢复解析器/网络并删除 iptables 规则
标签:DNSFlare, DNS攻击, DNS缓存, DNS缓存投毒, Flush-Reload, PoC, Reload攻击, USENIX Security, Web安全, 侧信道攻击, 内核驱动, 多模态安全, 安全漏洞, 密码管理, 插件系统, 数据可视化, 时间侧信道, 暴力破解, 概念验证, 用户行为分析, 缓存穿透, 网络协议, 网络安全, 蓝队分析, 逆向工具, 隐私保护, 隐私泄露