b2uerry/tl-wr902ac-cve-2026

GitHub: b2uerry/tl-wr902ac-cve-2026

该项目披露了 TP-Link TL-WR902AC 路由器 RADIUS 认证模块因使用未播种的 random() 导致认证符可预测的高危漏洞(CWE-338),并提供了完整的 PoC 与修复方案。

Stars: 0 | Forks: 0

# CVE 提交包 # TP-Link TL-WR902AC v4 - rt2860apd 中的 CWE-338 ## 1. 漏洞概述 **标题:** 由于未播种的 `random()` 导致 rt2860apd 中的 RADIUS Authenticator 可预测 **CWE:** CWE-338 - 使用密码学上较弱的伪随机数生成器 (PRNG) **产品:** TP-Link TL-WR902AC v4 (旅行路由器) **受影响固件:** EU_0.9.3_0.3 (2025-08-21 构建,发布版本 43848) - 二进制文件:/usr/bin/rt2860apd (Ralink DOT1X daemon,版本 2.6.0.0) - 固件 MD5:84d5acf2f429fa8868d80f7723bfe70b - 二进制文件链接库:uClibc 0.9.33.2 **严重性:** 高 (CVSS 3.1: 7.5) - 攻击向量:网络 (邻接) - 攻击复杂度:低 - 所需权限:无 - 用户交互:无 - 影响范围:未改变 - 机密性影响:高 (绕过认证) - 完整性影响:高 (伪造 RADIUS 消息) **发现者:** b2uerry **发现日期:** 2026-06-24 ## 2. 技术描述 ### 2.1 受影响组件 `rt2860apd` 是 Ralink/MediaTek WiFi Access Point daemon,负责: - 802.1X/WPA2-Enterprise 认证 - RADIUS 客户端通信 - WPA 密钥握手 (4-way handshake) 该二进制文件为 MIPS32 little-endian 编译,并动态链接到 uClibc 0.9.33.2。 ### 2.2 根本原因 位于地址 `0x406e8c` 的函数 `Radius_msg_make_authenticator` 通过以下计算生成 RADIUS Request Authenticator 字段: ``` int Radius_msg_make_authenticator(RADIUS_MSG *msg, void *station, int len) { struct timeval tv; int rand_val; gettimeofday(&tv, NULL); // 0x406e9c rand_val = random(); // 0x406eb0 MD5_Init(&ctx); // 0x406eb8 MD5_Update(&ctx, &tv, 8); // 0x406ec4 MD5_Update(&ctx, station, 4); // 0x406ed0 MD5_Update(&ctx, &rand_val, 4); // 0x406edc MD5_Final(msg->authenticator, &ctx); // 0x406ef0 } ``` 因此,该 authenticator 为: ``` MD5( tv_sec || tv_usec || station_data[0:4] || random() ) ``` ### 2.3 为什么存在漏洞 对 rt2860apd 的完整二进制审计显示: 1. **从未调用 `srandom()`。** 符号 `srandom` 既没有导入,也没有出现在 PLT 中。完整的交叉引用搜索结果为零。 2. **根据 C 标准和 glibc 的行为**,在没有预先调用 `srandom()` 的情况下调用 `random()` 时,PRNG 默认 seed = 1。所有输出 100% 是确定性的。 3. **`gettimeofday()` 提供了微秒精度**,但是根据数据包捕获时间戳,`tv_sec` 的值可以在几秒钟内被预测。 4. **同一二进制文件中的其他函数使用了 `hostapd_get_rand()`** (该函数从 `/dev/urandom` 读取),但 `Radius_msg_make_authenticator` 并未使用。 ### 2.4 攻击场景 同一网段上的攻击者可以: 1. 捕获设备发送的 RADIUS Access-Request 数据包 2. 提取 16 字节的 Authenticator 字段 3. 知道 (或猜测) `station_data` 的 4 字节值 4. 估算数据包时间戳 (相对于 pcap 时间 ±2 秒) 5. 为每个候选秒数暴力破解 `tv_usec` (0-999,999) 6. 为每个候选值计算 `MD5(tv || station_data || 0x6b8b4567)` 7. 与捕获的 authenticator 进行匹配 每秒不确定性的搜索空间为 2,000,000 个 MD5 哈希,在单个 CPU 核心上大约 1.3 秒即可完成。 **影响:** 攻击者可以预测下一个 RADIUS authenticator,从而能够: - 伪造 RADIUS 消息 - 绕过 802.1X 认证 - 未经授权访问网络 ## 3. 概念验证 PoC 以附加包中的 `final_proof.py` 形式提供。 它演示了: ### 证明 1:`random()` 的确定性 ``` $ python3 final_proof.py random() seed=1, 3 independent resets: [0] = 1804289383 (0x6b8b4567) ← identical across all resets [1] = 846930886 (0x327b23c6) [2] = 1681692777 (0x643c9869) ... ``` ### 证明 2:Authenticator 预测测试向量 提供了四个测试向量以供独立验证。 示例: ``` Input: tv_sec=0x60000000, tv_usec=0x00000000, station=0x00000000 random()=0x6B8B4567 (deterministic, seed=1) Output: MD5 = 06691441de1006440050152c8fcbf00d ``` ### 证明 3:暴力破解可行性 ``` Target authenticator: 0f850ee3cdce057898d426ebdd694a4c ±1 second search: 1,500,001 MD5 candidates Time to match: 1.08 seconds Result: EXACT MATCH (tv_sec=1782286400, tv_usec=500000) ``` ### 证明 4:跨架构验证 MIPS (QEMU 用户模式) 和 x86 (本地) 的 `random()` 产生相同的输出: ``` MIPS: [1804289383, 846930886, 1681692777, 1714636915, 1957747793] x86: [1804289383, 846930886, 1681692777, 1714636915, 1957747793] ``` glibc 和设备使用的 uClibc 0.9.33.2 都为 `random()` 实现了相同的 BSD libc TYPE_3 多项式。依赖 seed 的输出与架构无关。 ## 4. 补救措施 将对 `random()` 的调用替换为密码学安全的源: ``` // Vulnerable: rand_val = random(); // Fixed: hostapd_get_rand(&rand_val, sizeof(rand_val)); // (hostapd_get_rand already exists in the binary at 0x407400 // and reads from /dev/urandom) ``` 注意:同一二进制文件中的 `ieee802_1x_tx_key()` 和 `Config_read()` 已经使用了 `hostapd_get_rand()`,这证实了该修复是最小化且非侵入性的。 ## 5. 披露时间线 - 2026-06-22:在固件分析中发现漏洞 - 2026-06-24:PoC 开发并验证完成 (3/3 独立证明) - 2026-06-24:请求 CVE / 通知供应商 - 待定: 供应商回复 ## 6. 参考资料 - CWE-338: https://cwe.mitre.org/data/definitions/338.html - RFC 2865 - RADIUS: https://datatracker.ietf.org/doc/html/rfc2865 - IEEE 802.1X-2010 - Port-Based Network Access Control
标签:CVE, IoT安全, 密码学缺陷, 数字签名, 漏洞披露, 路由器漏洞, 身份验证强制, 逆向分析, 逆向工具, 防御绕过