天天看点

pythonweb扫描器_Python实现Awvs自动化扫描

最近再做一个python的小程序,主要功能是实现Acuenetix Web Vulnerability Scanner的自动化扫描,批量对一些目标进行扫描,然后对扫描结果写入mysql数据库。写这篇文章,分享一下一些思路。

程序主要分三个功能模块,Url下载、批量扫描、结果入库,

有一个另外独立的程序,在流量镜像服务器上进行抓包,抓取Http协议的包,然后对包进行筛选处理,保留一些带有各种参数的url,然后对url进行入库。url下载功能主要是从mysql数据库中下载url。

批量扫描功能主要调用了Awvs的命令行wvs_console.exe,调研的时候先是尝试用awvs计划任务来实现批量扫描,但是发现在将一些awvs设置发包给计划任务的时候会遇到各种困难,计划任务貌似也不是一个网页,采用的是XML模版,技术有限,最后没实现,只好放弃。

之后发现Awvs支持命令行,wvs_console.exe就是主程序,有很多命令参数,基本能实现Awvs界面操作的所有功能。批量扫描主要是读取下载到本地的url,进行逐一扫描。要将扫描结果保存到本地access数据库文件,需要使用savetodatabase参数。

Awvs会自动将扫描结果保存到本地的access数据库中,具体的表是Wvs_alerts,也可以设置保存到Mssql数据库中,具体的是在Application Setting进行设置。结果入库模块的功能是从access数据库筛选出危害等级为3的漏洞,然后将它们写入到mysql数据库。主要用了正则表达式对request中的host,漏洞文件,get或post提交的请求进行筛选拼凑,获取到完整的漏洞测试url。

贴上代码,很菜,代码各种Bug,最主要的是程序的整个流程设计存在问题,导致后来被大佬给否掉了,没有考虑到重复扫描和程序异常中止的情况,导致我的程序只能一直运行下去 ,否则重新运行又会从头对url进行扫描。

对此很郁闷,某天晚上下班回家想了想,觉得可以通过以下方法来解决以上两个问题:

Awvs扫描结果数据库中有一个Wvs_scans表,保存的都是扫描过的url,以及扫描开始时间和结束时间。可以将当天下载的url保存到一个list中,然后在扫描之前先将之前所有扫描过的URL查询出来,同样保存在list中,读取list中的url,判断是否在扫描过的URL list中,如果存在将之从url list中删除掉;如果不存在则再进行扫描。

异常中止的话貌似只能增加系统计划任务,每天结束再打开,不知道如何时时监视系统进程,通过是否存在wvs的进程来判断。

以上只是一个大概的程序介绍,贴上代码,代码可能存在一些问题,有兴趣的童鞋去完善完善,大佬觉得我的效率和编码能力有待提高,so,让继续学习,所以没再继续跟进这个项目。

downurl.py 代码:

#coding:utf-8

import MySQLdb

import os,time,shutil

import hashlib,re

datanow=time.strftime('%Y-%m-%d',time.localtime(time.time()))

#filetype='.txt'

#urlfilename=datanow+filetype

#path="D:\wvscan\url\\"

#newfile=path+urlfilename

datanow=time.strftime('%Y-%m-%d',time.localtime(time.time()))

con=MySQLdb.Connect('10.1.1.1','root','12345678','wvsdb')

cur=con.cursor()

sqlstr='select url from urls where time like %s'

values=datanow+'%'

cur.execute(sqlstr,values)

data=cur.fetchall()

#将当天的URL保存到本地url.txt文件

f=open(r'd:\Wvscan\url.txt','a+')

uhfile=open(r'd:\Wvscan\urlhash.txt','a+')

line=uhfile.readlines()

#保存之前对url进行简单的处理,跟本地的hash文件比对,确保url.txt中url不重复

for i in range(0,len(data)):

impurl=str(data[i][0]).split('=')[0]

urlhash=hashlib.new('md5',impurl).hexdigest()

urlhash=urlhash+'\n'

if urlhash in line:

pass

else:

uhfile.write(urlhash)

newurl=str(data[i][0])+'\n'

f.writelines(newurl)

cur.close()

con.close()

抓包程序抓到的url可能重复率较高,而且都是带参数的,保存到本地的时候截取了最前面的域名+目录+文件部分进行了简单的去重。Awvs可能不大适合这样的方式,只需要将全部的域名列出来,然后逐一扫描即可,site Crawler功能会自动爬行。

writeinmysql.py 结果入库模块,代码:

#coding:UTF-8

import subprocess

import os,time,shutil,sys

import win32com.client

import MySQLdb

