Python脚本实现Web漏洞扫描工具
这是去年毕设做的一个Web漏洞扫描小工具,主要针对简单的SQL注入漏洞、SQL盲注和XSS漏洞,代码是看过github外国大神(听说是SMAP的编写者之一)的两个小工具源码,根据里面的思路自己写的。以下是使用说明和源代码。 一、使用说明: 1.运行环境: Linux命令行界面+Python2.7 2.程序源码: Vim scanner//建立一个名为scanner的文件 Chmod a+xscanner//修改文件权限为可执行的 3.运行程序: Python scanner//运行文件 若没有携带目标URL信息,界面输出帮助信息,提醒可以可输入的参数。 参数包括: --h 输出帮助信息 例如扫描“http://127.0.0.1/dvwa/vulnerabilities/sqli/?id=&Submit=Submit” Python scanner--url="http://127.0.0.1/dvwa/vulnerabilities/sqli/?id=&Submit=Submit"--cookie="security=low;PHPSESSID=menntb9b2isj7qha739ihg9of1" 输出扫描结果如下: 结果显示: 存在XSS漏洞,漏洞匹配漏洞特征库“”>.XSS.<””,属于嵌入标签外的类型。 存在SQL注入漏洞,目标网站服务器的数据库类型为MySQL。 存在BLIND SQL注入漏洞。 二、源代码: 代码验证过可以运行,我个人推荐用DVWA测试吧。 #!-*-coding:UTF-8-*- import optparse,random,re,string,urllib,urllib2,difflib,itertools,httplib NAME = "Scanner for RXSS and SQLI" AUTHOR = "Lishuze" PREFIXES = (" ",") ","' ","') ",""") SUFFIXES = ("","-- -","#") BOOLEAN_TESTS = ("AND %d=%d","OR NOT (%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; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/45.0.2454.101 Safari/537.36","Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7_0; en-US) AppleWebKit/534.21 (KHTML,like Gecko) Chrome/11.0.678.0 Safari/534.21",) XSS_PATTERNS = ( (r"<!--[^>]*%(chars)s|%(chars)s[^<]*-->",""<!--.'.xss.'.-->",inside the comment",None),(r"(?s)<script[^>]*>[^<]*?'[^<']*%(chars)s|%(chars)s[^<']*'[^<]*</script>",""<script>.'.xss.'.</script>",enclosed by <script> tags,inside single-quotes",(r'(?s)<script[^>]*>[^<]*?"[^<"]*%(chars)s|%(chars)s[^<"]*"[^<]*</script>',"'<script>.".xss.".</script>',inside double-quotes",(r"(?s)<script[^>]*>[^<]*?%(chars)s|%(chars)s[^<]*</script>",""<script>.xss.</script>",enclosed by <script> tags",(r">[^<]*%(chars)s[^<]*(<|Z)","">.xss.<",outside of tags",r"(?s)<script.+?</script>|<!--.*?-->"),(r"<[^>]*'[^>']*%(chars)s[^>']*'[^>]*>",""<.'.xss.'.>",inside the tag,(r'<[^>]*"[^>"]*%(chars)s[^>"]*"[^>]*>',"'<.".xss.".>',(r"<[^>]*%(chars)s[^>]*>",""<.xss.>",outside of quotes",r"(?s)<script.+?</script>|<!--.*?-->") ) DBMS_ERRORS = { "MySQL": (r"SQL syntax.*MySQL",r"Warning.*mysql_.*",r"valid MySQL result",r"MySqlClient."),"Microsoft SQL Server": (r"Driver.* SQL[-_ ]*Server",r"OLE DB.* SQL Server",r"(W|A)SQL Server.*Driver",r"Warning.*mssql_.*",r"(W|A)SQL Server.*[0-9a-fA-F]{8}",r"(?s)Exception.*WSystem.Data.SqlClient.",r"(?s)Exception.*WRoadhouse.Cms."),"Microsoft Access": (r"Microsoft Access Driver",r"JET Database Engine",r"Access Database Engine"),"Oracle": (r"ORA-[0-9][0-9][0-9][0-9]",r"Oracle error",r"Oracle.*Driver",r"Warning.*Woci_.*",r"Warning.*Wora_.*") } def _retrieve_content_xss(url,data=None): surl="" for i in xrange(len(url)): if i > 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() except Exception,ex: retval = getattr(ex,"message","") return retval or "" def _retrieve_content_sql(url,data=None): retval = {HTTPCODE: httplib.OK} surl="" for i in xrange(len(url)): if i > url.find('?'): surl+=surl.join(url[i]).replace(' ',_headers) retval[HTML] = urllib2.urlopen(req,ex: retval[HTTPCODE] = getattr(ex,"code",None) retval[HTML] = getattr(ex,"") match = re.search(r"<title>(?P<result>[^<]+)</title>",retval[HTML],re.I) retval[TITLE] = match.group("result") if match else None retval[TEXT] = re.sub(r"(?si)<script.+?</script>|<!--.+?-->|<style.+?</style>|<[^>]+>|s+"," ",retval[HTML]) return retval def scan_page_xss(url,data=None): print "Start scanning RXSS:n" retval,usable = False,False url = re.sub(r"=(&|Z)","=1g<1>",url) if url else url data=re.sub(r"=(&|Z)",data) if data else data try: for phase in (GET,POST): current = url if phase is GET else (data or "") for match in re.finditer(r"((A|[?&])(?P<parameter>[w]+)=)(?P<value>[^&]+)",current): found,True print "Scanning %s parameter '%s'" % (phase,match.group("parameter")) prefix = ("".join(random.sample(string.ascii_lowercase,5))) suffix = ("".join(random.sample(string.ascii_lowercase,5))) if not found: 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) if phase is GET else _retrieve_content_xss(url,tampered) for sample in re.finditer("%s([^ ]+?)%s" % (prefix,suffix),content,re.I): #print sample.group() for regex,info,content_removal_regex in XSS_PATTERNS: context = re.search(regex % {"chars": re.escape(sample.group(0))},re.sub(content_removal_regex or "","",content),re.I) if context and not found and sample.group(1).strip(): print "!!!%s parameter '%s' appears to be XSS vulnerable (%s)" % (phase,match.group("parameter"),info) found = retval = True if not usable: print " (x) no usable GET/POST parameters found" except KeyboardInterrupt: print "r (x) Ctrl-C pressed" return retval def scan_page_sql(url,data=None): print "Start scanning SQLI:n" retval,POST): current = url if phase is GET else (data or "") for match in re.finditer(r"((A|[?&])(?P<parameter>w+)=)(?P<value>[^&]+)",current): vulnerable,True original=None print "Scanning %s parameter '%s'" % (phase,match.group("parameter")) tampered = current.replace(match.group(0),urllib.quote("".join(random.sample(TAMPER_SQL_CHAR_POOL,len(TAMPER_SQL_CHAR_POOL)))))) content = _retrieve_content_sql(tampered,data) if phase is GET else _retrieve_content_sql(url,tampered) for (dbms,regex) in ((dbms,regex) for dbms in DBMS_ERRORS for regex in DBMS_ERRORS[dbms]): if not vulnerable and re.search(regex,content[HTML],re.I): print "!!!%s parameter '%s' could be error SQLi vulnerable (%s)" % (phase,dbms) retval = vulnerable = True vulnerable = False original = original or (_retrieve_content_sql(current,current)) for prefix,boolean,suffix in itertools.product(PREFIXES,BOOLEAN_TESTS,SUFFIXES): if not vulnerable: template = "%s%s%s" % (prefix,suffix) payloads = dict((_,current.replace(match.group(0),urllib.quote(template % (1 if _ else 2,1),safe='%')))) for _ in (True,False)) contents = dict((_,_retrieve_content_sql(payloads[_],payloads[_])) for _ in (False,True)) if all(_[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()) and ratios[True] > 0.95 and ratios[False] < 0.95 if vulnerable: print "!!!%s parameter '%s' could be error Blind SQLi vulnerable" % (phase,match.group("parameter")) retval = True if not usable: print " (x) no usable GET/POST parameters found" except KeyboardInterrupt: print "r (x) Ctrl-C pressed" return retval def init_options(proxy=None,cookie=None,ua=None,referer=None): global _headers _headers = dict(filter(lambda _: _[1],((COOKIE,cookie),(UA,ua or NAME),(REFERER,referer)))) urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler({'http': proxy})) if proxy else None) if __name__ == "__main__": print "----------------------------------------------------------------------------------" print "%snBy:%s" % (NAME,AUTHOR) print "----------------------------------------------------------------------------------" parser = optparse.OptionParser() parser.add_option("--url",dest="url",help="Target URL") parser.add_option("--data",dest="data",help="POST data") parser.add_option("--cookie",dest="cookie",help="HTTP Cookie header value") parser.add_option("--user-agent",dest="ua",help="HTTP User-Agent header value") parser.add_option("--random-agent",dest="randomAgent",action="store_true",help="Use randomly selected HTTP User-Agent header value") parser.add_option("--referer",dest="referer",help="HTTP Referer header value") parser.add_option("--proxy",dest="proxy",help="HTTP proxy address") options,_ = parser.parse_args() if options.url: init_options(options.proxy,options.cookie,options.ua if not options.randomAgent else random.choice(USER_AGENTS),options.referer) result_xss= scan_page_xss(options.url if options.url.startswith("http") else "http://%s" % options.url,options.data) print "nScan results: %s vulnerabilities found" % ("possible" if result_xss else "no") print "----------------------------------------------------------------------------------" result_sql = scan_page_sql(options.url if options.url.startswith("http") else "http://%s" % options.url,options.data) print "nScan results: %s vulnerabilities found" % ("possible" if result_sql else "no") print "----------------------------------------------------------------------------------" else: parser.print_help() 以上所述是小编给大家介绍的Python脚本实现Web漏洞扫描工具,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |