天天看點

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

這個作者貌似有點懶,什麼都沒有留下。