NickStanislawski/vulnerability-scanner

GitHub: NickStanislawski/vulnerability-scanner

一个用 Python 从零构建的模块化 Web 应用漏洞扫描器,支持检测常见安全问题并通过静态 HTML 仪表盘可视化展示结果。

Stars: 0 | Forks: 0

# Web 应用漏洞扫描器 一份完整的记录,介绍从零开始设计、构建模块化漏洞扫描器的过程及经验教训——包括环境配置、扫描逻辑以及结果仪表盘。 ## 1. 项目目标 本项目的目标是构建一个能够识别常见 Web 应用安全漏洞的可用漏洞扫描器,并以简洁、易读的仪表盘展示结果——类似于初级渗透测试员或安全分析师在实际项目中可能使用的工具。 该项目并未对线上生产站点进行扫描(未经明确许可进行扫描既不道德也不合法),而是基于 **DVWA (Damn Vulnerable Web Application)** 进行构建和验证——这是一个专为在合法、受控环境中进行安全培训而设计的、 intentionally 充满漏洞的 Web 应用。 完成后的项目由三部分组成: 1. 执行实际漏洞检查的 Python 扫描引擎 2. 可视化扫描结果的静态 HTML 仪表盘 3. 涵盖环境配置和扫描器架构的支持文档 ## 2. 为什么选择 DVWA 无论意图如何,未经明确授权扫描任何网站都是非法的。DVWA 通过以下特性解决了这个问题: - **合法扫描** —— 未经明确授权扫描任何网站都是非法的,无论意图如何。DVWA 正是专门为此目的而设计的 - **可预测** —— 存在的漏洞是已知并有文档记录的,这使得验证扫描器是否真正正常工作成为可能,而不是产生误报或遗漏真实问题 - **可配置** —— DVWA 具有可调节的难度级别(Low / Medium / High),用于控制应用多少输入过滤,从而允许针对不同级别的防御对扫描器进行测试 在本项目中,DVWA 以 **Low** 安全级别运行,因为目标是验证检测逻辑,而不是测试对高级过滤的绕过。 ## 3. 环境配置 ### 为什么使用虚拟机 DVWA 是故意设计为存在漏洞的软件。直接在主要的开发机器上运行它会使该机器面临不必要的风险——例如,如果配置错误或暴露给网络,某些 DVWA 模块(如文件包含)可能会被用来访问主机系统上的文件。 作为安全最佳实践,DVWA 被隔离在运行于 VirtualBox 中的 **Kali Linux 虚拟机**内,而不是直接运行在 Mac 主机上。这将任何脆弱的行为限制在虚拟机内,从而不会影响主机系统。 ### 架构 ``` ┌─────────────────────────┐ ┌──────────────────────────┐ │ Host: MacBook Pro │ SSH │ Guest: Kali Linux VM │ │ - Python scanner code │ ──────> │ - Docker │ │ - Browser (dashboard) │ :2222 │ - DVWA container │ └─────────────────────────┘ └──────────────────────────┘ │ │ │ Port Forward 8080 │ └───────────────────────────────────┘ ``` - Kali 以 **headless**(无 GUI)模式运行,以减少资源消耗并简化管理 - Docker 在 Kali 中运行 DVWA,并将其暴露在 8080 端口上 - VirtualBox 将主机端口 8080 转发到客户虚拟机,使用环回地址 `127.0.0.1`,这样只有主机才能访问它——而不是更广泛的网络 - Python 扫描器在 Mac 主机上运行,并通过 `http://127.0.0.1:8080` 连接到 DVWA ### 配置步骤(摘要) 1. 在 Kali 虚拟机中安装 Docker (`sudo apt install docker.io`) 2. 在容器中运行 DVWA:`sudo docker run --rm -it -p 8080:80 vulnerables/web-dvwa` 3. 使用 `curl -v http://127.0.0.1:8080` 验证容器是否可访问 4. 配置 VirtualBox 端口转发(主机 `127.0.0.1:8080` → 客户机 `8080`) 5. 从主机浏览器访问 DVWA,登录(`admin` / `password`),并初始化数据库 6. 确认安全级别设置为 **Low** 完整的配置步骤已在 `DVWA_SETUP.md` 中单独记录。 ## 4. Python 扫描器 ### 设计理念 该扫描器被构建为一组**独立的、单一职责的模块**,每个模块针对一类漏洞。这反映了真实漏洞扫描工具的结构,并使代码库易于扩展——添加新检查只需编写一个新模块并在 orchestrator 中注册即可。 每个模块都返回一个 `Finding` 对象列表: ``` @dataclass class Finding: category: str severity: str title: str description: str remediation: str ``` 这种一致的数据结构意味着每个模块,无论检查什么内容,都可以由 orchestrator 进行相同的组合和处理。 ### 构建的模块 **`headers_check.py`** 向目标发送请求并检查响应头,以确定是否存在关键的安全 header:`Content-Security-Policy`、`Strict-Transport-Security`、`X-Frame-Options`、`X-Content-Type-Options` 和 `Referrer-Policy`。每个缺失的 header 都会被标记为适当的严重级别并提供修复建议。 **`ssl_check.py`** 打开到 443 端口的原始 socket 连接并检查 SSL/TLS 证书,检查是否过期、自签名以及弱密码套件。如果根本没有 SSL(就像运行在纯 HTTP 上的 DVWA 那样),这将被标记为中等严重级别的发现。 **`ports_check.py`** 使用 `concurrent.futures.ThreadPoolExecutor` 并发扫描精心挑选的高风险端口列表。如果与数据库(MySQL、PostgreSQL、MongoDB、Redis)相关的端口被暴露,则会被标记为严重,因为数据库永远不应从受信任网络之外直接访问。 **`sql_injection_check.py`** 登录 DVWA(处理其 CSRF token 要求),抓取目标页面的 HTML 表单,并向每个输入字段提交一组常见的 SQL 注入 payload。系统会将响应与已知的 SQL 错误特征列表(例如 `"you have an error in your sql syntax"`)进行比对,以检测注入是否成功。 **`xss_check.py`** 结构与 SQL 注入模块类似,但它向 DVWA 的反射型和存储型 XSS 页面上的表单提交标准的 XSS payload(例如 ``),然后检查 payload 是否在响应中未经转义地被反射回来——这表明该应用程序未对用户输入进行清理。 ### 身份验证处理 一个显著的技术障碍是,早期版本的 SQL 注入和 XSS 模块没有返回任何发现,尽管已知 DVWA 存在漏洞。调查发现,扫描器的登录请求被拒绝了,因为 DVWA 在其登录表单中包含了一个 **CSRF token** (`user_token`),必须在提交用户名和密码的同时提交它。解决方法是首先获取登录页面,使用 BeautifulSoup 解析出当前 token,并将其包含在登录的 POST 请求中。这是一个很好的现实世界身份验证怪癖示例,扫描器必须考虑到这一点——许多现代 Web 应用使用 CSRF 保护,简单的脚本登录在面对这些保护时会默默失败。 ### Orchestrator `main.py` 将所有五个模块结合在一起: 1. 针对目标 URL 运行每个模块 2. 将所有发现合并到一个列表中 3. 按严重级别对发现进行排序(critical → high → medium → low) 4. 构建每个严重级别的摘要计数 5. 将完整的结果集输出为 JSON 文件 ``` { "target": "http://127.0.0.1:8080", "total_findings": 11, "summary": { "critical": 2, "high": 4, "medium": 4, "low": 1 }, "findings": [ ... ] } ``` ### 严重级别判定标准 | 严重级别 | 标准 | |----------|----------| | Critical | 直接导致系统被攻破的路径——例如确认的 SQL 注入、暴露的数据库端口 | | High | 需要极少额外努力即可利用的严重弱点——例如确认的 XSS、缺失 CSP/HSTS | | Medium | 需要更多努力或特定条件才能利用的较高风险——例如缺失点击劫持保护、无 SSL | | Low | 信息性——不直接促成攻击,但反映了较差的安全卫生习惯 | ## 5. 针对 DVWA 的扫描结果 对 DVWA(Low 安全级别)运行完整的扫描器产生了 11 项发现: - **2 项 Critical** —— 暴露的 MySQL 端口、确认的 SQL 注入 - **4 项 High** —— 缺失 CSP、缺失 HSTS、反射型 XSS、存储型 XSS - **4 项 Medium** —— 缺失 X-Frame-Options、缺失 X-Content-Type-Options、无 SSL/TLS、暴露的备用 HTTP 端口 - **1 项 Low** —— 缺失 Referrer-Policy 这些结果与 DVWA 记录的漏洞高度一致,确认了扫描器的模块功能正常,既没有产生误报,也没有遗漏已知问题。 ## 6. 仪表盘 ### 设计决策 我们构建了一个独立的 HTML/CSS/JavaScript 仪表盘,而不是完整的 React 应用程序。这是一个刻意的范围决定——该项目的目标是展示漏洞扫描和评估技能,而不是作者已经具备经验的前端框架熟练度。静态页面也意味着仪表盘不需要构建步骤,可以直接通过 GitHub Pages 托管,且零配置。 ### 功能 - 显示按严重级别统计发现数量的摘要磁贴 - 可过滤的发现列表(按严重级别过滤) - 可展开的发现——点击某项发现会显示其修复指南 - 颜色编码的严重级别标签,便于快速视觉扫描 - 简洁、明亮的、受安全工具启发的视觉风格,使用等宽字体 ### 开发期间捕获的安全漏洞 在开发过程中,出现了一个有趣的问题:仪表盘最初使用 `innerHTML` 来渲染发现描述。由于实际的扫描发现中有几个包含原始的 payload 文本,如 ``(XSS 测试期间使用的实际 payload),使用 `innerHTML` 渲染它会导致浏览器将其解释为真实的 HTML——可能会执行嵌入在扫描器自身输出中的 script 标签。通过改用安全的 DOM 方法(`textContent`)而不是 `innerHTML` 修复了这个问题,确保发现中的任何类似 HTML 的内容始终显示为纯文本,而不是被执行。 这是一个有用的(尽管是次要的)现实提醒:**任何显示不受信任或攻击者控制字符串的工具都需要谨慎处理该数据**,即使是内部工具也是如此。 ## 7. 项目结构 ``` vulnerability-scanner/ ├── dashboard/ │ └── dashboard.html ├── scanner/ │ ├── main.py │ ├── scan_results.json │ └── scanners/ │ ├── headers_check.py │ ├── ssl_check.py │ ├── ports_check.py │ ├── sql_injection_check.py │ └── xss_check.py ├── writeups/ │ ├── DVWA_SETUP.md │ └── SCANNER_WRITEUP.md └── README.md ``` ## 8. 经验总结 - 如何使用虚拟化安全地隔离故意设计为存在漏洞的软件,以及为什么从安全角度来看这种隔离很重要 - 真实的 CSRF 保护如何悄无声息地破坏简单的脚本身份验证,以及如何解决这些问题 - 如何设计一个模块化且易于扩展的扫描器架构 - 如何以编程方式检测和验证几种不同的漏洞类别:缺失的安全 header、SSL/TLS 配置错误、暴露的端口、SQL 注入和 XSS - 即使在防御性安全工具中,安全数据处理的重要性——在仪表盘本身中捕获并修复了自身造成的 XSS 渲染漏洞 ## 9. 未来改进 - 将 Python 扫描器封装在 Node.js REST API 中,以支持从仪表盘进行实时的按需扫描,而不是静态 JSON 输出 - 添加支持身份验证的抓取,以测试更多 DVWA 模块(CSRF、文件包含、命令注入) - 为扫描报告添加 PDF 导出选项 - 使用更广泛的模式库和针对未知密钥格式的基于熵的检测来扩展机密检测模块 - 将 API 部署在免费层级的主机(Render/Railway)上以进行全面的实时演示,仅扫描预先批准的练习目标 ## 10. 道德声明 该扫描器专门针对 DVWA 构建和测试,DVWA 是一个明确为此目的而设计的工具,在隔离的本地环境中运行。在开发过程中的任何时刻,都没有对外部或第三方系统进行扫描。未经明确、书面授权扫描任何系统都是不道德和非法的,该项目从一开始的设计就旨在完全避免这种风险。
标签:CISA项目, DOE合作, Python, Splunk, 加密, 多模态安全, 数据可视化, 无后门, 漏洞扫描器, 请求拦截, 逆向工具