介绍
SiteVulScan
是一款用于扫描目标站点漏洞的脚本,支持批量输入目标,将结果输出到Excel中,输出字段:序号、协议、host、端口、URL、影响产品、漏洞名称、漏洞编号、风险等级、漏洞类型、检测时间、参考链接、修复建议。
。
脚本参数
usage: SiteVulScan.py [-h] [-u URL] [-f FILE] [-t THREAD]
options:
-h, --help show this help message and exit
-u URL, --url URL 单个URL检测
-f FILE, --file FILE 指定url文件(一行一个)
-t THREAD, --thread THREAD
并发数(int: 5)
输出日志
[ CMS ] https://api.birdy02.com:8443 【Laravel,Apache-Shiro,Access-Control,Docker_Daemon,Python】
[ Vul ] Check Laravel Debug 信息泄露
[ Vul ] Check Laravel配置信息泄露
[ CMS ] https://api.birdy02.com 【OpenResty】
[ Vul ] Check Laravel Debug Enabled
[ Vul ] Check Larvel Debug Method Enabled
[ Vul ] Check UniSharp Laravel File Manager 2.0.0 - Arbitrary File Read
[ Vul ] Check Laravel Horizon Dashboard - Unauthenticated
[ Vul ] Check Laravel Ignition - Cross-Site Scripting
[ Vul ] Check Laravel log file publicly accessible
[ Vul ] Check Laravel Telescope Disclosure
[ 检测报告 ] output\SiteVulScan_1733568438\result.xlsx
代码源码
# -*- coding: utf-8 -*-
from secScript import analyze_url, poc_info, exploit, Function, Docx, log, Fore, outPath, program_exit
import openpyxl, argparse, os.path, time
from urllib.parse import urlparse
import concurrent.futures
result = []
model = 'SiteVulScan'
pocs = dict()
# poc漏洞检测
def check_vul(cms: str, _url: str) -> list | None:
global pocs, result
for v in pocs[cms]:
v_res = exploit(v, _url)
if v_res is None: return
log("Vul", "{} {}".format(
Fore.RED + "【Vul Exists】" if v_res["isVul"] else Fore.YELLOW + "Check",
Fore.RESET + v_res["vName"]
), False)
result.append([v_res, _url]) if v_res["isVul"] else None
return result
# 主要检测方法
def run(_url: str) -> list:
_res = []
global pocs
if len(pocs) < 1: pocs = poc_info("list")
res = analyze_url(_url, True)
if res is None:
log(Fore.RED + "Request Error", Fore.RED + _url)
return _res
cms = ",".join(res.get("CMS")) if res.get("CMS") else ''
log("CMS", "{} {}".format(Fore.YELLOW + _url, Fore.RESET + f"【{cms}】"))
if not pocs: return _res
for i in [i for i in res.get('CMS') if i in pocs] if res.get('CMS') else []:
_r = check_vul(i, _url)
_res.extend(_r) if _r is not None else None
return _res
# 输出Excel表格
def outExcel(path: str) -> str:
path = os.path.join(outPath, "{}_{}".format(model, path))
if not os.path.exists(path): os.makedirs(path)
workbook = openpyxl.Workbook()
worksheet = workbook.active
worksheet.append([
"序号", "协议", "host", "端口", "URL",
"影响产品", "漏洞名称", "漏洞编号", "风险等级", "漏洞类型", "检测时间", "参考链接", "修复建议"
])
for num, i in enumerate(result):
if i is None or len(i) == 0: continue
v = i[0]
uri = urlparse(i[-1])
Docx.write_docx(v, i[-1], path)
worksheet.append([
str(num + 1), uri.scheme, uri.hostname, uri.port, i[-1],
v.get("product"), v.get("vName"), ",".join(v.get("vId")),
v.get("level"), v.get("vType"), v.get("timer"), v.get("link"),
"\n".join(v.get("fix"))
])
file = os.path.join(path, "result.xlsx")
workbook.save(file)
log("检测报告", file)
return file
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--url', help='单个URL检测')
parser.add_argument('-f', '--file', help='指定url文件(一行一个)')
parser.add_argument('-t', '--thread', help='并发数(int: 5)', default=5, type=int)
args = parser.parse_args()
if args.thread < 1: args.thread = 1
if args.url:
run(args.url)
elif args.file:
try:
with concurrent.futures.ProcessPoolExecutor(max_workers=args.thread) as executor:
futures = [executor.submit(run, i) for i in Function.fileGetUrl(args.file)]
result = []
[result.extend(i.result()) for i in futures]
except KeyboardInterrupt:
program_exit()
else:
print("")
else:
parser.print_help()
if len(result) > 0: outExcel(str(int(time.time())))