作者:且听安全
原文链接: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

图片

图片

mExtensionZimbraExtension 类型,并且在 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 :

图片


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1924/