Python脚本实现Web漏洞扫描工具


Posted in Python onOctober 25, 2016

这是去年毕设做的一个Web漏洞扫描小工具,主要针对简单的SQL注入漏洞、SQL盲注和XSS漏洞,代码是看过github外国大神(听说是SMAP的编写者之一)的两个小工具源码,根据里面的思路自己写的。以下是使用说明和源代码。

一、使用说明:

1.运行环境:

Linux命令行界面+Python2.7

2.程序源码:

Vim scanner//建立一个名为scanner的文件

Chmod a+xscanner//修改文件权限为可执行的

3.运行程序:

Python scanner//运行文件

若没有携带目标URL信息,界面输出帮助信息,提醒可以可输入的参数。

参数包括:

--h 输出帮助信息
--url 扫描的URL
--data POST请求方法的参数
--cookie HTTP请求头Cookie值
--user-agent HTTP请求头User-Agent值
--random-agent 是否使用浏览器伪装
--referer 目标URL的上一层界面
--proxy HTTP请求头代理值

例如扫描“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", None), 
(r'(?s)<script[^>]*>[^<]*?"[^<"]*%(chars)s|%(chars)s[^<"]*"[^<]*</script>',"'<script>.\".xss.\".</script>', enclosed by <script> tags, inside double-quotes", None), 
(r"(?s)<script[^>]*>[^<]*?%(chars)s|%(chars)s[^<]*</script>","\"<script>.xss.</script>\", enclosed by <script> tags", None), 
(r">[^<]*%(chars)s[^<]*(<|\Z)", "\">.xss.<\", outside of tags", r"(?s)<script.+?</script>|<!--.*?-->"), 
(r"<[^>]*'[^>']*%(chars)s[^>']*'[^>]*>", "\"<.'.xss.'.>\", inside the tag, inside single-quotes", r"(?s)<script.+?</script>|<!--.*?-->"), 
(r'<[^>]*"[^>"]*%(chars)s[^>"]*"[^>]*>', "'<.\".xss.\".>', inside the tag, inside double-quotes", r"(?s)<script.+?</script>|<!--.*?-->"), 
(r"<[^>]*%(chars)s[^>]*>", "\"<.xss.>\", inside the tag, 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(' ',"%20") 
else: 
surl+=surl.join(url[i]) 
try: 
req = urllib2.Request(surl, data, _headers) 
retval[HTML] = urllib2.urlopen(req, timeout=30).read() 
except Exception, 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") 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)", "=1\g<1>", url) if url else url 
data=re.sub(r"=(&|\Z)", "=1\g<1>", 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, usable = False, 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, usable = False, False 
url = re.sub(r"=(&|\Z)", "=1\g<1>", url) if url else url 
data=re.sub(r"=(&|\Z)", "=1\g<1>", 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): 
vulnerable, usable = False, True 
original=None 
print "Scanning %s parameter '%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) 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, match.group("parameter"), dbms) 
retval = vulnerable = True 
vulnerable = False 
original = original or (_retrieve_content_sql(current, data) if phase is GET else _retrieve_content_sql(url, current)) 
for prefix,boolean,suffix in itertools.product(PREFIXES,BOOLEAN_TESTS,SUFFIXES): 
if not vulnerable: 
template = "%s%s%s" % (prefix,boolean, suffix) 
payloads = dict((_, current.replace(match.group(0), "%s%s" % (match.group(0), urllib.quote(template % (1 if _ else 2, 1), safe='%')))) for _ in (True, False)) 
contents = dict((_, _retrieve_content_sql(payloads[_], data) if phase is GET else _retrieve_content_sql(url, 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 "%s\nBy:%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漏洞扫描工具,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python日期操作学习笔记
Oct 07 Python
python发布模块的步骤分享
Feb 21 Python
Python argv用法详解
Jan 08 Python
解决pandas.DataFrame.fillna 填充Nan失败的问题
Nov 06 Python
python+opencv实现阈值分割
Dec 26 Python
解决Python 使用h5py加载文件,看不到keys()的问题
Feb 08 Python
Python3简单实现串口通信的方法
Jun 12 Python
django之静态文件 django 2.0 在网页中显示图片的例子
Jul 28 Python
弄懂这56个Python使用技巧(轻松掌握Python高效开发)
Sep 18 Python
Pycharm 使用 Pipenv 新建的虚拟环境(图文详解)
Apr 16 Python
Python爬虫如何应对Cloudflare邮箱加密
Jun 24 Python
Python urlopen()参数代码示例解析
Dec 10 Python
python+django快速实现文件上传
Oct 24 #Python
python实现简单爬虫功能的示例
Oct 24 #Python
简单谈谈Python中的反转字符串问题
Oct 24 #Python
Python 内置函数complex详解
Oct 23 #Python
Python检测生僻字的实现方法
Oct 23 #Python
python 写入csv乱码问题解决方法
Oct 23 #Python
解决Python中字符串和数字拼接报错的方法
Oct 23 #Python
You might like
PHPlet在Windows下的安装
2006/10/09 PHP
php中eval函数的危害与正确禁用方法
2014/06/30 PHP
PHP 实现代码复用的一个方法 traits新特性
2015/02/22 PHP
php 利用socket发送HTTP请求(GET,POST)
2015/08/24 PHP
PHP使用SOAP扩展实现WebService的方法
2016/04/01 PHP
PHP实现mysqli批量执行多条语句的方法示例
2017/07/22 PHP
PHP中数组转换为SimpleXML教程
2019/01/27 PHP
javascript与CSS复习(《精通javascript》)
2010/06/29 Javascript
jQuery中change事件用法实例
2014/12/26 Javascript
JS获取数组最大值、最小值及长度的方法
2015/11/24 Javascript
React.js入门实例教程之创建hello world 的5种方式
2016/05/11 Javascript
javascript创建含数字字母的随机字符串方法总结
2016/08/01 Javascript
Vue数据驱动模拟实现5
2017/01/13 Javascript
JavaScript实现瀑布流以及加载效果
2017/02/11 Javascript
js解决软键盘遮挡输入框的问题分享
2017/12/19 Javascript
Vue 页面状态保持页面间数据传输的一种方法(推荐)
2018/11/01 Javascript
js指定日期增加指定月份的实现方法
2018/12/19 Javascript
解决element ui select下拉框不回显数据问题的解决
2019/02/20 Javascript
优雅的处理vue项目异常实战记录
2019/06/05 Javascript
ES2020 已定稿,真实场景案例分析
2020/05/25 Javascript
Python实现动态图解析、合成与倒放
2018/01/18 Python
python之pandas用法大全
2018/03/13 Python
详解python异步编程之asyncio(百万并发)
2018/07/07 Python
Python3常用内置方法代码实例
2019/11/18 Python
python实现凯撒密码、凯撒加解密算法
2020/06/11 Python
python cookie反爬处理的实现
2020/11/01 Python
德国婴儿推车和儿童安全座椅商店:BABYSHOP
2016/09/01 全球购物
大专生简历的自我评价
2013/11/26 职场文书
煤矿安全生产责任书
2014/04/15 职场文书
爱护公共设施倡议书
2014/08/29 职场文书
大学生党员自我评价
2015/03/04 职场文书
企业宣传语大全
2015/07/13 职场文书
2019朋友新婚祝福语精选
2019/10/10 职场文书
2020年元旦晚会策划书模板
2019/12/30 职场文书
Python 数据结构之十大经典排序算法一文通关
2021/10/16 Python
Python进程间的通信之语法学习
2022/04/11 Python