Python脚本实现Web漏洞扫描工具
这是去年毕设做的一个Web漏洞扫描小工具,主要针对简单的SQL注入漏洞、SQL盲注和XSS漏洞,代码是看过github外国大神(听说是SMAP的编写者之一)的两个小工具源码,根据里面的思路自己写的。以下是使用说明和源代码。
一、使用说明:
1.运行环境:
Linux命令行界面+Python2.7
2.程序源码:
Vimscanner//建立一个名为scanner的文件
Chmoda+xscanner//修改文件权限为可执行的
3.运行程序:
Pythonscanner//运行文件
若没有携带目标URL信息,界面输出帮助信息,提醒可以可输入的参数。
参数包括:
--h输出帮助信息
--url扫描的URL
--dataPOST请求方法的参数
--cookieHTTP请求头Cookie值
--user-agentHTTP请求头User-Agent值
--random-agent是否使用浏览器伪装
--referer目标URL的上一层界面
--proxyHTTP请求头代理值
例如扫描“http://127.0.0.1/dvwa/vulnerabilities/sqli/?id=&Submit=Submit”
Pythonscanner--url="http://127.0.0.1/dvwa/vulnerabilities/sqli/?id=&Submit=Submit"--cookie="security=low;PHPSESSID=menntb9b2isj7qha739ihg9of1"
输出扫描结果如下:
结果显示:
存在XSS漏洞,漏洞匹配漏洞特征库“”>.XSS.<””,属于嵌入标签外的类型。
存在SQL注入漏洞,目标网站服务器的数据库类型为MySQL。
存在BLINDSQL注入漏洞。
二、源代码:
代码验证过可以运行,我个人推荐用DVWA测试吧。
#!-*-coding:UTF-8-*- importoptparse,random,re,string,urllib,urllib2,difflib,itertools,httplib NAME="ScannerforRXSSandSQLI" AUTHOR="Lishuze" PREFIXES=("",")","'","')","\"") SUFFIXES=("","---","#") BOOLEAN_TESTS=("AND%d=%d","ORNOT(%d=%d)") TAMPER_SQL_CHAR_POOL=('(',')','\'','"''"') TAMPER_XSS_CHAR_POOL=('\'','"','>','<',';') GET,POST="GET","POST" COOKIE,UA,REFERER="Cookie","User-Agent","Referer" TEXT,HTTPCODE,TITLE,HTML=xrange(4) _headers={} USER_AGENTS=( "Mozilla/5.0(X11;Linuxi686;rv:38.0)Gecko/20100101Firefox/38.0", "Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/45.0.2454.101Safari/537.36", "Mozilla/5.0(Macintosh;U;IntelMacOSX10_7_0;en-US)AppleWebKit/534.21(KHTML,likeGecko)Chrome/11.0.678.0Safari/534.21", ) XSS_PATTERNS=( (r"<!--[^>]*%(chars)s|%(chars)s[^<]*-->","\"<!--.'.xss.'.-->\",insidethecomment",None), (r"(?s)<script[^>]*>[^<]*?'[^<']*%(chars)s|%(chars)s[^<']*'[^<]*</script>","\"<script>.'.xss.'.</script>\",enclosedby<script>tags,insidesingle-quotes",None), (r'(?s)<script[^>]*>[^<]*?"[^<"]*%(chars)s|%(chars)s[^<"]*"[^<]*</script>',"'<script>.\".xss.\".</script>',enclosedby<script>tags,insidedouble-quotes",None), (r"(?s)<script[^>]*>[^<]*?%(chars)s|%(chars)s[^<]*</script>","\"<script>.xss.</script>\",enclosedby<script>tags",None), (r">[^<]*%(chars)s[^<]*(<|\Z)","\">.xss.<\",outsideoftags",r"(?s)<script.+?</script>|<!--.*?-->"), (r"<[^>]*'[^>']*%(chars)s[^>']*'[^>]*>","\"<.'.xss.'.>\",insidethetag,insidesingle-quotes",r"(?s)<script.+?</script>|<!--.*?-->"), (r'<[^>]*"[^>"]*%(chars)s[^>"]*"[^>]*>',"'<.\".xss.\".>',insidethetag,insidedouble-quotes",r"(?s)<script.+?</script>|<!--.*?-->"), (r"<[^>]*%(chars)s[^>]*>","\"<.xss.>\",insidethetag,outsideofquotes",r"(?s)<script.+?</script>|<!--.*?-->") ) DBMS_ERRORS={ "MySQL":(r"SQLsyntax.*MySQL",r"Warning.*mysql_.*",r"validMySQLresult",r"MySqlClient\."), "MicrosoftSQLServer":(r"Driver.*SQL[\-\_\]*Server",r"OLEDB.*SQLServer",r"(\W|\A)SQLServer.*Driver",r"Warning.*mssql_.*",r"(\W|\A)SQLServer.*[0-9a-fA-F]{8}",r"(?s)Exception.*\WSystem\.Data\.SqlClient\.",r"(?s)Exception.*\WRoadhouse\.Cms\."), "MicrosoftAccess":(r"MicrosoftAccessDriver",r"JETDatabaseEngine",r"AccessDatabaseEngine"), "Oracle":(r"ORA-[0-9][0-9][0-9][0-9]",r"Oracleerror",r"Oracle.*Driver",r"Warning.*\Woci_.*",r"Warning.*\Wora_.*") } def_retrieve_content_xss(url,data=None): surl="" foriinxrange(len(url)): ifi>url.find('?'): surl+=surl.join(url[i]).replace('',"%20") else: surl+=surl.join(url[i]) try: req=urllib2.Request(surl,data,_headers) retval=urllib2.urlopen(req,timeout=30).read() exceptException,ex: retval=getattr(ex,"message","") returnretvalor"" def_retrieve_content_sql(url,data=None): retval={HTTPCODE:httplib.OK} surl="" foriinxrange(len(url)): ifi>url.find('?'): surl+=surl.join(url[i]).replace('',"%20") else: surl+=surl.join(url[i]) try: req=urllib2.Request(surl,data,_headers) retval[HTML]=urllib2.urlopen(req,timeout=30).read() exceptException,ex: retval[HTTPCODE]=getattr(ex,"code",None) retval[HTML]=getattr(ex,"message","") match=re.search(r"<title>(?P<result>[^<]+)</title>",retval[HTML],re.I) retval[TITLE]=match.group("result")ifmatchelseNone retval[TEXT]=re.sub(r"(?si)<script.+?</script>|<!--.+?-->|<style.+?</style>|<[^>]+>|\s+","",retval[HTML]) returnretval defscan_page_xss(url,data=None): print"StartscanningRXSS:\n" retval,usable=False,False url=re.sub(r"=(&|\Z)","=1\g<1>",url)ifurlelseurl data=re.sub(r"=(&|\Z)","=1\g<1>",data)ifdataelsedata try: forphasein(GET,POST): current=urlifphaseisGETelse(dataor"") formatchinre.finditer(r"((\A|[?&])(?P<parameter>[\w]+)=)(?P<value>[^&]+)",current): found,usable=False,True print"Scanning%sparameter'%s'"%(phase,match.group("parameter")) prefix=("".join(random.sample(string.ascii_lowercase,5))) suffix=("".join(random.sample(string.ascii_lowercase,5))) ifnotfound: tampered=current.replace(match.group(0),"%s%s"%(match.group(0),urllib.quote("%s%s%s%s"%("'",prefix,"".join(random.sample(TAMPER_XSS_CHAR_POOL,len(TAMPER_XSS_CHAR_POOL))),suffix)))) content=_retrieve_content_xss(tampered,data)ifphaseisGETelse_retrieve_content_xss(url,tampered) forsampleinre.finditer("%s([^]+?)%s"%(prefix,suffix),content,re.I): #printsample.group() forregex,info,content_removal_regexinXSS_PATTERNS: context=re.search(regex%{"chars":re.escape(sample.group(0))},re.sub(content_removal_regexor"","",content),re.I) ifcontextandnotfoundandsample.group(1).strip(): print"!!!%sparameter'%s'appearstobeXSSvulnerable(%s)"%(phase,match.group("parameter"),info) found=retval=True ifnotusable: print"(x)nousableGET/POSTparametersfound" exceptKeyboardInterrupt: print"\r(x)Ctrl-Cpressed" returnretval defscan_page_sql(url,data=None): print"StartscanningSQLI:\n" retval,usable=False,False url=re.sub(r"=(&|\Z)","=1\g<1>",url)ifurlelseurl data=re.sub(r"=(&|\Z)","=1\g<1>",data)ifdataelsedata try: forphasein(GET,POST): current=urlifphaseisGETelse(dataor"") formatchinre.finditer(r"((\A|[?&])(?P<parameter>\w+)=)(?P<value>[^&]+)",current): vulnerable,usable=False,True original=None print"Scanning%sparameter'%s'"%(phase,match.group("parameter")) tampered=current.replace(match.group(0),"%s%s"%(match.group(0),urllib.quote("".join(random.sample(TAMPER_SQL_CHAR_POOL,len(TAMPER_SQL_CHAR_POOL)))))) content=_retrieve_content_sql(tampered,data)ifphaseisGETelse_retrieve_content_sql(url,tampered) for(dbms,regex)in((dbms,regex)fordbmsinDBMS_ERRORSforregexinDBMS_ERRORS[dbms]): ifnotvulnerableandre.search(regex,content[HTML],re.I): print"!!!%sparameter'%s'couldbeerrorSQLivulnerable(%s)"%(phase,match.group("parameter"),dbms) retval=vulnerable=True vulnerable=False original=originalor(_retrieve_content_sql(current,data)ifphaseisGETelse_retrieve_content_sql(url,current)) forprefix,boolean,suffixinitertools.product(PREFIXES,BOOLEAN_TESTS,SUFFIXES): ifnotvulnerable: template="%s%s%s"%(prefix,boolean,suffix) payloads=dict((_,current.replace(match.group(0),"%s%s"%(match.group(0),urllib.quote(template%(1if_else2,1),safe='%'))))for_in(True,False)) contents=dict((_,_retrieve_content_sql(payloads[_],data)ifphaseisGETelse_retrieve_content_sql(url,payloads[_]))for_in(False,True)) ifall(_[HTTPCODE]for_in(original,contents[True],contents[False]))and(any(original[_]==contents[True][_]!=contents[False][_]for_in(HTTPCODE,TITLE))): vulnerable=True else: ratios=dict((_,difflib.SequenceMatcher(None,original[TEXT],contents[_][TEXT]).quick_ratio())for_in(True,False)) vulnerable=all(ratios.values())andratios[True]>0.95andratios[False]<0.95 ifvulnerable: print"!!!%sparameter'%s'couldbeerrorBlindSQLivulnerable"%(phase,match.group("parameter")) retval=True ifnotusable: print"(x)nousableGET/POSTparametersfound" exceptKeyboardInterrupt: print"\r(x)Ctrl-Cpressed" returnretval definit_options(proxy=None,cookie=None,ua=None,referer=None): global_headers _headers=dict(filter(lambda_:_[1],((COOKIE,cookie),(UA,uaorNAME),(REFERER,referer)))) urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler({'http':proxy}))ifproxyelseNone) if__name__=="__main__": print"----------------------------------------------------------------------------------" print"%s\nBy:%s"%(NAME,AUTHOR) print"----------------------------------------------------------------------------------" parser=optparse.OptionParser() parser.add_option("--url",dest="url",help="TargetURL") parser.add_option("--data",dest="data",help="POSTdata") parser.add_option("--cookie",dest="cookie",help="HTTPCookieheadervalue") parser.add_option("--user-agent",dest="ua",help="HTTPUser-Agentheadervalue") parser.add_option("--random-agent",dest="randomAgent",action="store_true",help="UserandomlyselectedHTTPUser-Agentheadervalue") parser.add_option("--referer",dest="referer",help="HTTPRefererheadervalue") parser.add_option("--proxy",dest="proxy",help="HTTPproxyaddress") options,_=parser.parse_args() ifoptions.url: init_options(options.proxy,options.cookie,options.uaifnotoptions.randomAgentelserandom.choice(USER_AGENTS),options.referer) result_xss=scan_page_xss(options.urlifoptions.url.startswith("http")else"http://%s"%options.url,options.data) print"\nScanresults:%svulnerabilitiesfound"%("possible"ifresult_xsselse"no") print"----------------------------------------------------------------------------------" result_sql=scan_page_sql(options.urlifoptions.url.startswith("http")else"http://%s"%options.url,options.data) print"\nScanresults:%svulnerabilitiesfound"%("possible"ifresult_sqlelse"no") print"----------------------------------------------------------------------------------" else: parser.print_help()
以上所述是小编给大家介绍的Python脚本实现Web漏洞扫描工具,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!