利用 zimbra clientuploader 实现文件上传

发布于 2024-08-26 07:29:08 字数 7812 浏览 20 评论 0

0x00 前言

Zimbra 邮件服务器的管理面板支持文件上传的功能,通常情况下,我们通过管理员用户登录管理面板,使用名为 Client Upload 的功能即可将文件上传至 Zimbra 邮件服务器的 downloads 目录。

这里面我们需要进一步的思考,实现文件上传的方法有哪些?如何禁用文件上传的功能?能否通过第三方扩展或者插件实现文件上传?能否绕过?

本文仅在技术研究的角度回答以上问题。

0x01 简介

本文将要介绍以下内容:

  • 原理分析
  • 通过 zimbraAdmin 管理面板实现文件上传
  • 通过 zimlet 实现文件上传
  • 通过 Zimbra SOAP API 实现文件上传
  • 利用思路
  • 防御建议

0x02 原理分析

Zimbra 邮件服务器通过 com_zimbra_clientuploader 实现文件上传的功能

我们可以在 Zimbra 邮件服务器的安装文件中找到文件上传功能对应的文件

对应安装目录下的文件为 /opt/zimbra/lib/ext/com_zimbra_clientuploader/com_zimbra_clientuploader.jar

为了查看具体的实现代码,这里需要对 jar 文件进行反编译,反编译的功能可以使用 JD-GUI,地址: http://java-decompiler.github.io/

使用 JD-GUI 打开 com_zimbra_clientuploader.jar ,文件结构如下图

Alt text

(1) 文件上传功能的主函数

对应文件 ClientUploaderHandler.class

(2) 文件上传功能的写入位置

对应文件 ClientUploaderLC.class ,如下图

Alt text

写入位置为 /opt/zimbra/jetty/webapps/zimbra/downloads

(3) 响应代码对应的内容

对应文件 ZClientUploaderResoCode.class ,如下图

Alt text

内容如下:

  SUCCEEDED(1L, "Succeeded"),
  FAILED(20000000L, "Upload failed"),
  NOT_A_FILE(20000001L, "The request does not upload a file"),
  REPO_INVALID(20000002L, "Invalid directory for client repo or temporary files."),
  REPO_NO_WRITE(20000003L, "No write permission on directory for client repo or temporary files"),
  SAVE_ERROR(20000004L, "Failed to save the upload file"),
  PARSE_REQUEST_ERROR(20000005L, "Failed to parse the request"),
  FILE_EXCEED_LIMIT(20000006L, "File size exceeds allowed max size"),
  MISSING_LIB_PATH(30000001L, "Cannot find lib directory so cannot execute zmupdatedownload"),
  UPDATE_LINK_FAILED(30000002L, "Failed to update links in downloads/index.html"),
  NO_PERMISSION(40000001L, "Permission denied");

可以用来判断上传失败的原因

综合以上代码,我们可以得出以下推断:

  1. com_zimbra_clientuploader 作为 Zimbra 的一部分,保存在安装目录下,实现文件上传的功能,提供文件上传的接口
  2. 通过 Zimbra 管理面板能够安装第三方插件,一种是扩展 Zimbra 管理面板的功能,对应名称为 Admin Extensions,另一种是扩展客户端的功能,对应名称为 Zimlets
  3. 无论是 Admin Extensions 还是 Zimlets,实现文件上传都要调用 com_zimbra_clientuploader 提供的文件上传接口。反过来说,只要禁用了 com_zimbra_clientuploader 提供的文件上传接口,那么使用 Admin Extensions 和 Zimlets 都无法实现文件上传。

下面分别介绍三种实现文件上传的方法并验证我们的推断。

0x03 通过 zimbraAdmin 管理面板实现文件上传

通过管理员用户登录管理面板,选择 Tools and Migration -> Client Upload ,如图

Alt text

上传成功后,Zimbra 邮件服务器的保存路径: /opt/zimbra/jetty/webapps/zimbra/downloads

0x04 通过 zimlet 实现文件上传

Zimlets 用来扩展客户端的功能,也就是说,当安装了 Zimlets,使用普通用户登录邮箱时,就能够访问已安装的 Zimlets

如下图

Alt text

Zimlets 的开发可以参考 https://wiki.zimbra.com/wiki/Zimlet_Developers_Guide:Example_Zimlets

注:

Zimlets 支持运行 jsp 文件,但是默认关闭该功能

