ericalfonce/webscanner-final-project
GitHub: ericalfonce/webscanner-final-project
一个基于 Python Flask 的 Web 漏洞扫描器,支持自动检测 SQL 注入、XSS 和 HTTP 安全标头缺失并生成含教育内容的 PDF 报告。
Stars: 0 | Forks: 0
# WebScanner — Web 漏洞扫描器
这是一个基于 Python Flask 构建的 Web 漏洞扫描器,专为 ATC 信息与通信技术文凭(2026)开发。用于检测常见的 Web 应用安全问题 —— SQL 注入、跨站脚本攻击 (XSS) 以及缺失的 HTTP 安全标头 —— 同时提供实时扫描进度、针对每项发现的教育性报告以及 PDF 导出功能。
## 功能
| 模块 | 功能说明 |
|---|---|
| **SQL 注入** | 针对 URL 参数和 HTML 表单输入进行基于错误、基于布尔型和基于时间盲注的测试(24 个 payload) |
| **XSS 检测** | 使用 23 个精选 payload 进行反射型跨站脚本攻击检测;同时测试 URL 参数和表单输入 |
| **安全标头** | 检查 7 个关键 HTTP 标头:CSP、HSTS、X-Frame-Options、X-Content-Type-Options、Referrer-Policy、Permissions-Policy、X-XSS-Protection |
| **智能爬虫** | 广度优先链接发现,最多爬取 50 个页面;提取表单、URL 参数,并将爬取范围限定在目标域名内 |
| **详细报告** | 为每个漏洞提供针对单项发现的证据、使用的 payload、修复建议和教育背景 |
| **PDF 导出** | 下载带有品牌标识的 PDF 扫描报告,包含严重性细分 |
| **实时进度** | 实时日志推送,每 2 秒轮询一次;在活跃扫描期间显示动画进度 |
| **扫描历史** | 记录每个用户的所有扫描历史,包含状态、持续时间和发现摘要 |
| **快速 / 完整模式** | 快速扫描 = 10 个页面,1–3 分钟。完整扫描 = 最多 50 个页面,5–15 分钟 |
## 技术栈
| 层级 | 技术 |
|---|---|
| Backend | Python 3 · Flask 3.0 · Flask-Login · Flask-WTF (CSRF) |
| ORM | SQLAlchemy 2.x |
| Database | SQLite (`instance/scanner.db`) |
| 扫描 | `requests` · BeautifulSoup4 (`html.parser`) |
| PDF | ReportLab 4.x |
| Frontend | Bootstrap 5.3 · Bootstrap Icons · Inter font · Vanilla JS |
| Auth | bcrypt (cost factor 12) |
## 安装说明
### 1. 克隆代码仓库
```
git clone https://github.com/ericalfonce/webscanner-final-project.git
cd webscanner-final-project
```
### 2. 创建虚拟环境
```
python -m venv venv
# Windows
venv\Scripts\activate
# macOS / Linux
source venv/bin/activate
```
### 3. 安装依赖
```
pip install -r requirements.txt
```
### 4. 运行
```
python run.py
```
在浏览器中打开 [http://127.0.0.1:5000](http://127.0.0.1:5000)。
数据库 (`instance/scanner.db`) 会在首次运行时自动创建,并包含两个预置的测试账号。
## 使用说明
1. **注册** 一个新账号,或使用测试账号登录(见下文)
2. 点击导航栏中的 **新建扫描**
3. 输入目标 URL(例如 `http://localhost/dvwa`)
4. 选择扫描模块:SQLi、XSS、Headers(或同时选择三项)
5. 选择扫描深度:**快速** 或 **完整**
6. 点击 **开始扫描** — 每 2 秒实时更新进度
7. 扫描完成后查看完整报告
8. 点击 **下载 PDF** 获取可分享的报告
### 测试账号
| 用户名 | 密码 | 备注 |
|---|---|---|
| `testuser` | `testpass123` | 默认预置账号 |
## 扫描模式
| 模式 | 爬取页面数 | 爬取深度 | 预计耗时 |
|---|---|---|---|
| **快速** | 最多 10 个 | 1 层 | 1–3 分钟 |
| **完整** | 最多 50 个 | 2 层 | 5–15 分钟 |
## 架构
### 应用工厂模式
本应用使用 Flask 的应用工厂模式(位于 `app/__init__.py` 的 `create_app()`)。扩展(`SQLAlchemy`、`LoginManager`、`CSRFProtect`)在模块级别实例化,并在工厂内部绑定到应用 —— 这允许为测试创建多个应用实例,并避免循环导入。
### 后台线程扫描运行器
扫描在守护线程 (`threading.Thread`) 中运行,以便 HTTP 响应能立即返回,浏览器可以轮询进度。由于后台线程不继承请求上下文,该线程会手动推入其专属的 Flask 应用上下文 (`app.app_context()`)。进度被存储在 `ScanLog` 行中,浏览器每 2 秒通过 AJAX 轮询一次 `/scanner/status/`。
### Blueprint 结构
| Blueprint | URL 前缀 | 职责 |
|---|---|---|
| `auth_bp` | `/auth` | 登录、注册、登出 |
| `dashboard_bp` | `/` | 仪表板和首页 |
| `scanner_bp` | `/scanner` | 扫描生命周期、进度、结果、PDF、历史记录 |
## 项目结构
```
webscanner-final-project/
├── run.py # Entry point — creates app and runs dev server
├── requirements.txt
├── README.md
│
├── app/
│ ├── __init__.py # App factory, extension init, blueprint registration
│ ├── config.py # DevelopmentConfig / ProductionConfig
│ ├── models.py # User, Scan, Finding, ScanLog (SQLAlchemy ORM)
│ │
│ ├── auth/
│ │ ├── routes.py # /auth/register, /auth/login, /auth/logout
│ │ └── forms.py # RegistrationForm, LoginForm (Flask-WTF)
│ │
│ ├── dashboard/
│ │ └── routes.py # / (dashboard index)
│ │
│ ├── scanner/
│ │ ├── routes.py # Scan runner + all /scanner/* routes
│ │ ├── crawler.py # Breadth-first crawler (BFS, same-domain scoping)
│ │ ├── sqli_scanner.py # SQL Injection: error / boolean / time-based
│ │ ├── xss_scanner.py # XSS: reflected payload injection
│ │ ├── header_scanner.py # 7 HTTP security headers
│ │ ├── analyzer.py # Deduplication and severity sorting
│ │ └── reporter.py # ReportLab PDF generation
│ │
│ ├── static/
│ │ └── css/style.css
│ │
│ └── templates/
│ ├── base.html # Shared layout (Bootstrap 5.3)
│ ├── auth/ # login.html, register.html
│ ├── dashboard/ # index.html
│ ├── scanner/ # new_scan.html, scan_progress.html, results.html, history.html
│ └── errors/ # 404.html, 500.html
│
├── data/
│ ├── payloads/
│ │ ├── sqli_payloads.json # 24 SQL Injection payloads
│ │ └── xss_payloads.json # 23 XSS payloads
│ └── educational/
│ └── vuln_info.json # Educational content per vulnerability type
│
└── instance/
└── scanner.db # SQLite database (auto-created, git-ignored)
```
## 数据库模型
### `User`
| 列名 | 类型 | 备注 |
|---|---|---|
| `id` | Integer PK | |
| `username` | String(64) | 唯一 |
| `email` | String(120) | 唯一,以小写存储 |
| `password_hash` | String(256) | bcrypt, cost 12 |
| `created_at` | DateTime | UTC |
### `Scan`
| 列名 | 类型 | 备注 |
|---|---|---|
| `id` | Integer PK | |
| `user_id` | FK → users | |
| `target_url` | String(2048) | |
| `scan_type` | String(20) | `quick` 或 `full` |
| `scan_modules` | String(100) | 逗号分隔:`sqli,xss,headers` |
| `status` | String(20) | `pending` → `running` → `completed` / `failed` |
| `pages_crawled` | Integer | |
| `total_tests` | Integer | |
| `started_at` | DateTime | UTC |
| `completed_at` | DateTime | UTC |
| `error_message` | Text | 失败时设置 |
### `Finding`
| 列名 | 类型 | 备注 |
|---|---|---|
| `id` | Integer PK | |
| `scan_id` | FK → scans | 级联删除 |
| `vuln_type` | String(20) | `sqli`, `xss`, `header` |
| `severity` | String(10) | `high`, `medium`, `low`, `info` |
| `title` | String(200) | |
| `affected_url` | String(2048) | |
| `affected_parameter` | String(200) | |
| `payload_used` | Text | 触发该发现的具体 payload |
| `evidence` | Text | 响应片段 |
| `remediation` | Text | 修复指南 |
| `educational_info` | Text | JSON:了解更多链接和解释 |
### `ScanLog`
| 列名 | 类型 | 备注 |
|---|---|---|
| `id` | Integer PK | |
| `scan_id` | FK → scans | 级联删除 |
| `timestamp` | DateTime | UTC |
| `log_level` | String(10) | `info`, `warning`, `error` |
| `message` | Text | |
## API 端点
除非特别标注为公开,所有路由均需登录。
| 方法 | 路径 | 描述 |
|---|---|---|
| GET/POST | `/auth/register` | 注册新账号(公开) |
| GET/POST | `/auth/login` | 登录(公开) |
| GET | `/auth/logout` | 登出 |
| GET | `/` | 仪表板 |
| GET/POST | `/scanner/new` | 新建扫描表单 + 提交扫描 |
| GET | `/scanner/progress/` | 实时进度页面 |
| GET | `/scanner/status/` | JSON 状态(进度页面每 2 秒轮询一次) |
| GET | `/scanner/results/` | 完整扫描结果 |
| GET | `/scanner/results//pdf` | 下载 PDF 报告 |
| GET | `/scanner/history` | 用户所有扫描记录 |
| POST | `/scanner/delete/` | 删除某次扫描 |
### `/scanner/status/` 响应格式
```
{
"status": "running",
"pages_crawled": 7,
"total_tests": 14,
"findings_count": 3,
"high_count": 1,
"medium_count": 2,
"low_count": 0,
"logs": [
{"level": "info", "message": "Testing: http://target/login", "time": "14:02:33"}
]
}
```
## 配置
`app/config.py` — 通过设置相应的环境变量来覆盖任何默认值:
| 设置 | 默认值 | 环境变量 | 描述 |
|---|---|---|---|
| `SECRET_KEY` | `dev-secret-key-...` | `SECRET_KEY` | Flask session 密钥 — 在生产环境中**必须**更改 |
| `DATABASE_URL` | SQLite `instance/scanner.db` | `DATABASE_URL` | 任何兼容 SQLAlchemy 的 URI |
| `SCAN_REQUEST_TIMEOUT` | `10` | — | 每次 HTTP 请求的超时秒数 |
| `SCAN_REQUEST_DELAY` | `0.5` | — | 请求之间的礼貌延迟(秒) |
| `SCAN_MAX_PAGES` | `50` | — | 每次完整扫描爬取的最大页面数 |
| `SCAN_CRAWL_DEPTH` | `2` | — | 最大 BFS 深度 |
对于生产环境,请设置 `FLASK_ENV=production` 以启用 `ProductionConfig` (`DEBUG=False`)。
## 扫描器模块
### SQL 注入 (`sqli_scanner.py`)
对每个 URL 参数和表单输入应用三种检测技术:
1. **基于错误** — 注入 payload (`'`, `''`, `' OR '1'='1` 等) 并检查响应是否包含 20 多种数据库错误字符串 (`sql syntax`, `ora-`, `sqlite3`, `unclosed quotation mark` 等)
2. **基于布尔型** — 比较真假条件下的响应内容长度 (`AND 1=1` 对比 `AND 1=2`)
3. **基于时间盲注** — 测量在注入 `SLEEP(3)` / `WAITFOR DELAY '0:0:3'` payload 后的响应时间;如果延迟 ≥ 3 秒则标记为漏洞
### XSS (`xss_scanner.py`)
仅检测反射型 XSS。向 URL 参数和表单字段注入 23 个 payload,并检查原始 payload 是否在未转义的情况下出现在响应 HTML 中。使用 BeautifulSoup 解析 DOM 并验证 payload 未被 HTML 实体编码。
### 安全标头 (`header_scanner.py`)
检查目标根 URL 上的七个标头:
| 标头 | 缺失时的严重性 |
|---|---|
| `Content-Security-Policy` | High |
| `Strict-Transport-Security` | High |
| `X-Frame-Options` | Medium |
| `X-Content-Type-Options` | Low |
| `Referrer-Policy` | Low |
| `Permissions-Policy` | Low |
| `X-XSS-Protection` | Low |
### 爬虫 (`crawler.py`)
使用 `collections.deque` 进行广度优先搜索 (BFS)。将所有爬取的链接范围限定在目标域名内。提取内容:
- 所有 `` 链接
- 所有带有输入字段名称的 `
标签:BeEF, CISA项目, Python Flask, SQL注入检测, Web漏洞扫描器, XSS检测, 安全测试, 攻击性安全, 爬虫, 逆向工具