def audit(self): callbaks = ["callback", "cb", "json"] params = self.requests.params isBreak = True for p in params.keys(): if p.lower() in callbaks: isBreak = False break if isBreak: return result = self.check_sentive_content(self.response.text) if not result: return p = urlparse(self.requests.url) fake_domain = "{}://{}".format(p.scheme, p.netloc) + random_str(4, string.ascii_lowercase + string.digits) + ".com/" headers = self.requests.headers headers["Referer"] = fake_domain req = requests.get(self.requests.url, headers=headers) result2 = self.check_sentive_content(req.text) if not result2: return result = ResultObject(self) result.init_info(self.requests.url, "jsonp敏感信息", VulType.SENSITIVE) result.add_detail("payload探测", self.requests.raw, self.response.raw, "发现敏感信息:{}".format(repr(result2)), "", "", PLACE.GET) self.success(result)
def audit(self): vul_reg = [r"(\.html\([^\)]\))"] if self.check_jquery(): for _ in vul_reg: text = re.findall(_, self.response.text, re.M | re.I) issuc = False if text: for t in set(text): ignores = ['function'] iscontinue = True for i in ignores: if i in t: iscontinue = False break if not iscontinue: continue result = ResultObject(self) result.init_info(self.requests.url, "页面中存在.HTML绕过", VulType.SENSITIVE) result.add_detail("payload探测", self.requests.raw, self.response.raw, "根据正则:{} 发现敏感信息:{}".format(_, text), "", "", PLACE.GET) self.success(result) issuc = True break if issuc: break
def audit(self): if self.requests.suffix != ".js": return regx = [ # 匹配url # r'(\b|\'|")(?:http:|https:)(?:[\w/\.]+)?(?:[a-zA-Z0-9_\-\.]{1,})\.(?:php|asp|ashx|jspx|aspx|jsp|json|action|html|txt|xml|do)(\b|\'|")', # 匹配邮箱 r'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+', # 匹配token或者密码泄露 # 例如token = xxxxxxxx, 或者"apikey" : "xssss" r'\b(?:secret|secret_key|token|secret_token|auth_token|access_token|username|password|aws_access_key_id|aws_secret_access_key|secretkey|authtoken|accesstoken|access-token|authkey|client_secret|bucket|email|HEROKU_API_KEY|SF_USERNAME|PT_TOKEN|id_dsa|clientsecret|client-secret|encryption-key|pass|encryption_key|encryptionkey|secretkey|secret-key|bearer|JEKYLL_GITHUB_TOKEN|HOMEBREW_GITHUB_API_TOKEN|api_key|api_secret_key|api-key|private_key|client_key|client_id|sshkey|ssh_key|ssh-key|privatekey|DB_USERNAME|oauth_token|irc_pass|dbpasswd|xoxa-2|xoxrprivate-key|private_key|consumer_key|consumer_secret|access_token_secret|SLACK_BOT_TOKEN|slack_api_token|api_token|ConsumerKey|ConsumerSecret|SESSION_TOKEN|session_key|session_secret|slack_token|slack_secret_token|bot_access_token|passwd|api|eid|sid|api_key|apikey|userid|user_id|user-id)["\s]*(?::|=|=:|=>)["\s]*[a-z0-9A-Z]{8,64}"?', # 匹配IP地址 r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b', # 匹配云泄露 r'[\w]+\.cloudfront\.net', r'[\w\-.]+\.appspot\.com', r'[\w\-.]*s3[\w\-.]*\.?amazonaws\.com\/?[\w\-.]*', r'([\w\-.]*\.?digitaloceanspaces\.com\/?[\w\-.]*)', r'(storage\.cloud\.google\.com\/[\w\-.]+)', r'([\w\-.]*\.?storage.googleapis.com\/?[\w\-.]*)', # 匹配手机号 r'(?:139|138|137|136|135|134|147|150|151|152|157|158|159|178|182|183|184|187|188|198|130|131|132|155|156|166|185|186|145|175|176|133|153|177|173|180|181|189|199|170|171)[0-9]{8}' # 匹配域名 r'((?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+(?:biz|cc|club|cn|com|co|edu|fun|group|info|ink|kim|link|live|ltd|mobi|net|online|org|pro|pub|red|ren|shop|site|store|tech|top|tv|vip|wang|wiki|work|xin|xyz|me))', ] for _ in regx: texts = re.findall(_, self.response.text, re.M | re.I) issuc = False if texts: for text in set(texts): ignores = [ 'function', 'encodeURIComponent', 'XMLHttpRequest' ] iscontinue = True for i in ignores: if i in text: iscontinue = False break if not iscontinue: continue result = ResultObject(self) result.init_info(self.requests.url, "js文件中存在敏感信息", VulType.SENSITIVE) result.add_detail("payload探测", self.requests.raw, self.response.raw, "根据正则:{} 发现敏感信息:{}".format(_, text), "", "", PLACE.GET) self.success(result) issuc = True break if issuc: break
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): 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", '/bin/(bash|sh)[^\r\n<>]*[\r\n]', '\[boot loader\][^\r\n<>]*[\r\n]' ] 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
class W13SCAN(PluginBase): name = 'XSS语义化探测插件' def init(self): self.result = ResultObject(self) self.result.init_info(self.requests.url, "XSS脚本注入", VulType.XSS) def getSSTIPayload(self, randint1=444, randint2=666) -> list: ''' 顺便检测下模板注入~ return ['{123*1111}', '<%=123*1111%>', '#{123*1111}', '${{123*1111}}', '{{123*1111}}', '{{= 123*1111}}', '<# 123*1111>', '{@123*1111}', '[[123*1111]]', '${{"{{"}}123*1111{{"}}"}}'] :return: list ''' r = [] payloads = [ "{%d*%d}", "<%%=%d*%d%%>", "#{%d*%d}", "${{%d*%d}}", "{{%d*%d}}", "{{= %d*%d}}", "<# %d*%d>", "{@%d*%d}", "[[%d*%d]]", "${{\"{{\"}}%d*%d{{\"}}\"}}", ] for item in payloads: r.append(item % (randint1, randint2)) return r 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检测 randnum1 = random.randint(50, 500) randnum2 = random.randint(80, 400) 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: result = self.new_result() result.init_info(self.requests.url, "SSTI模板注入", VulType.XSS) result.add_detail( "payload请求", r1.reqinfo, generateResponse(r1), "payload:{} 会回显{} 不编码payload".format( payload, checksum), k, payload, positon) self.success(result) # url编码请求 r1 = self.req(positon, data) if checksum in r1.text: result = self.new_result() result.init_info(self.requests.url, "SSTI模板注入", VulType.XSS) result.add_detail( "payload请求", r1.reqinfo, generateResponse(r1), "payload:{} 会回显{} url编码payload".format( payload, checksum), k, payload, positon) self.success(result) # html编码请求 r1 = self.req(positon, data) if checksum in r1.text: result = self.new_result() result.init_info(self.requests.url, "SSTI模板注入", VulType.XSS) result.add_detail( "payload请求", r1.reqinfo, generateResponse(r1), "payload:{} 会回显{} html编码payload".format( payload, checksum), k, payload, positon) self.success(result) if len(self.result.detail) > 0: self.success(self.result)
class W13SCAN(PluginBase): name = 'SSTI模板注入探测插件' def init(self): self.result = ResultObject(self) self.result.init_info(self.requests.url, "模板注入", VulType.SSTI) def getSSTIPayload(self, randint1=444, randint2=666) -> list: ''' 顺便检测下模板注入~ return ['{123*1111}', '<%=123*1111%>', '#{123*1111}', '${{123*1111}}', '{{123*1111}}', '{{= 123*1111}}', '<# 123*1111>', '{@123*1111}', '[[123*1111]]', '${{"{{"}}123*1111{{"}}"}}'] :return: list ''' r = [] payloads = [ "{%d*%d}", "<%%=%d*%d%%>", "#{%d*%d}", "${{%d*%d}}", "{{%d*%d}}", "{{= %d*%d}}", "<# %d*%d>", "{@%d*%d}", "[[%d*%d]]", "${{\"{{\"}}%d*%d{{\"}}\"}}", ] for item in payloads: r.append(item % (randint1, randint2)) return r 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, position in iterdatas: if position == PLACE.URI: continue for k, v in origin_dict.items(): v = unquote(v) if v not in resp: continue data = copy.deepcopy(origin_dict) # ssti检测 r1 = self.test_ssti(data, k, position) if r1: r2 = self.test_ssti(data, k, position) if r2: result = self.new_result() result.init_info(self.requests.url, "SSTI模板注入", VulType.SSTI) result.add_detail("第一次payload请求", r1["request"], r1["response"], r1["desc"], k, r1["payload"], position) result.add_detail("第二次payload请求", r2["request"], r2["response"], r2["desc"], k, r2["payload"], position) self.success(result) break if len(self.result.detail) > 0: self.success(self.result) 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 != ".js": return regs = { "Slack Token": "(xox[p|b|o|a]-[0-9]{12}-[0-9]{12}-[0-9]{12}-[a-z0-9]{32})", "RSA private key": "-----BEGIN RSA PRIVATE KEY-----", "SSH (DSA) private key": "-----BEGIN DSA PRIVATE KEY-----", "SSH (EC) private key": "-----BEGIN EC PRIVATE KEY-----", "PGP private key block": "-----BEGIN PGP PRIVATE KEY BLOCK-----", "Amazon AWS Access Key ID": "AKIA[0-9A-Z]{16}", "Amazon MWS Auth Token": "amzn\\.mws\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", "AWS API Key": "AKIA[0-9A-Z]{16}", "Facebook Access Token": "EAACEdEose0cBA[0-9A-Za-z]+", "Facebook OAuth": "[f|F][a|A][c|C][e|E][b|B][o|O][o|O][k|K].*['|\"][0-9a-f]{32}['|\"]", "GitHub": "[g|G][i|I][t|T][h|H][u|U][b|B].*['|\"][0-9a-zA-Z]{35,40}['|\"]", "Generic API Key": "[a|A][p|P][i|I][_]?[k|K][e|E][y|Y].*['|\"][0-9a-zA-Z]{32,45}['|\"]", "Generic Secret": "[s|S][e|E][c|C][r|R][e|E][t|T].*['|\"][0-9a-zA-Z]{32,45}['|\"]", "Google API Key": "AIza[0-9A-Za-z\\-_]{35}", "Google Cloud Platform API Key": "AIza[0-9A-Za-z\\-_]{35}", "Google Cloud Platform OAuth": "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com", "Google Drive API Key": "AIza[0-9A-Za-z\\-_]{35}", "Google Drive OAuth": "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com", "Google (GCP) Service-account": "\"type\": \"service_account\"", "Google Gmail API Key": "AIza[0-9A-Za-z\\-_]{35}", "Google Gmail OAuth": "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com", "Google OAuth Access Token": "ya29\\.[0-9A-Za-z\\-_]+", "Google YouTube API Key": "AIza[0-9A-Za-z\\-_]{35}", "Google YouTube OAuth": "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com", "Heroku API Key": "[h|H][e|E][r|R][o|O][k|K][u|U].*[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}", "MailChimp API Key": "[0-9a-f]{32}-us[0-9]{1,2}", "Mailgun API Key": "key-[0-9a-zA-Z]{32}", "Password in URL": "[a-zA-Z]{3,10}://[^/\\s:@]{3,20}:[^/\\s:@]{3,20}@.{1,100}[\"'\\s]", "PayPal Braintree Access Token": "access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}", "Picatic API Key": "sk_live_[0-9a-z]{32}", "Slack Webhook": "https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8}/[a-zA-Z0-9_]{24}", "Stripe API Key": "sk_live_[0-9a-zA-Z]{24}", "Stripe Restricted API Key": "rk_live_[0-9a-zA-Z]{24}", "Square Access Token": "sq0atp-[0-9A-Za-z\\-_]{22}", "Square OAuth Secret": "sq0csp-[0-9A-Za-z\\-_]{43}", "Twilio API Key": "SK[0-9a-fA-F]{32}", "Twitter Access Token": "[t|T][w|W][i|I][t|T][t|T][e|E][r|R].*[1-9][0-9]+-[0-9a-zA-Z]{40}", "Twitter OAuth": "[t|T][w|W][i|I][t|T][t|T][e|E][r|R].*['|\"][0-9a-zA-Z]{35,44}['|\"]" } finds = [] msg = "" for key in regs: results = re.findall(regs[key], self.response.text, re.M | re.I) if len(results) != 0: for result in results: if len(result) < 100: finds.append(key) msg = msg + "根据{}的正则表达式:{} 发现敏感信息:{} \n".format( key, regs[key], result) if len(finds) > 0: result = ResultObject(self) result.init_info(self.requests.url, "js文件中存在token敏感信息", VulType.SENSITIVE) result.add_detail("payload探测", self.requests.raw, self.response.raw, msg, "", "", PLACE.GET) self.success(result)
def audit(self): if self.requests.suffix != ".js": return regx = { # 匹配url # r'(\b|\'|")(?:http:|https:)(?:[\w/\.]+)?(?:[a-zA-Z0-9_\-\.]{1,})\.(?:php|asp|ashx|jspx|aspx|jsp|json|action|html|txt|xml|do)(\b|\'|")', # 匹配邮箱 "邮箱信息": r'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+', # 匹配token或者密码泄露 # 例如token = xxxxxxxx, 或者"apikey" : "xssss" "Token或密码": r'\b(?:secret|secret_key|token|secret_token|auth_token|access_token|username|password|aws_access_key_id|aws_secret_access_key|secretkey|authtoken|accesstoken|access-token|authkey|client_secret|bucket|email|HEROKU_API_KEY|SF_USERNAME|PT_TOKEN|id_dsa|clientsecret|client-secret|encryption-key|pass|encryption_key|encryptionkey|secretkey|secret-key|bearer|JEKYLL_GITHUB_TOKEN|HOMEBREW_GITHUB_API_TOKEN|api_key|api_secret_key|api-key|private_key|client_key|client_id|sshkey|ssh_key|ssh-key|privatekey|DB_USERNAME|oauth_token|irc_pass|dbpasswd|xoxa-2|xoxrprivate-key|private_key|consumer_key|consumer_secret|access_token_secret|SLACK_BOT_TOKEN|slack_api_token|api_token|ConsumerKey|ConsumerSecret|SESSION_TOKEN|session_key|session_secret|slack_token|slack_secret_token|bot_access_token|passwd|api|eid|sid|api_key|apikey|userid|user_id|user-id)["\s]*(?::|=|=:|=>)["\s]*[a-z0-9A-Z]{8,64}"?', # 匹配IP地址 "IP地址": r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b', # 匹配云泄露 "Cloudfront云泄露": r'[\w]+\.cloudfront\.net', "Appspot云泄露": r'[\w\-.]+\.appspot\.com', "亚马逊云泄露": r'[\w\-.]*s3[\w\-.]*\.?amazonaws\.com\/?[\w\-.]*', "Digitalocean云泄露": r'([\w\-.]*\.?digitaloceanspaces\.com\/?[\w\-.]*)', "Google云泄露": r'(storage\.cloud\.google\.com\/[\w\-.]+)', "Google存储API泄露": r'([\w\-.]*\.?storage.googleapis.com\/?[\w\-.]*)', # 匹配手机号 "手机号": r'(?:139|138|137|136|135|134|147|150|151|152|157|158|159|178|182|183|184|187|188|198|130|131|132|155|156|166|185|186|145|175|176|133|153|177|173|180|181|189|199|170|171)[0-9]{8}', # 匹配域名 # "域名泄露": r'((?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+(?:biz|cc|club|cn|com|co|edu|fun|group|info|ink|kim|link|live|ltd|mobi|net|online|org|pro|pub|red|ren|shop|site|store|tech|top|tv|vip|wang|wiki|work|xin|xyz|me))', # SSH 密钥 "SSH密钥": '([-]+BEGIN [^\\s]+ PRIVATE KEY[-]+[\\s]*[^-]*[-]+END [^\\s]+ ' 'PRIVATE KEY[-]+)', # access_key "Access Key": 'access_key.*?["\'](.*?)["\']', "Access Key ID 1": 'accesskeyid.*?["\'](.*?)["\']', "Access Key ID 2": 'accesskeyid.*?["\'](.*?)["\']', # 亚马逊 aws api 账号 密钥 "亚马逊AWS API": 'AKIA[0-9A-Z]{16}', "亚马逊AWS 3S API 1": 's3\\.amazonaws.com[/]+|[a-zA-Z0-9_-]*\\.s3\\.amazonaws.com', "亚马逊AWS 3S API 2": '([a-zA-Z0-9-\\.\\_]+\\.s3\\.amazonaws\\.com|s3://[a-zA-Z0-9-\\.\\_]+|s3-[a-zA-Z0-9-\\.\\_\\/]+|s3.amazonaws.com/[a-zA-Z0-9-\\.\\_]+|s3.console.aws.amazon.com/s3/buckets/[a-zA-Z0-9-\\.\\_]+)', "亚马逊AWS 3S API 3": 'amzn\\\\.mws\\\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', # author 信息 "作者信息": '@author[: ]+(.*?) ', "API": 'api[key|_key|\\s+]+[a-zA-Z0-9_\\-]{5,100}', "基础信息": 'basic [a-zA-Z0-9=:_\\+\\/-]{5,100}', "Bearer": 'bearer [a-zA-Z0-9_\\-\\.=:_\\+\\/]{5,100}', # facebook token "Facebook Token": 'EAACEdEose0cBA[0-9A-Za-z]+', # github token "Github Token": '[a-zA-Z0-9_-]*:[a-zA-Z0-9_\\-]+@github\\.com*', # google api "Google API": 'AIza[0-9A-Za-z-_]{35}', # google captcha 验证 "Google验证码": '6L[0-9A-Za-z-_]{38}|^6[0-9a-zA-Z_-]{39}$', # google oauth 权限 "Google OAuth": 'ya29\\.[0-9A-Za-z\\-_]+', # jwt "JWT鉴权": 'ey[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.?[A-Za-z0-9-_.+/=]*$', # mailgun 服务密钥 "Mailgun服务密钥": 'key-[0-9a-zA-Z]{32}', # paypal braintree 访问凭证 "Paypal/Braintree访问凭证": 'access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}', # PGP 密钥块 "PGP密钥": '-----BEGIN PGP PRIVATE KEY BLOCK-----', # possible_creds "密码泄露": '(?i)(password\\s*[`=:\\"]+\\s*[^\\s]+|password ' 'is\\s*[`=:\\"]*\\s*[^\\s]+|pwd\\s*[`=:\\"]*\\s*[^\\s]+|passwd\\s*[`=:\\"]+\\s*[^\\s]+)', # RSA "RSA密钥": '-----BEGIN EC PRIVATE KEY-----', # DSA "DSA密钥": '-----BEGIN DSA PRIVATE KEY-----', # stripe 账号泄露 "Stripe账号泄露 1": 'rk_live_[0-9a-zA-Z]{24}', "Stripe账号泄露 2": 'sk_live_[0-9a-zA-Z]{24}', # twillio 账号泄露 "Twillio 账号泄露 1": 'AC[a-zA-Z0-9_\\-]{32}', "Twillio 账号泄露 2": 'SK[0-9a-fA-F]{32}', "Twillio 账号泄露 3": 'AP[a-zA-Z0-9_\\-]{32}' } for name, _ in regx.items(): texts = re.findall(_, self.response.text, re.M | re.I) issuc = False if texts: for text in set(texts): ignores = [ 'function', 'encodeURIComponent', 'XMLHttpRequest' ] is_continue = True for i in ignores: if i in text: is_continue = False break if not is_continue: continue result = ResultObject(self) result.init_info(self.requests.url, "js文件中存在敏感信息", VulType.SENSITIVE) result.add_detail("payload探测", self.requests.raw, self.response.raw, "根据正则:{} 发现敏感信息:{}".format(_, text), "", "", PLACE.GET) self.success(result) issuc = True break if issuc: break