查看是否开启的命令:

zmprov gs <mail domain name> | grep zimbraZimletJspEnabled

启用 Zimbra 执行 jsp 的命令:

zmprov ms <mail domain name> zimbraZimletJspEnabled TRUE
zmcontrol restart

这里举例进行说明,使用示例 Zimlets Simple_JSP_via_Action ,下载地址:https://wiki.zimbra.com/wiki/ZCS_6.0:Zimlet_Developers_Guide:Examples:Simple_JSP_via_Action

通过 Zimbra 管理面板进行安装,如下图

Alt text

选择安装文件 com_zimbra_example_simplejspaction.zip

使用普通用户登录邮箱,在 Zimlets 下能够访问已安装的 Zimlets,如下图

Alt text

点击后,发现 jsp 文件能够访问,但是无法运行,如下图

Alt text

这里我找到了一种有趣的文件上传方法:虽然无法运行 jsp 文件,但是可以运行 html 文件,那么我们何不通过 html 实现文件上传呢?

新建文件 upload.html,内容如下:

<html>
<body>
<form method=POST ENCTYPE="multipart/form-data" ACTION="https://<url>/service/extension/clientUploader/upload" METHOD=POST>
<input type="file" name="xxx" />
<input type="submit" value="submit" />
</form>
</body>
</html>

其中, <url> 需要替换为 Zimbra 邮件服务器对应的 url

将 upload.html 压缩到 com_zimbra_example_simplejspaction.zip 中,重新通过 Zimbra 管理面板进行安装

使用普通用户登录邮箱,访问 https://<url>/zimlet/com_zimbra_example_simplejspaction/upload.html

如下图

Alt text

直接上传会失败,这是因为普通用户没有上传文件的权限

这里可以通过修改 Cookie 的方式,实现文件上传

添加 Cookie 的名称为 ZM_ADMIN_AUTH_TOKEN ,Cookie 的数值可在登录 Zimbra 管理面板后的 Cookie 中获得

同时要删除普通用户的 Cookie,对应名称为 ZM_AUTH_TOKEN

完整的 Cookie 格式如下图

Alt text

上传成功后,在 Zimbra 邮件服务器的 /opt/zimbra/jetty/webapps/zimbra/downloads 下可以看到对应的文件

为了进一步利用,我们可以尝试添加一个隐藏的 zimlet,这里以名称 com_zimbra_test 为例

com_zimbra_test.xml 的文件内容如下:

<zimlet name="com_zimbra_test"
        version="1.0"
        description="Zimlet test">
    <zimletPanelItem label=" " icon="zimbraIcon">
        <toolTipText> </toolTipText>
    </zimletPanelItem>
</zimlet>

安装后,在用户邮箱内的 Zimlets 中显示为空行,如下图

Alt text

0x05 通过 Zimbra SOAP API 实现文件上传

代码可参考:https://github.com/3gstudent/Homework-of-Python/blob/master/Zimbra_SOAP_API_Manage.py

细节可参考之前的文章《Zimbra-SOAP-API 开发指南 2》

0x06 验证推断

修改 Zimbra 邮件服务器 /opt/zimbra/jetty/webapps/zimbra/downloads 目录的用户访问权限,将 Create and delete files 修改为 List files only

再次使用以上三种方法上传文件,均失败,返回结果如下:

<html><head></head><body onload="window.parent._uploadManager.loaded(20000003,'Upload failed');"></body></html>

20000003 对应的内容为 "No write permission on directory for client repo or temporary files" ,表示权限不够

由此验证了之前的推论:只要禁用了 com_zimbra_clientuploader 提供的文件上传接口,那么使用 Admin Extensions 和 Zimlets 都无法实现文件上传。

0x07 防御建议

禁用 Zimbra 邮件服务器 /opt/zimbra/jetty/webapps/zimbra/downloads 目录的用户写入权限

0x08 小结

本文介绍了 Zimbra 邮件服务器三种实现文件上传的方法,得出结论:只要禁用了 com_zimbra_clientuploader 提供的文件上传接口,去除用户的写权限,使用 Admin Extensions 和 Zimlets 都无法实现文件上传。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

千と千尋

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

xu362930323

文章 0 评论 0

缱倦旧时光

文章 0 评论 0

qq_eXruk9

文章 0 评论 0

遂心如意

文章 0 评论 0

guojiayue1

文章 0 评论 0

愿与i

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文