ZappaBoy/vuln-scanner
GitHub: ZappaBoy/vuln-scanner
一个自动化漏洞评估平台,编排 86 个开源安全工具进行并行扫描,并借助可选的 LLM 分析层生成去重结果、PoC 脚本及多格式专业报告。
Stars: 10 | Forks: 0
# 漏洞扫描器
一个自动化漏洞评估平台,它编排 **86 个开源安全工具**,聚合并去重扫描结果,运行可选的 **OpenAI 兼容 LLM 分析层** 用于分类、聚类和修复,生成 **概念验证脚本**,并生成专业的 **Markdown、HTML 和 JSON 报告** —— 所有这些都来自单个 BlackArch Linux Docker 镜像。
## 目录
1. [架构](#architecture)
2. [工具](#tools)
3. [目标类型门控](#target-type-gating)
4. [扫描模式](#scan-modes)
5. [认证扫描](#authenticated-scanning)
6. [LLM 分析](#llm-analysis)
7. [PoC 生成与执行](#poc-generation-and-execution)
8. [插件系统](#plugin-system)
9. [报告格式](#report-formats)
10. [快速开始](#quick-start)
11. [配置](#configuration)
12. [环境变量](#environment-variables)
13. [项目结构](#project-structure)
14. [添加新工具](#adding-a-new-tool)
15. [开发](#development)
16. [DefectDojo 集成](#defectdojo-integration)
## 架构
```
config.toml / env vars / CLI args
↓
AppConfig (pydantic, 3-layer merge: TOML < env < CLI)
↓
Plugin loader — auto-discovers ./plugins/ + ~/.vuln-scanner/plugins/
↓
ScanOrchestrator
• classify_target() → TargetType
• tool.applies_to(target) — skips mismatched pairs
• asyncio + ThreadPoolExecutor — parallel (tool × target) tasks
• AuthConfig forwarded to every applicable tool
↓
ScanResult[] → Assessment
↓
LLMAnalyzer (optional)
• Pass 1: triage + PoC design (threaded, per result)
• Pass 2: PoC generation (PocGenerator, host-safe)
• Pass 3: mitigation (evidence-informed)
• Pass 4: clustering + exec summary
↓
PocRunner (container-only, VS_IN_CONTAINER=1 guard)
↓
┌────────┬────────┬────────┐
│ .md │ .html │ .json │ (all formats written in parallel)
└────────┴────────┴────────┘
↓
DefectDojo (optional)
```
所有扫描工具和 PoC 执行都在 **BlackArch Linux** Docker 容器内运行 —— 不会在宿主机上安装任何东西。
## 工具
86 个按类别组织的工具。每个工具都声明了它支持的目标类型;编排器会自动跳过不兼容的匹配。
### 网络与端口扫描
| 工具 | 备注 |
|------|-------|
| `nmap` | 带有服务/版本检测的全端口扫描 |
| `rustscan` | 快速端口扫描器,结果输入至 nmap |
| `masscan` | 高速 TCP/UDP 扫描器 |
| `naabu` | 带有服务检测的端口扫描器 |
| `netdiscover` | 基于 ARP 的主机发现 |
### Web 应用程序
| 工具 | 备注 |
|------|-------|
| `nuclei` | 基于模板的漏洞扫描器 |
| `nikto` | Web 服务器配置错误扫描器 |
| `wapiti` | 黑盒 Web 漏洞扫描器 |
| `ffuf` | 快速 Web 模糊测试工具 (目录、参数、标头) |
| `feroxbuster` | 递归内容发现工具 |
| `gobuster` | URI/DNS/vhost 暴力破解工具 |
| `wfuzz` | Web 应用程序模糊测试工具 |
| `dalfox` | 带有参数分析的 XSS 扫描器 |
| `xsstrike` | 高级 XSS 检测引擎 |
| `commix` | 命令注入利用工具 |
| `sqlmap` | 自动化 SQL 注入和接管工具 |
| `nosqlmap` | NoSQL 注入扫描器 |
| `httpx` | HTTP 探测与指纹识别 |
| `whatweb` | Web 技术指纹识别工具 |
| `wafw00f` | WAF 检测和指纹识别 |
| `wpscan` | WordPress 漏洞扫描器 |
| `acunetix` | Web 漏洞扫描器 (基于 API) |
| `arachni` | Web 应用程序安全扫描器 |
| `zap` | OWASP ZAP DAST 扫描器 |
| `wapiti` | 黑盒漏洞扫描器 |
| `drheader` | HTTP 安全标头分析器 |
| `humble` | HTTP 标头安全检查器 |
| `hakrawler` | 用于 URL 和 endpoint 的快速 Web 爬虫 |
| `katana` | 下一代 Web 爬虫框架 |
| `gau` | 已知 URL 收集器 (AlienVault, WaybackMachine) |
| `jsluice` | JavaScript 密钥和 URL 提取器 |
| `corscanner` | CORS 配置错误扫描器 |
| `crlfuzz` | CRLF 注入扫描器 |
| `smuggler` | HTTP 请求走私检测器 |
| `linkfinder` | JavaScript/HTML 源码中的 endpoint 发现 |
| `cariddi` | 带有密钥和 endpoint 检测的 Web 爬虫 |
### API & GraphQL
| 工具 | 备注 |
|------|-------|
| `kiterunner` | 使用 kite 文件的 API 路由发现 |
| `graphql_cop` | GraphQL 安全审计工具 |
| `restler` | 有状态 REST API 模糊测试工具 |
| `apifuzzer` | 基于 OpenAPI/Swagger 的模糊测试工具 |
| `cherrybomb` | OpenAPI 规范安全 linter |
| `arjun` | HTTP 参数发现工具 |
| `paramspider` | 从 wayback/来源挖掘参数 |
### DNS 与侦察
| 工具 | 备注 |
|------|-------|
| `amass` | 子域名枚举 (被动 + 主动) |
| `subfinder` | 快速被动子域名枚举 |
| `dnsx` | DNS 解析器和探测工具包 |
| `dnsrecon` | DNS 枚举和区域传输 |
| `fierce` | DNS 侦察和主机发现 |
| `theharvester` | OSINT: 电子邮件、姓名、主机、子域名 |
| `puredns` | 带有通配符过滤的快速子域名暴力破解工具 |
| `alterx` | 子域名排列引擎 |
| `waybackurls` | 从 Wayback Machine 获取历史 URL |
| `httprobe` | 存活的 HTTP/HTTPS 主机探测器 |
### TLS / SSL
| 工具 | 备注 |
|------|-------|
| `testssl` | TLS 配置和密码套件审计 |
| `sslyze` | TLS 扫描器 (密码套件, Heartbleed, ROBOT) |
| `sslscan` | SSL/TLS 服务扫描器 |
| `tlsx` | 快速 TLS 探测 |
| `tls_attacker` | TLS 协议攻击工具 |
| `ssh_audit` | SSH 配置和算法审计工具 |
### SMB 与网络服务
| 工具 | 备注 |
|------|-------|
| `smbmap` | SMB 共享枚举和权限 |
| `enum4linux` | SMB/NetBIOS 枚举 |
| `crackmapexec` | Active Directory 和 SMB 评估 |
| `openvas` | OpenVAS 漏洞扫描器 |
### SAST 与代码分析
| 工具 | 备注 |
|------|-------|
| `bandit` | Python SAST — 常见的安全反模式 |
| `semgrep` | 带有社区规则的多语言 SAST |
| `gosec` | Go 安全检查器 |
| `bearer` | 带有隐私和安全规则的数据流 SAST |
| `horusec` | 多语言 SAST 引擎 |
| `brakeman` | Ruby on Rails SAST 扫描器 |
| `flawfinder` | 针对 C/C++ 常见缺陷的静态分析 |
| `dependency_check` | OWASP 依赖项漏洞扫描器 |
| `pip_audit` | Python 包漏洞检查器 |
### 软件组合分析 (SCA)
| 工具 | 备注 |
|------|-------|
| `osv-scanner` | 开源漏洞数据库扫描器 |
| `npm-audit` | Node.js 包漏洞审计 |
| `govulncheck` | Go 模块漏洞检查器 |
### 密钥检测
| 工具 | 备注 |
|------|-------|
| `gitleaks` | Git 历史密钥扫描器 |
| `trufflehog` | 基于深度信息熵的密钥查找器 |
| `secretfinder` | JS 文件和 endpoint 中的密钥 |
| `detect-secrets` | 基于基准线的密钥扫描器 |
| `noseyparker` | 带有模式规则的高速密钥扫描器 |
### IaC 与配置
| 工具 | 备注 |
|------|-------|
| `checkov` | Terraform/K8s/Dockerfile IaC 扫描器 |
| `tfsec` | Terraform 静态分析 |
| `terrascan` | 多云 IaC 安全扫描器 |
| `hadolint` | Dockerfile 最佳实践 linter |
### 云基础设施
| 工具 | 备注 |
|------|-------|
| `prowler` | AWS/GCP/Azure 安全态势评估 |
| `kube-bench` | CIS Kubernetes 基准检查器 |
### 容器与供应链
| 工具 | 备注 |
|------|-------|
| `trivy` | 容器镜像 + 文件系统漏洞扫描器 |
| `grype` | 容器和包漏洞匹配器 |
## 目标类型门控
编排器将每个目标分类为一个或多个类型,并且仅运行声明支持该类型的工具。这消除了例如针对 Web URL 运行 SMB 工具而产生的噪音。
| 类型 | 示例 | 匹配的工具 |
|------|---------|-----------------|
| `HOST` | `example.com` | DNS、SSL、Web、SMB 工具 |
| `IP` | `10.0.0.1` | 网络、端口、SMB 工具 |
| `CIDR` | `10.0.0.0/24` | 网络扫描器 |
| `URL` | `https://app.example.com` | Web、API、SSL 工具 |
| `PATH` | `/src/myapp` | SAST、SCA、密钥、IaC 工具 |
| `REPO` | `https://github.com/org/repo` | 密钥、SAST、SCA 工具 |
| `IMAGE` | `myapp:latest` | 容器扫描器 |
| `CLOUD` | `aws:profile=prod`, `arn:aws:…` | 云态势工具 (prowler, kube-bench, terrascan) |
分类是自动的 —— 只需传入目标字符串;扫描器会自行识别类型。
可识别的云目标格式:
- AWS ARN: `arn:aws:iam::123456789012:root`
- 命名配置文件简写: `aws:profile=production`
- GCP project: `projects/my-project-id`
- Azure subscription UUID: `00000000-0000-0000-0000-000000000000`
## 扫描模式
| 模式 | 描述 |
|------|-------------|
| `paranoid` | 最高隐蔽性 —— 被动探测,最小足迹 |
| `passive` | 无主动攻击 —— 仅枚举和抓取 Banner **(默认)** |
| `active` | 启用标准漏洞检查 |
| `aggressive` | 全面扫描:所有模板,暴力破解,快速计时 |
## 认证扫描
凭据将被转发到所有适用的 Web 工具 (nuclei, ffuf, feroxbuster, gobuster, nikto, sqlmap, dalfox, wpscan, wapiti, katana, hakrawler, arjun, wfuzz, corscanner, kiterunner, httpx)。
### 全局凭据
除非存在针对目标的覆盖配置,否则将应用于每个目标。
**通过配置:**
```
[scan.auth]
bearer_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
username = "admin"
password = "secret"
[scan.auth.cookies]
session = "abc123"
[scan.auth.headers]
X-API-Key = "my-api-key"
```
**通过环境变量** (仅限全局):
```
VS_AUTH_BEARER_TOKEN=eyJ...
VS_AUTH_USERNAME=admin
VS_AUTH_PASSWORD=secret
```
**通过 CLI** (仅限全局):
```
vuln-scanner --targets https://app.example.com \
--auth-bearer eyJ... \
--auth-cookie session=abc123 \
--auth-header X-API-Key=secret
```
### 针对目标的凭据
当扫描多个需要不同凭据的目标时,请在 `[scan.auth.targets.""]` 下定义针对目标的覆盖配置。匹配的条目会完全**替换**该目标的全局配置 —— 不会进行合并。针对目标的认证仅限配置文件 (环境变量和 CLI 标志只能设置全局默认值)。
```
[scan.auth]
# 全局 fallback — 用于任何没有特定条目的 target
bearer_token = "default-token"
# 主应用的 JWT
[scan.auth.targets."https://app.example.com"]
bearer_token = "app-specific-jwt"
# admin panel 的 Cookie session
[scan.auth.targets."https://admin.example.com"]
[scan.auth.targets."https://admin.example.com".cookies]
session = "s%3Aabc123"
csrftoken = "xyz789"
# 内部 API 的 HTTP Basic
[scan.auth.targets."10.0.0.50"]
username = "apiuser"
password = "s3cret"
# 传统应用的表单登录
[scan.auth.targets."https://legacy.example.com"]
login_url = "https://legacy.example.com/login"
username = "admin"
password = "password123"
[scan.auth.targets."https://legacy.example.com".login_data]
_token = "csrf-value-here"
```
**解析优先级:** `针对目标的配置 > 全局配置`
## LLM 分析
当存在 API key 时,LLM 层会自动激活。它会对扫描结果执行四遍处理:
| 步骤 | 名称 | 功能描述 |
|------|------|-------------|
| 1 | **分类** | 为每个发现分配 CWE、置信度、误报标志、可利用性摘要,并设计 PoC |
| 2 | **PoC 生成** | 编写自包含的 Python/Bash 脚本,使用容器中已有的工具确认发现 |
| 3 | **缓解** | 提供具体的短期缓解措施和永久性修复方案,可选地参考 PoC 证据 |
| 4 | **聚类** | 按根本原因对发现进行分组,编写共享的修复方案,并生成执行摘要 |
### 提供商配置
LLM 客户端兼容 OpenAI-API —— 适用于 OpenAI、Azure OpenAI、Ollama、vLLM、LM Studio、OpenRouter 以及任何其他兼容的 endpoint。
```
[llm]
enabled = "auto" # "auto" | true | false (auto = on when api_key present)
api_key = "" # or set OPENAI_API_KEY env var
base_url = "" # leave empty for OpenAI; set for Ollama/vLLM/etc.
model = "gpt-4o" # REQUIRED when LLM is active — no default
# 采样参数(所有 OpenAI 兼容)
temperature = 0.2
top_p = 0.95
max_tokens = 4096
# top_k 和其他非标准参数放在 extra_body 中:
# [llm.extra_body]
# top_k = 40
```
**Ollama 示例:**
```
[llm]
base_url = "http://localhost:11434/v1"
api_key = "ollama"
model = "llama3.2"
```
**vLLM 例:**
```
[llm]
base_url = "http://localhost:8000/v1"
api_key = "token-abc123"
model = "meta-llama/Meta-Llama-3-8B-Instruct"
```
### 功能矩阵
每个 LLM 功能都是一个命名的特性,支持全局切换,并可按工具或按类别进行覆盖。
| 功能 | 默认 | 描述 |
|---------|:-------:|-------------|
| `logs_analysis` | 开启 | 将工具的原始输出提供给 LLM |
| `enrich` | 开启 | CWE / 置信度 / 误报 / 可利用性分类 |
| `classify` | 开启 | 对发现的类型和风险进行分类 |
| `cluster` | 开启 | 按根本原因对发现进行分组 |
| `mitigation` | 开启 | 生成缓解和修复方案 |
| `generate_poc` | 开启 | 将 PoC 脚本作为报告资产写入 |
| `execute_poc` | **关闭** | 在容器内运行 PoC *(需要 `VS_IN_CONTAINER=1`)* |
| `false_positive_filter` | 开启 | 从报告中抑制可能的误报 |
**全局功能配置:**
```
[llm.features]
generate_poc = true
execute_poc = false # enable only inside Docker
# 按工具覆盖 — 禁用 bandit 的 PoC(SAST,无 runtime target)
[llm.features.tool.bandit]
generate_poc = false
# 按类别覆盖 — 禁用 noisy crawlers 的日志分析
[llm.features.category.web]
logs_analysis = false
```
**功能优先级:** `工具覆盖 > 类别覆盖 > 全局`
### 自定义提示词
所有 LLM 提示词均可被覆盖:
```
[llm.prompts]
enrich_system = "You are a senior penetration tester..."
mitigation_user = "Write remediation steps for: {title}..."
# 可用占位符:{title} {severity} {description} {cwe}
# {exploitability} {tool} {target} {cves} {raw_output}
```
### 范围过滤器
```
[llm]
include_tools = [] # empty = all tools
exclude_tools = ["hakrawler", "gau"]
include_categories = []
exclude_categories = ["dns"]
```
## PoC 生成与执行
### 生成 (始终对宿主安全)
LLM 会为每个发现编写自包含的 Python 和/或 Bash 脚本。脚本使用 BlackArch 镜像中已有的工具 (`curl`、`sqlmap`、`nuclei`、`dalfox` 等) 并写入到 `_assets/poc/`。生成过程绝不执行代码 —— 它仅写入文件。
```
[llm.poc]
languages = ["python", "bash"]
only_severities = ["critical", "high", "medium"]
max_pocs = 20
allow_git_clone = false # permit cloning official exploit PoCs from GitHub
```
### 执行 (仅在容器内)
PoC 的执行受两个独立的防护措施限制:
1. `[llm.features]` 中的 `execute_poc = true`
2. `VS_IN_CONTAINER=1` 环境变量 (内置在 Docker 镜像中)
如果缺少任何一个防护措施,运行器将静默拒绝,因此它**无法在宿主机上执行**。静态拒绝列表会在执行前拒绝包含破坏性模式的脚本 (`rm -rf /`、`mkfs.`、fork 炸弹等)。
```
# 在 container 内启用 PoC 执行
VS_LLM_FEATURE_EXECUTE_POC=true docker compose ... run --rm scanner ...
```
## 插件系统
将定义了一个或多个 `AbstractTool` 子类的 `.py` 文件放入 `./plugins/` (或 `~/.vuln-scanner/plugins/`) 中,它们会在启动时被自动发现 —— 无需修改代码。
**发现顺序** (如果名称冲突,后面的条目会覆盖前面的):
1. `./plugins/` (相对于 CWD)
2. `~/.vuln-scanner/plugins/`
3. 通过 `[plugins] dirs` 或 `--plugin-dir` 配置的额外目录
**示例插件** (`plugins/my_scanner.py`):
```
from vuln_scanner.tools.abstract import AbstractTool
from vuln_scanner.tools.enums import Severity, ScanStatus, TargetType
from vuln_scanner.tools.models import Finding, ScanInput, ScanResult
class MyScannerTool(AbstractTool):
name: str = "my-scanner"
category: str = "web"
# Only runs against URL targets — skipped automatically for IPs, paths, etc.
applicable_targets: frozenset[TargetType] = frozenset({TargetType.URL})
def build_command(self, target: str, scan_input: ScanInput) -> list[str]:
return ["my-scanner", "--target", target, "--json"]
def parse_output(self, raw: str, target: str) -> list[Finding]:
...
```
**配置:**
```
[plugins]
enabled = true
dirs = ["/opt/company-scanners"]
```
**CLI:**
```
vuln-scanner --plugin-dir /opt/company-scanners --targets https://app.example.com
```
### 针对目标的行为
插件工具是全局注册的,但编排器的类型门控控制着每个插件实际针对哪些目标运行。声明了 `applicable_targets = frozenset({TargetType.URL})` 的插件永远不会针对 IP 或文件系统路径触发。
要在类型门控之外将插件限制为特定的目标字符串 (例如,仅针对已知的预发布主机运行),请在 `run()` 中返回 `ScanStatus.SKIPPED`:
```
def run(self, target: str, scan_input: ScanInput) -> ScanResult:
if "staging" not in target:
return ScanResult(tool=self.name, target=target, status=ScanStatus.SKIPPED)
return super().run(target, scan_input)
```
没有配置级别的针对目标的插件过滤器 —— 该逻辑属于插件本身。
## 报告格式
并行生成三种格式。可选择任意组合:
```
[report]
formats = ["markdown", "html", "json"]
output_dir = "./reports"
```
或通过 CLI:`--formats markdown html json`
### Markdown (`.md`)
遵循行业渗透测试惯例的专业结构化报告:
1. **执行摘要** —— 面向管理层的文字描述
2. **范围和方法论** —— 目标列表、使用的工具、扫描配置
3. **严重性评级指南** —— CVSS 范围
4. **发现概览** —— 风险分布矩阵 + 按目标的明细
5. **漏洞集群** —— 根本原因分组 (由 LLM 生成)
6. **详细发现** —— 每个发现:ID、严重性、受影响的系统、描述、业务影响、分析师注、缓解措施、永久修复、PoC 参考
7. **附录 A** —— 扫描错误
8. **附录 B** —— PoC 资产索引
如果多个工具报告了在同一目标上的相同问题,这些发现会被去重为一个显示所有相关工具的单一条目。
### HTML (`.html`)
自包含的单文件报告 (无外部依赖),具有:
- 明暗主题切换
- 按严重性颜色编码的发现卡片
- 可折叠的集群部分
- 统计网格和执行摘要主视觉区
### JSON (`.json`)
`Assessment` 模型的完整结构化转储 —— 发现、LLM 富化信息、集群、统计数据、PoC 记录。适用于 CI/CD pipeline 摄取和下游工具对接。
## 快速开始
`poc.sh` 脚本通过一条命令启动 DefectDojo、三个易受攻击的目标以及扫描器。
**前提条件:** `docker`、`docker compose` 插件、`curl`、`python3`
```
./poc.sh
```
| 步骤 | 操作 |
|------|--------|
| 1 | 检查前提条件 |
| 2 | 加载 `.env` (如果缺失,则从 `.env.example` 复制) |
| 3 | 启动 DefectDojo 技术栈 |
| 4 | 等待 DefectDojo API 准备就绪 |
| 5 | 通过管理员凭据获取 API token |
| 6 | 启动易受攻击的目标容器 |
| 7 | 等待每个目标可达 |
| 8 | 构建扫描器 Docker 镜像 |
| 9 | 运行扫描器,生成报告,推送到 DefectDojo |
| 10 | 打印包含 URL 和清理说明的摘要 |
**使用 LLM 分析:**
```
# 复制示例 env 并添加你的 key
cp .env.example .env
# 编辑 .env:设置 OPENAI_API_KEY 和 VS_LLM_MODEL
./poc.sh
```
**覆盖扫描模式:**
```
SCAN_MODE=active ./poc.sh
```
**清理:**
```
docker compose down -v
docker compose -f docker-compose.target.yaml down -v
```
## 易受攻击的目标
### 本地 (Docker —— 由 `poc.sh` 启动)
| 应用 | URL | 描述 |
|-----|-----|-------------|
| [OWASP Juice Shop](https://owasp.org/www-project-juice-shop/) | http://localhost:3000 | 涵盖 OWASP Top 10 的现代 Node.js 应用 |
| [WebGoat](https://owasp.org/www-project-webgoat/) | http://localhost:8888/WebGoat | Java/Spring 编写的故意不安全的应用 |
### 远程实验室 —— [pentest-ground.com](https://pentest-ground.com)
由 pentest-ground.com 维护的公开的、故意存在漏洞的系统。无需设置 —— 直接扫描以验证工具和 PoC 生成。
| 系统 | URL | 类型 | 漏洞类别 |
|--------|-----|------|----------------------|
| DVWA | `https://pentest-ground.com:4280` | 经典 Web 应用 | CSRF, XSS, SQLi |
| DVGQL | `https://pentest-ground.com:5013` | GraphQL API | CMDi, XSS, SQLi |
| RestFlaw | `https://pentest-ground.com:9000` | REST API | SQLi, 代码注入, XXE |
| GuardianLeaks | `https://pentest-ground.com:81` | Web 应用 | XSS, SSRF, 代码注入 |
```
vuln-scanner --targets \
https://pentest-ground.com:4280 \
https://pentest-ground.com:5013 \
https://pentest-ground.com:9000 \
https://pentest-ground.com:81 \
--mode active
```
## 配置
复制带有注释的模板:
```
cp config.example.toml config.toml
```
**完整参考:**
```
[scan]
targets = ["192.168.1.1", "https://app.example.com", "/src/myapp"]
mode = "passive" # paranoid | passive | active | aggressive
timeout = 300 # per-tool timeout in seconds
rate_limit = null # requests/sec; null = no limit
# 已认证扫描 — 转发至所有适用的 web tools
[scan.auth]
bearer_token = "" # Authorization: Bearer
username = "" # HTTP Basic username
password = "" # HTTP Basic password
login_url = "" # Form-based login URL
# [scan.auth.cookies]
# session = "abc123"
# [scan.auth.headers]
# X-API-Key = "secret"
[tools]
exclude = ["nikto"] # skip specific tools by name
[categories]
include = ["web", "ssl"] # limit to these categories; empty = all
[plugins]
enabled = true
# dirs = ["/opt/company-scanners"]
[report]
formats = ["markdown", "html", "json"]
output_dir = "./reports"
[defectdojo]
url = "http://localhost:8080"
api_key = ""
product_name = "My Product"
engagement_name = "Automated Scan"
# ── LLM 分析 ─────────────────────────────────────────────────────────────
[llm]
enabled = "auto" # "auto" | true | false
api_key = "" # or OPENAI_API_KEY env var
base_url = "" # leave empty for OpenAI
model = "" # required when active, e.g. "gpt-4o" or "llama3.2"
temperature = 0.2
top_p = 0.95
max_tokens = 4096
# extra_body = { top_k = 40 } # 用于 Ollama/vLLM 的 top_k 支持
exclude_tools = []
exclude_categories = []
[llm.features]
logs_analysis = true
enrich = true
classify = true
cluster = true
mitigation = true
generate_poc = true
execute_poc = false # container-only; set VS_LLM_FEATURE_EXECUTE_POC=true
false_positive_filter = true
# 按工具的功能覆盖(tool > category > global 优先级)
[llm.features.tool.bandit]
generate_poc = false
[llm.features.category.dns]
logs_analysis = false
[llm.poc]
languages = ["python", "bash"]
only_severities = ["critical", "high", "medium"]
max_pocs = 20
allow_git_clone = false
```
**配置合并优先级:** `CLI > 环境变量 > config.toml > 默认值`
## 环境变量
### 核心
| 变量 | CLI 标志 | 描述 |
|----------|----------|-------------|
| `VS_TARGETS` | `--targets` | 空格分隔的目标列表 |
| `VS_MODE` | `--mode` | 扫描模式 |
| `VS_TIMEOUT` | `--timeout` | 每个工具的超时时间 (秒) |
| `VS_RATE_LIMIT` | `--rate-limit` | 速率限制 (req/s) |
| `VS_MAX_CONCURRENT` | `--max-concurrent` | 并行工具槽位 |
| `VS_INCLUDE_TOOLS` | `--include-tools` | 按名称设置工具白名单 |
| `VS_EXCLUDE_TOOLS` | `--exclude-tools` | 按名称设置工具黑名单 |
| `VS_INCLUDE_CATEGORIES` | `--include-categories` | 设置类别白名单 |
| `VS_EXCLUDE_CATEGORIES` | `--exclude-categories` | 设置类别黑名单 |
| `VS_OUTPUT_DIR` | `--output-dir` | 报告输出目录 |
### 报告
| 变量 | CLI 标志 | 描述 |
|----------|----------|-------------|
| `VS_FORMATS` | `--formats` | 报告格式:`markdown html json` |
### LLM
| 变量 | CLI 标志 | 描述 |
|----------|----------|-------------|
| `OPENAI_API_KEY` | — | API key (标准环境变量,用作备选) |
| `OPENAI_BASE_URL` | — | Base URL 备选 (用于非 OpenAI endpoint) |
| `VS_LLM_ENABLED` | `--no-llm` | `auto` \| `true` \| `false` |
| `VS_LLM_MODEL` | `--llm-model` | 模型名称 (激活时必填) |
| `VS_LLM_TEMPERATURE` | — | 采样温度 |
| `VS_LLM_MAX_TOKENS` | — | 最大输出 token |
| `VS_LLM_FEATURE_` | `--llm-feature NAME=on` | 全局功能切换,例如 `VS_LLM_FEATURE_GENERATE_POC=false` |
| `VS_LLM_FEATURE_EXECUTE_POC` | `--llm-poc-execute` | 启用 PoC 执行 (仅在容器内) |
### 认证扫描
| 变量 | CLI 标志 | 描述 |
|----------|----------|-------------|
| `VS_AUTH_BEARER_TOKEN` | `--auth-bearer` | Bearer token (`Authorization: Bearer …`) |
| `VS_AUTH_USERNAME` | `--auth-user` | HTTP Basic 用户名 |
| `VS_AUTH_PASSWORD` | `--auth-pass` | HTTP Basic 密码 |
| `VS_AUTH_LOGIN_URL` | `--auth-login-url` | 基于表单的登录 URL |
Cookie 和额外的标头必须通过配置文件或 `--auth-cookie` / `--auth-header` CLI 标志进行设置。
### 插件
| 变量 | CLI 标志 | 描述 |
|----------|----------|-------------|
| `VS_PLUGINS_ENABLED` | `--no-plugins` | 启用/禁用插件自动发现 |
| `VS_PLUGINS_DIRS` | `--plugin-dir` | 额外的插件目录 (空格分隔) |
### DefectDojo
| 变量 | CLI 标志 | 描述 |
|----------|----------|-------------|
| `VS_DEFECTDOJO_URL` | `--defectdojo-url` | DefectDojo base URL |
| `VS_DEFECTDOJO_API_KEY` | `--defectdojo-api-key` | API token |
| `VS_DEFECTDOJO_PRODUCT` | — | Product 名称 |
| `VS_DEFECTDOJO_ENGAGEMENT` | — | Engagement 名称 |
## 项目结构
```
vuln_scanner/
├── config/
│ ├── models.py # AppConfig, AppLLMConfig, PluginsConfig (pydantic)
│ └── loader.py # 3-layer merge: TOML + env (VS_*) + CLI
│
├── tools/
│ ├── enums.py # Severity, Confidence, ScanStatus, ScanMode, TargetType
│ ├── models.py # Finding, ScanInput, ScanResult, AuthConfig (pydantic)
│ ├── target.py # classify_target() — maps target string to TargetType set
│ ├── abstract.py # AbstractTool ABC + subprocess execution helpers
│ ├── __init__.py # TOOL_REGISTRY (86 tools)
│ └── .py # One file per tool (86 total)
│
├── llm/
│ ├── models.py # LLMConfig, LLMFeatures, PocConfig (pydantic)
│ ├── features.py # resolve_features() — tool > category > global merge
│ ├── client.py # LLMClient — thin openai SDK wrapper
│ ├── analyzer.py # LLMAnalyzer — 4-pass analysis pipeline
│ └── prompts.py # Default prompt templates (all overridable)
│
├── poc/
│ ├── models.py # Poc, PocVerdict
│ ├── generator.py # PocGenerator — writes scripts, never executes (host-safe)
│ └── runner.py # PocRunner — executes scripts (VS_IN_CONTAINER guard)
│
├── reports/
│ ├── base.py # AbstractReporter
│ ├── markdown.py # Professional structured Markdown report
│ ├── html.py # Self-contained HTML with light/dark theme
│ └── json_reporter.py # Full Assessment JSON dump
│
├── defectdojo/
│ └── client.py # DefectDojoClient — push findings via REST API
│
├── plugins.py # Plugin auto-discovery (./plugins/, ~/.vuln-scanner/plugins/)
├── model.py # Assessment, Cluster, AssessmentStats
└── orchestrator.py # ScanOrchestrator — type-gated, async concurrent execution
plugins/ # Drop .py plugin files here (auto-discovered at startup)
main.py # Entry point
config.example.toml # Fully documented configuration template
.env.example # Environment variable reference
Dockerfile # BlackArch-based image; bakes VS_IN_CONTAINER=1
docker-compose.yml # DefectDojo stack
docker-compose.scanner.yml # Scanner service
docker-compose.target.yaml # Vulnerable test targets (Juice Shop, WebGoat)
poc.sh # End-to-end quick-start script
```
## 添加新工具
对于一次性或私有工具,请使用[插件系统](#plugin-system) —— 将 `.py` 文件放入 `./plugins/` 中,无需修改代码。对于应随项目一起发布的工具:
1. 创建 `vuln_scanner/tools/mytool.py`:
```
from vuln_scanner.tools.abstract import AbstractTool
from vuln_scanner.tools.enums import Severity, TargetType
from vuln_scanner.tools.models import Finding, ScanInput
class MyTool(AbstractTool):
name: str = "mytool"
category: str = "web"
# Declare which target types this tool supports.
# The orchestrator skips mismatched (tool, target) pairs automatically.
applicable_targets: frozenset[TargetType] = frozenset({TargetType.URL, TargetType.HOST})
def build_command(self, target: str, scan_input: ScanInput) -> list[str]:
return ["mytool", "--target", target]
def parse_output(self, raw: str, target: str) -> list[Finding]:
findings = []
for line in raw.splitlines():
if "VULN" in line:
findings.append(Finding(
title="Example finding",
severity=Severity.HIGH,
description=line,
tool=self.name,
target=target,
))
return findings
```
2. 在 `vuln_scanner/tools/__init__.py` 中注册它:
```
from vuln_scanner.tools.mytool import MyTool
TOOL_REGISTRY: dict[str, type[AbstractTool]] = {
...
"mytool": MyTool,
}
```
3. 将二进制文件添加到 `Dockerfile`:
```
RUN pacman -Sy --noconfirm mytool
```
**提示:**
- 对于写入文件而不是标准输出的工具,请在 `build_command()` 中使用 `OUTPUT_FILE_SENTINEL` 并重写 `run()` 以调用 `self._run_with_tempfile()`。
- 带有 `applicable_targets = frozenset(TargetType)` (默认值) 的工具会针对所有目标类型运行 —— 请仅对真正通用的工具使用此项。
- 找不到二进制文件 → `ScanStatus.SKIPPED` (在报告中隐藏)。工具错误 → `ScanStatus.FAILED` (显示在附录 A 中)。
## 开发
```
# 安装 dev dependencies
uv sync
# 运行测试(仅限 host-safe — 不执行真实工具)
uv run pytest tests/ -v
# Lint
uv run ruff check .
uv run ruff format .
```
**测试类别:**
- `tests/test_config.py` — 配置合并和验证
- `tests/test_target_typing.py` — `classify_target()` 和 `applies_to()`
- `tests/test_orchestrator_gating.py` — 使用模拟工具进行类型门控
- `tests/test_llm.py` — LLM 功能、模拟客户端、PoC 运行器容器防护
- `tests/test_reports.py` — 所有三种报告器 (Markdown、HTML、JSON)
- `tests/test_nmap.py` — nmap 出解析器
**安全规则:** 永远不要在宿主机上运行真正的扫描工具。所有工具执行都在 Docker 容器内针对隔离的目标容器进行。`PocRunner` 强制执行此操作 —— 它会在执行任何 PoC 脚本之前检查 `VS_IN_CONTAINER=1`,并且 Docker 镜像中内置了此变量。
## DefectDojo 集成
当配置了 `api_key` 和 `product_name` 后,发现的结果将被自动推送。
**获取你的 API key:**
1. 在 http://localhost:8080 打开 DefectDojo
2. 登录 (默认:`admin` / `admin`)
3. 前往 **Profile → API v2 Key**
**手动推送:**
```
VS_DEFECTDOJO_API_KEY=your-key \
VS_DEFECTDOJO_PRODUCT="My App" \
uv run vuln-scanner --targets 192.168.1.1
```
标签:Docker容器, LIDS, Petitpotam, Python, 大语言模型分析, 安全工具集成, 实时处理, 密码管理, 插件系统, 攻击面发现, 无后门, 自动化安全评估, 计算机取证, 请求拦截, 逆向工具