作者:且听安全
原文链接:https://mp.weixin.qq.com/s/2pUW4H1v6mnXtMqTlxZCMA
漏洞信息
前段时间 Zimbra 官方通报了一个 RCE 漏洞 CVE-2022-27925 ,也有小伙伴在漏洞空间站谈到了这个漏洞,上周末在家有时间完成了漏洞的分析与复现。漏洞原理并不复杂,但在搭建环境的过程中遇到了一些坑,下面将分析过程分享给大家。
从描述来看,这是一个 ZIP 压缩包解析导致路径穿越类型的漏洞。
环境搭建
由于直接安装 v9.0.0 或 v8.8.15 默认就是最新版,因此选择安装 v8.8.12。安装过程非常曲折,环境搭建有疑惑的小伙伴可以加入漏洞空间站进行交流。
最终完成安装并启动成功:
通过配置 mailboxd_java_options
加入调试信息:
重启 Zimbra 服务即可打开远程调试:
寻找调用链
漏洞出现在 mboximport
相关的功能中,全盘搜索定位到位于 zimbrabackup.jar
中的 MailboxImportServlet
:
从命名规则和存在的成员函数 doPost
来看, MailboxImportServlet
应该对应一个 Servlet
对象,但是 MailboxImportServlet
继承于 ExtensionHttpHandler
而非 HttpServlet
:
所以还需要寻找某种相互之间的转换关系。我们知道 Zimbra 自定义了 Servlet
对象的基类 ZimbraServlet
,搜索其子类:
定位 ExtensionDispatcherServlet
:
可以找到相关配置:
所以 ExtensionDispatcherServlet
对应的 URL 规则为 /service/extension/*
,回到 ExtensionDispatcherServlet#service
函数:
通过 getHandler
函数来寻找对应的 ExtensionHttpHandler
对象 handler
(前面定位的 MailboxImportServlet
正好继承于 ExtensionHttpHandler
),进入 getHandler
函数:
提取 URL 中 /service/extension
之后的字符串并赋值给 extPath
,带入 getHandler
函数:
返回的 ExtensionHttpHandler
对象来自于 sHandlers
键值对,其中的 key
来自于 ExtensionHttpHandler#getPath
函数,查看定义:
ExtensionHttpHandler#getPath
:
mExtension
为 ZimbraExtension
类型,并且在 init
函数中完成初始化,搜索 ZimbraExtension
子类:
定位 BackupExtension
,里面刚好注册了 MailboxImportServlet
类型:
所以构造特定 URL 将调用 MailboxImportServlet
,测试如下:
成功进入 MailboxImportServlet#doPost
函数处理逻辑。
权限认证分析
下面分析一下 doPost
函数的处理逻辑,首先通过 getAuthTokenFromCookie
从 Cookie 中提取 token 认证信息,并检查是否为管理员权限:
AuthToken authToken = ZimbraServlet.getAuthTokenFromCookie(req, resp);
if (authToken == null || !authToken.isAdmin()) {
Log.mboxmove.warn("Auth failed");
this.sendError(resp, 403, "Auth failed");
}
进入 getAuthTokenFromCookie
:
因为这里 isAdminReq
默认为 false
,因此认证后需要携带 ZM_AUTH_TOKEN
的 Cookie 值,而非 ZM_ADMIN_AUTH_TOKEN
:
漏洞点定位
通过权限检查后,将会进行一系列参数提取与判断,当提供的 account-name
等参数通过验证后,将进入第 152 行 importFrom
函数:
其中 in
来自于 POST 请求数据包,进入 importFrom
函数:
提取 ZIP 压缩包,调用 restore
函数:
进入 getAccountSession
函数:
实例化 ZipBackupTarget.RestoreAcctSession
对象,进入构造函数:
跟进 unzipToTempFiles
函数:
ZIP 压缩包解压过程存在路径穿越漏洞,导致可以向任意路径写入 shell 。
漏洞复现
通过上述分析,我们可以构造一个存在路径穿越的 ZIP 压缩包,并发送特定 POST 请求实现压缩包解压路径穿越:
最终写入 shell :
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1924/