CVE-2022-27925 Zimbra Collaboration 存在路徑穿越漏洞最終導致RCE
漏洞信息
前段時間 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 :
