Xray批量扫描结果合并
起因
在写花溪九尾这个项目的过程中,遇到了这样的场景:
用户使用花溪九尾从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
上传项目代码更新