gumslone/GumVulns
GitHub: gumslone/GumVulns
一款单文件 PHP 命令行工具,通过并行聚合多个漏洞数据库,支持按 CVE、关键词、CPE、purl 或 GitHub 链接检索漏洞情报并返回标准化结果。
Stars: 0 | Forks: 0
# GumVulns
一个单文件 PHP CLI,支持**并行搜索多个漏洞 API** 并
为每个匹配项返回标准化记录:**CVE id、描述、评分、严重程度、
攻击向量、来源**。
## 环境要求
PHP 8.1+,并需配备 `curl`、`json` 和 `mbstring` 扩展。
## 用法
提供三种查询模式,可根据输入自动检测:
```
# CVE id — 查询每个 source
php gumvulns.php CVE-2021-44228
# keyword — NVD + Vulners
php gumvulns.php "apache log4j"
# GitHub download / source link — commit -> OSV.dev, owner/repo/tag -> CPE sources
php gumvulns.php https://github.com/jquery/jquery/archive/refs/tags/3.3.1.zip
php gumvulns.php https://github.com/owner/repo/commit/
# CPE / CPE stub — 解析 platform,解析其 title,返回所有匹配的 CVE
php gumvulns.php "cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*"
php gumvulns.php --cpe apache:log4j
php gumvulns.php --cpe a:openbsd:openssh:9.1 --limit=20
# Package URL (purl) — 通过 OSV.dev 原生查询
php gumvulns.php "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1"
php gumvulns.php "pkg:npm/lodash@4.17.20"
php gumvulns.php "pkg:pypi/django@3.2"
# 通用选项
php gumvulns.php CVE-2021-44228 --json
php gumvulns.php CVE-2021-44228 --source=nvd,redhat
php gumvulns.php --list-sources
php gumvulns.php --help
```
### CPE 模式
接受完整的 **CPE 2.3** 字符串 (`cpe:2.3:a:vendor:product:version:...`)、
旧版 **CPE 2.2 URI** (`cpe:/a:vendor:product:version`),或纯 **片段**
(`product`, `vendor:product`, `vendor:product:version`, `a:vendor:product`)。
随后它会:
1. 将 CPE 解析为全部 11 个字段并输出分解结果。
2. 从 **NVD CPE 字典**解析平台标题。
3. 从支持 CPE 的来源(NVD
`virtualMatchString`、Shodan CVEDB、Vulners)返回**所有匹配的 CVE**,并**按 CVE id 去重**。
每一行列出了报告该漏洞的所有来源。
结果排序规则为:**已确认存在漏洞的优先**(如果提供了版本号),
然后按 **CVSS 评分**排序;如果评分相同,则具有**已知公开
漏洞利用程序**(见下文)的 CVE 排名高于未被利用的 CVE。
### 在 CPE 模式中添加 OSV (`--osv-package`)
OSV.dev 不支持 CPE 搜索 —— 其查询 API 基于包坐标而非
CPE。要将 OSV 结果引入 CPE 搜索中,请显式指定包:
```
php gumvulns.php --cpe apache:log4j:2.14.1 \
--osv-package=Maven:org.apache.logging.log4j:log4j-core
# 或一个 Package URL:
php gumvulns.php --cpe apache:log4j:2.14.1 \
--osv-package="pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1"
```
`SPEC` 格式为 `ecosystem:name[@version]`(名称本身可以包含 `:`,例如 Maven
坐标)或一个 purl。如果提供了版本,则默认使用 CPE 的版本,因此 OSV
会精确返回影响该版本的公告 —— 这些结果会通过 CVE id
合并到 CPE 结果中,并通过 OSV 的版本
范围标记为 **VULNERABLE**。
### 包 URL (purl) 模式
传入一个 [purl](https://github.com/package-url/purl-spec),GumVulns 将进行
**原生 OSV.dev 查询**(OSV 直接理解 purl,包括其版本),因此
您会准确获得影响该包版本的公告 —— 每一项都通过 OSV 的版本
范围标记为 **VULNERABLE**:
```
php gumvulns.php "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1"
php gumvulns.php "pkg:npm/lodash@4.17.20"
php gumvulns.php "pkg:pypi/django@3.2"
```
purl 的 `name` 和 `version` 也将用于查询支持 CPE 的来源
(NVD、Shodan、EUVD、Vulners),并用于驱动漏洞利用/PoC 和 EOL 补充信息,所有结果
均按 CVE id 合并。在此模式下,OSV 是权威的匹配器;CPE 来源
仅作为尽力而为的参考(purl 名称可能不等同于厂商的 CPE 产品字符串)。
### GitHub 链接模式
粘贴一个 GitHub 下载或源码 URL,GumVulns 会提取其中的关键信息:
| URL 形式 | 提取内容 |
|---|---|
| `…/archive/.tar.gz`, `…/commit/`, codeload `…/zip/` | commit SHA |
| `…/archive/refs/tags/.zip`, `…/releases/download//…` | owner, repo, version |
| `…/tree/`, `…/blob//…`, `raw.githubusercontent.com////…` | owner, repo, ref |
随后进行以下搜索:
- **通过 commit** 在 **OSV.dev** 中搜索(使用 `{"commit": …}` 调用 `/v1/query`) —— OSV 会将该哈希值
与每个公告的 git 范围进行匹配。短 SHA 会首先通过 GitHub API 解析为完整
哈希(`GITHUB_TOKEN` 可提高速率限制)。
- **通过 CPE**(`owner`→vendor,`repo`→product,`tag`→version)在支持 CPE 的
来源(NVD、Shodan、Vulners)中进行搜索。
来自两条路径的结果将合并,并按 CVE id 去重。
## 受影响版本范围
结果包含每个 CVE 的**受影响版本范围** —— 即该
范围起始和结束的版本,并带有包含/排除边界:
- **NVD** —— 来自 CPE 配置节点的
`versionStartIncluding/Excluding` + `versionEndIncluding/Excluding`。
- **OSV** —— `introduced` / `fixed` / `last_affected` 事件(为支持生态系统/semver 版本,跳过
GIT commit 范围)。
- **GitHub Advisory** —— 每个受影响包的 `vulnerable_version_range`。
- **EUVD** —— ENISA 的 `product_version` 字符串(自由格式)。
在表格中,它们显示为一个 `Affected` 区块,例如:
```
Affected: org.apache.logging.log4j:log4j-core: >= 2.13.0, < 2.16.0
org.apache.logging.log4j:log4j-core: < 2.12.2
```
`>=`/`<=` 表示该版本处于边界**包含**范围内,`>`/`<` 表示
**不包含**,而 `= X` 表示单一受影响版本。在 CPE 模式下,来自
所有来源的范围都会被合并并去重。`--json` 输出会将它们以结构化形式存放在 `affected[]` 下:
```
{
"product": "org.apache.logging.log4j:log4j-core",
"version_start_including": "2.13.0",
"version_start_excluding": null,
"version_end_including": null,
"version_end_excluding": "2.16.0",
"range": "org.apache.logging.log4j:log4j-core: >= 2.13.0, < 2.16.0"
}
```
## 版本漏洞标记
当您提供**版本**(例如 `apache:log4j:2.14.1` 之类的 CPE 或 GitHub tag
链接)时,GumVulns 会将其与每个 CVE 的受影响范围进行对比并标记:
```
Status: ⚠ VULNERABLE — queried version is within log4j: >= 2.13.0, < 2.16.0
Status: ✓ not affected — queried version is outside the affected ranges
Status: ? unknown — no comparable version range for this product
```
比对过程使用 PHP 的 `version_compare`(可处理 `2.0-beta9`、`1.2.1.2-jre17`
等),并遵循包含/排除边界。仅当漏洞范围的**产品**
与查询匹配时才会进行考量,因此查询 log4j 时,不会与诸如
仅仅捆绑了 log4j 的 Siemens 固件范围进行判定。已确认存在漏洞的结果
将置顶排序。`--json` 输出会为每个结果添加 `vulnerable`(`true`/`false`/
`null`)以及 `matched_range` 字段。
## 漏洞利用 / PoC 可用性
每个结果都会为其 CVE 标注已知的**公开漏洞利用程序 / PoC**
(表格中显示为 `Exploit:` 行,JSON 中显示为 `exploits[]`)。指标体系参考自
[search_vulns](https://github.com/ra1nb0rn/search_vulns):
| 指标 | 来源文件 | 模式 |
|---|---|---|
| **Nuclei** 模板 | `projectdiscovery/nuclei-templates` `cves.json` | 所有 |
| **Exploit-DB** | `exploit-database/exploitdb` `files_exploits.csv` | 所有 |
| **Metasploit** | `rapid7/metasploit-framework` `db/modules_metadata_base.json` | 所有 |
| **PoC-in-GitHub** | `nomi-sec/PoC-in-GitHub` (按 CVE 区分的 JSON) | CVE id 查询 |
这三个批量文件会(并行)下载一次,并
在 `~/.cache/gumvulns` 中缓存 6 小时;预热运行不会增加延迟。PoC-in-GitHub
是按 CVE 获取的,因此它仅在单个 CVE 查找时运行。使用 `--no-poc` 可跳过
所有漏洞利用补充信息。
## 生命周期结束 (EOL) 状态
在提供版本号的 CPE / GitHub 模式下,GumVulns 会针对该产品查询
[endoflife.date](https://endoflife.date),并报告所查询
版本的发布分支是处于**支持阶段**还是**生命周期结束 (END-OF-LIFE)**:
```
Lifecycle: ⚠ END-OF-LIFE (branch 1, latest 1.2.17, EOL 2015-10-15)
Lifecycle: supported (branch 2, latest 2.26.0)
```
这会显示在 CPE 信息头部以及 JSON 输出的 `eol` 字段中。
## CVSS 评分
当来源仅提供 CVSS **向量**而没有基础分数时(例如 OSV),将使用内置计算器
根据向量计算分数和定性严重程度,该计算器支持 **CVSS v2 和 v3.0/v3.1**(带前缀、纯粹或
带括号的向量)。CVSS v4 向量将予以显示,但暂不进行评分。
## 来源
| 来源 | API key | CVE 查找 | 关键词 | CPE | Commit |
|---|---|---|---|---|---|
| NVD (NIST) | 可选 `NVD_API_KEY` | ✅ | ✅ | ✅ | — |
| CIRCL CVE Search | — | ✅ | — | — | — |
| Red Hat Security Data | — | ✅ | — | — | — |
| Shodan CVEDB | — | ✅ | — | ✅ | — |
| Ubuntu Security | — | ✅ | — | — | — |
| OSV.dev (Google) | — | ✅ | — | — | ✅ |
| GitHub Advisory DB | 可选 `GITHUB_TOKEN` | ✅ | — | — | — |
| CISA KEV (已知漏洞利用) | — | ✅ | — | — | — |
| FIRST EPSS (漏洞利用概率) | — | ✅ | — | — | — |
| EUVD (ENISA, EU 数据库) | — | ✅ | ✅ | ✅ | — |
| CVE Details (HTML 抓取) | cookie,见下文 | ✅ | — | — | — |
| Vulners | `VULNERS_API_KEY` | ✅ | ✅ | ✅ | — |
| VulnCheck | `VULNCHECK_API_KEY` | ✅ | — | — | — |
| 漏洞利用/PoC 指标 | — | 补充信息 (所有模式) | | | |
| endoflife.date | — | EOL 状态 (带版本) | | | |
除了上述查询来源外,结果还会被**进一步丰富**:每个 CVE 都会
标注已知的公开漏洞利用程序/PoC(Nuclei、Exploit-DB、Metasploit、PoC-in-GitHub ——
参考自 [search_vulns](https://github.com/ra1nb0rn/search_vulns)),并且当
提供版本时,会从 endoflife.date 获取其生命周期结束 (EOL) 状态。请参阅下文的
[漏洞利用 / PoC 可用性](#exploit--poc-availability) 和
[生命周期结束状态](#end-of-life-status)。
九个来源可以在**零配置**下运行。带密钥的来源在其
环境变量被设置时会自动启用:
```
export NVD_API_KEY=... # strongly recommended — NVD throttles hard without it
export GITHUB_TOKEN=...
export VULNERS_API_KEY=...
export VULNCHECK_API_KEY=...
```
### EUVD (ENISA) 和 CVE Details
- **EUVD** 使用 ENISA EU 漏洞数据库 JSON 搜索 API
(`euvdservices.enisa.europa.eu/api/search`)。CVE 查找通过文本搜索,并
保留 `aliases` 中包含该 CVE 的记录;CPE 模式则通过
`product`/`vendor` 进行过滤。
- **CVE Details** 没有免费 API 且处于 Cloudflare 保护之下,因此 GumVulns
**会抓取公开的 CVE 页面** (`cvedetails.com/cve//`),从页面 meta 标签中提取
描述,并从 HTML 中提取 CVSS 向量(随后在本地计算
分数)。匿名服务器请求会收到 `403`
Cloudflare 质询 —— 若要使用此功能,请从浏览器中复制 `cf_clearance`/会话 cookie
并导出:
export CVEDETAILS_COOKIE='cf_clearance=...; ...'
## 输出
每个来源都会被标准化为相同的字段,当来源未提供严重程度时,将根据
CVSS 基础分数进行推导。请求通过 `curl_multi` 并发执行,因此总延迟大致
等于最慢来源的延迟。`Sources queried` 页脚会报告每个来源的
HTTP 状态、结果数量以及任何错误。
## 添加来源
实现 `VulnSource`(`id`、`name`、`buildRequest`、`parse`),并将一个实例
添加到 `gumvulns_sources()` 中。聚合器会为您处理并发、超时和
错误报告。
标签:API聚合, CPE解析, CVE查询, ffuf, Homebrew安装, OpenVAS, PHP, XSS, 实时处理, 文档结构分析, 漏洞情报