事情从不简单直到它变得简单(Dell UnityVSA预认证命令注入CVE-2025-36604)
欢迎回来,这一周真是精彩!我们为你经历的一切感到高兴和/或遗憾。事情会变得更好和/或更糟,但你很可能能够挺过去。
今天,我们将沿着花园小径漫步,深入档案库,发布我们对2025年3月在Dell UnityVSA解决方案中发现并披露给戴尔的一个漏洞的分析。
作为我们持续增强watchTowr平台中先发制人暴露管理技术的一部分,我们在利用watchTowr平台的组织的攻击面中看到的技术上执行零日漏洞研究。这为我们的客户提供了主动防御,并在我们与供应商和项目联系以寻求适当修复的同时,提供了漏洞的前瞻性可见性。
3月,我们报告了Dell UnityVSA版本5.5.0.0.5.259(我们假设早期版本也存在)中的一个预认证命令注入漏洞。一如既往,我们更容易像机器人一样引用这个漏洞,使用充满爱意分配的CVE-2025-36604。
Dell UnityVSA(虚拟存储设备)是Dell Unity存储平台的软件定义版本。UnityVSA不是运行在专用的Dell存储硬件上,而是作为虚拟机在VMware ESXi等管理程序上运行,为您提供大部分Unity功能的纯软件包。
众所周知,存储及围绕存储生态系统的解决方案对互联网居民具有实质性意义,主要且明显的原因是它们提供了通往敏感数据的清晰路径,这些数据要么1.可用,要么2.可被勒索软件加密。
带着这个令人振奋和激励的事实,让我们开始吧…
UnityVSA、戴尔和14个CVE
为了铺垫背景,让我们看看戴尔发布补丁后UnityVSA的情况 - 迅速被戴尔Unity安全发布说明打脸(可能是友好的):
有人设法找到了14个(是的,十四个!)预认证命令注入漏洞 - 我们可以通过两种方式看待这些信息:
- 垃圾场大火,或者,
- 现在这是一个清理过的、编写良好且安全的代码库。
我们不得不弄清楚 - 神秘感和潜在的惊喜太诱人了 - 于是我们很快地对修补后的漏洞进行了差异比较。
我们使用了:
- Dell UnityVSA 5.4.0.0.5.094(已知存在漏洞)
- Dell UnityVSA 5.5.0.0.5.259(假设通过14个全面补丁后完美)
AccessTool.pm
在差异结果中,有一个文件特别引起了我们的注意。AccessTool.pm站在那里 - 嘲笑着我们,并可能扮演着我们补丁差异分析焦点的罪魁祸首:
快速浏览Perl模块显示了多个修复 - 包括开发人员以注释形式给自己的有用提醒,关于一些讨厌的不需要的命令注入问题。
当然,这本身并不坏,我们讨论过"代码异味"的概念 - 这是我们大脑转化为直觉的指标。让我们看看。
该代码片段位于一个名为getCASURL的Perl函数内部。
差异显示,对于有灵感的人来说,这看起来像是一个教科书式的Perl命令注入 - 攻击者影响的值(如$host)被拼接成一个单一的$exec_cmd字符串。在修补版本中,相同的输入被包裹在单引号中,以尝试消除shell元字符。
最后的致命一击是$exec_cmd使用经典的Perl反引号运算符运行,因此任何转义失误都是您远程命令执行所需的全部。
getCASURL
此时,我们问自己:在这个显然强大的代码库中是否还有更多?
再看一下上面的截图。你看到我们看到的了吗?让我们放大。
事实证明,如果$type设置为字面值"login",那么在574行,$uri直接连接到我们的$exec_cmd - 最终命令中。
明显的问题:为什么这个变量没有被转义?在其他任何地方,开发人员都花时间转义输入,但这里没有。他们是否假设它不受攻击者控制?或者我们正在观察未来的工作保障?
无论哪种方式……唉。
为了理解我们如何到达上面的代码片段,重要的是要注意代码驻留在一个名为getCASURL的函数中:
要到达$uri被连接的代码部分,传递给getCASURL的最终参数 - $type - 必须等于字面值"login"。这是控制连接逻辑的唯一条件;如果不满足,所讨论的代码路径将永远不会执行。
考虑到这一点,下一步是审查getCASURL的每个调用者,以识别$type被设置为"login"(或可以被影响成为"login")的地方。映射这些调用站点让我们将理论路径与实际可到达的路径分开,并将我们的分析集中在重要的场景上。
跟踪调用链
有了这个门控条件,明显的下一步是追踪谁实际调用了getCASURL:
这个函数有两个调用站点。如果执行到达getCASLoginURL,最终参数被设置为字面值"login",这满足了命中$uri连接所需的条件。
下一步是继续搜索并识别getCASLoginURL的每个调用者。映射这些调用站点将显示此路径在实践中的执行时间,并帮助我们评估实际的可达性。
进一步跟踪,我们发现调用源自make_return_address() - 这就是它变得有趣的地方:
进入getCASLoginURL的路径起源于make_return_address()。该助手通过标准的Perl调用$r->uri()检索入站请求URI,然后使用该值调用getCASLoginURL。
当我们看到AccessHandler.pm如何使用它时,情节变得更加复杂。
继续跟踪,make_return_address()从AccessHandler.pm被调用。该模块中的handler()函数在第153行检查请求是否缺少cookie。如果不存在cookie,用户被视为未认证,并被重定向到登录页面,这会触发使用当前HTTP上下文调用make_return_address($r)。
Apache配置
当然,除非处理程序实际执行,否则这一切都不重要。答案位于Apache的配置中:
正如我们所见,Apache的配置为相关请求范围注册了该函数。
在httpd.conf中,我们观察到一个配置条目将匹配的请求路由到AccessHandler::handler,确保在处理请求期间调用该模块。
实际上,这意味着handler()为落入该范围的每个传入请求运行。当请求到达时没有预期的cookie,代码通过调用make_return_address($r)触发重定向到登录流程,这反过来导致getCASLoginURL(…)。该路径仅在$type等于"login"时到达$uri连接。
这实际上意味着开发人员通过使用PerlModule指令加载Perl模块,注册了一个要在每个请求上执行的回调。因此,AccessHandler::handler为Web服务器处理的每个请求调用。
流程映射
这是几个移动部分 - 让我们退后一步映射流程:
|
|
完美。这意味着我们可以通过向任何在请求URI中包含有效命令注入负载的页面发出HTTP请求来执行登录重定向路径。我们必须确保请求不携带认证cookie,以便触发处理程序。
事情从不简单直到它变得简单
链清晰了,下一个问题很明显:当我们尝试时会发生什么?
起初,看起来我们有一个明确的胜利。但现实有其他计划(一如既往):
我们的第一次尝试失败了:因为URI没有指向有效资源,Perl模块从未触发。
这很好地解释了为什么这个路径可能长时间未被发现 - 没有解析,没有处理程序,没有漏洞。
但是,如果我们给它一个确实需要解析的URI呢?在这种情况下,处理程序开始行动,突然我们一直在追逐的代码路径可能变得活跃。
检测工件生成器
按照惯例,我们分享此漏洞的检测工件生成器 - 使团队能够识别其环境中的易受攻击主机。
时间线
我们要感谢Dell PSIRT在处理此安全报告时的专业精神和响应能力。
| 日期 | 详情 |
|---|---|
| 2025年3月28日 | WT-2025-0037被发现并披露给戴尔。 |
| 2025年3月28日 | watchTowr开始在客户端攻击面上寻找漏洞。 |
| 2025年3月31日 | 戴尔确认收到WT-2025-0037报告并打开票据VRT-29331。 |
| 2025年7月31日 | 戴尔PSIRT发布安全公告,随后发布产品新版本(5.5.1)。 |
| 2025年10月3日 | 博客文章发布。 |