import re,hashlib

reload(sys)

sys.setdefaultencoding('utf-8')

#需要先在win服务器设置odbc源,指向access文件。实际用pyodbc模块可能更好一些

def writeinmysql():

conn = win32com.client.Dispatch(r'ADODB.Connection')

DSN = 'PROVIDER=Microsoft Access Driver (*.mdb, *.accdb)'

conn.Open('awvs')

cur=conn.cursor()

rs = win32com.client.Dispatch(r'ADODB.Recordset')

rs.Open('[WVS_alerts]', conn, 1, 3)

if rs.recordcount == 0:

exit()

#遍历所有的结果,cmp进行筛选危害等级为3的,也就是高危

while not rs.eof:

severity = str(rs('severity'))

if cmp('3', severity):

rs.movenext

continue

vultype = rs('algroup')

vulfile=rs('affects')

#由于mysql库中要求的漏洞类型和access的名称有点差别,所以还需要对漏洞类型和危害等级进行二次命名,sql注入和xss为例

xss='Cross site'

sqlinject='injection'

if xss in str(vultype):

vultype='XSS'

level='低危'

elif sqlinject in str(vultype):

vultype="SQL注入"

level='高危'

else:

level='中危'

#拼凑出漏洞测试url,用了正则表达式, post和get类型的request请求是不同的

params = rs('parameter')

ss = str(rs('request'))

str1 = ss[0:4]

if 'POST'== str1:

requestType = 'POST'

regex = 'POST (.*?) HTTP/1\.\d+'

str1 = re.findall(regex, ss);

else:

requestType = 'GET'

regex = 'GET (.*?) HTTP/1\.\d+'

str1 = re.findall(regex, ss);

regex = 'Host:(.*?)\r\n'

host = re.findall(regex, ss);

if host == []:

host = ''

else:

host = host[0].strip()

if str1 == []:

str1 = ''

else:

str1 = str1[0]

url =host + str1

timex=time.strftime('%Y-%m-%d',time.localtime(time.time()))

status=0

scanner='Awvs'

comment=''

db = MySQLdb.connect(host="10.1.1.1", user="root", passwd="12345678", db="wvsdb",charset='utf8')

cursor = db.cursor()

sql = 'insert into vuls(status,comment,vultype,url,host,params,level,scanner) values(%s,%s,%s,%s,%s,%s,%s,%s)'

values =[status,comment,vultype,'http://'+url.lstrip(),host,params,level,scanner]

#入库的时候又进行了去重,确保mysql库中没有存在该条漏洞记录,跟本地保存的vulhash进行比对,感觉这种方法很原始。

hashvalue=str(values[2])+str(values[4])+str(vulfile)+str(values[5])

vulhash=hashlib.new('md5',hashvalue).hexdigest()

vulhash=vulhash+'\n'

file=open(r'D:\Wvscan\vulhash.txt','a+')

if vulhash in file.readlines():

pass

else:

file.write(vulhash+'\n')

cursor.execute(sql, values)

delsql='delete from vuls where vultype like %s or vultype like %s'

delvaluea='Slow HTTP%'

delvalueb='Host header%'

delinfo=[delvaluea,delvalueb]

cursor.execute(delsql,delinfo)

db.commit()

rs.movenext

rs.close

conn.close

cursor.close()

db.close()

if __name_=='__main__':

writeinmysql()

time.sleep(10)

#备份每天的扫描数据库,用原始数据库替换,方便第二天继续保存。

datanow=time.strftime('%Y-%m-%d',time.localtime(time.time()))

filetype='.mdb'

urlfilename=datanow+filetype

path="D:\wvscan\databak\\"

databakfile=path+urlfilename

shutil.copyfile(r'D:\Wvscan\data\vulnscanresults.mdb',databakfile)

shutil.copyfile(r'D:\Wvscan\vulnscanresults.mdb',r'D:\Wvscan\data\vulnscanresults.mdb')

startwvs.py,扫描模块,这个模块问题较多,就是之前提到的,没有考虑重复扫描和异常终止的问题,贴上代码:

#coding:utf-8

import subprocess

import os,time,shutil

file=open(r"D:\Wvscan\url.txt","r")

def wvsscan():

for readline in file:

url=readline.strip('\n')

cmd=r"d:\Wvs\wvs_console.exe /Scan "+url+r" /SavetoDatabase"

doscan=subprocess.Popen(cmd)

doscan.wait()

if __name__=='__main__':

wvsscan()

阿德马原创,转载请注明出处,Tks!

最后编辑:2014-01-10作者:admin

这个作者貌似有点懒,什么都没有留下。