起因
在寫花溪九尾這個項目的過程中,遇到了這樣的場景:
用戶使用花溪九尾從txt文件讀取待掃描的URL,使用360 0Kee-Team 的 crawlergo動態爬蟲對輸入的網址進行爬取,這時候對於每一個URL,都對應了crawlergo爬取的多個子URL,xray會對多個子URL進行漏洞掃描,但是每個子URL都會生成一個漏洞報告(如果有漏洞的話),這樣導致我們想要查看某一個URL的全部漏洞會比較困難,同時漏洞報告數量的增多,挨個打開檢查漏洞是否存在也會耗費時間
解決
將某個URL的漏洞報告全部存儲到saveTempXray文件夾下,當該URL掃描結束后讀取文件夾下的所有報告並提取漏洞信息,將其合並為一個報告,存儲到saveXray文件夾下,同時清空saveTempXray文件夾
關鍵點
關鍵點在於讀取文件夾下所有報告,使用xpath或者正則表達式都OK,接下來挨個模塊實現,分而治之
將報告存儲到臨時文件夾下
原來的報告是存儲在saveXray文件夾下,核心代碼魔改自pppXray
def xrayScan(targeturl,outputfilename="test"):
try:
scanCommand="{} webscan --url \"{}\" --html-output {}\{}.html".format(config.Xray_Path,targeturl,config.Xray_report_path,outputfilename)
print(scanCommand)
os.system(scanCommand)
except Exception as e:
print(e)
pass
return
在config.py中,Xray_report_path="{}\\save\\saveXray".format(Root_Path)
得益於之前模塊化編程的習慣,這里只需要把config.Xray_report_path修改為Xray_temp_report_path
Xray_temp_report_path即臨時文件夾
讀取所有報告
在一個URL的子URL全部掃描結束后,讀取所有報告
首先需要獲取所有的報告名,因為都在Xray_temp_report_path變量目錄下,所以使用os.listdir列出文件夾下的全部文件名
reportList=os.listdir(config.Xray_temp_report_path)
遍歷所有文件名並依次按照UTF-8編碼統一讀取
for report in reportList:
tempReport="{}\\{}".format(config.Xray_temp_report_path,report)
with open(tempReport,'r',encoding='utf-8') as f:
temp=f.read()
temp里面存儲的就是讀取的文件內容
提取漏洞信息
此處使用正則表達式
因為一個報告里面會有很多漏洞信息,所以使用列表存儲
pattern = re.compile(r'<script class=\'web-vulns\'>(.*?)</script>')
for report in reportList:
tempReport="{}\\{}".format(config.Xray_temp_report_path,report)
with open(tempReport,'r',encoding='utf-8') as f:
temp=f.read()
result=pattern.findall(temp)
print(result)
合並報告
將result都拼接到列表中,這里可以使用+,切片賦值,extend(),我們直接使用普普通通+號拼接就行
加上之前的代碼,然后將漏洞列表存儲在resultList列表中
def mergeReport(filename):
reportList=os.listdir(config.Xray_temp_report_path)
resultList=[]
pattern = re.compile(r'<script class=\'web-vulns\'>(.*?)</script>')
for report in reportList:
tempReport="{}\\{}".format(config.Xray_temp_report_path,report)
with open(tempReport,'r',encoding='utf-8') as f:
temp=f.read()
result=pattern.findall(temp)
resultList+=result
print(resultList)
return

接着將列表中的所有漏洞信息合並在模板HTML中
模板HTML,只要觀察一下xray掃描報告的結構,就能分離出無漏洞的基礎報告界面

只有在<script class='web-vulns'>(.*?)</script>中的才是漏洞信息,上面的都是報告界面的基礎代碼
所以可以剝離出一個modelFile.html,對每個URL的掃描結果在此基礎上進行拼接即可
讀基礎模板
context=""
with open("{}\\modelFile.html".format(config.Root_Path),'r',encoding='utf-8') as f:
context+=f.read()
拼接基礎模板
for result in resultList:
result="<script class=\'web-vulns\'>{}</script>".format(result)
context+=result
此處context已經是我們需要的整合后的漏洞報告了
存儲到saveXray文件夾下
此處很簡單,寫入即可
with open("{}\\{}.html".format(config.Xray_report_path,filename),'w',encoding='utf-8') as f:
f.write(context)
清空臨時文件夾
清空臨時文件夾的代碼很簡單,模塊化編程
先強制遞歸刪除該文件夾,然后新建該文件夾,變相達成了刪除該文件夾下的全部文件
'''
cleanTempXrayReport()函數
功能:刪除xray臨時報告目錄下的全部文件
'''
def cleanTempXrayReport():
shutil.rmtree("{}".format(config.Xray_temp_report_path))
os.mkdir("{}".format(config.Xray_temp_report_path))
return
全部代碼
全部代碼即cleanTempXrayReport和mergeReport函數
'''
cleanTempXrayReport()函數
功能:刪除xray臨時報告目錄下的全部文件
'''
def cleanTempXrayReport():
shutil.rmtree("{}".format(config.Xray_temp_report_path))
os.mkdir("{}".format(config.Xray_temp_report_path))
return
'''
mergeReport()函數
功能:合並報告
傳入參數:目標保存文件名 filename
'''
def mergeReport(filename):
reportList=os.listdir(config.Xray_temp_report_path)
resultList=[]
pattern = re.compile(r'<script class=\'web-vulns\'>(.*?)</script>')
for report in reportList:
tempReport="{}\\{}".format(config.Xray_temp_report_path,report)
with open(tempReport,'r',encoding='utf-8') as f:
temp=f.read()
result=pattern.findall(temp)
resultList+=result
context=""
with open("{}\\modelFile.html".format(config.Root_Path),'r',encoding='utf-8') as f:
context+=f.read()
for result in resultList:
result="<script class=\'web-vulns\'>{}</script>".format(result)
context+=result
with open("{}\\{}.html".format(config.Xray_report_path,filename),'w',encoding='utf-8') as f:
f.write(context)
cleanTempXrayReport()
return
測試
測試代碼是否正確,掃描http://testphp.vulnweb.com/
掃描命令:python3 scan.py -a http://testphp.vulnweb.com/
掃描結束后,臨時報告文件夾saveTempXray為空

saveXray文件夾下有一個報告,與期望輸出相同

打開該報告

成功合並漏洞,雖然有重復,但因為還沒有對漏洞進行去重,所以有重復是很正常的

上傳更新
使用git上傳項目代碼更新

