RicheyWorks/ZeroDayFeedParser
GitHub: RicheyWorks/ZeroDayFeedParser
一个Java威胁情报工具,从NVD获取最新CVE,按CVSS严重性排序,导出CSV并通过Discord发送严重漏洞告警。
Stars: 0 | Forks: 0
# ZeroDayFeedParser
一个基于 Java 的网络安全威胁情报工具,可从 NIST 国家漏洞数据库(NVD)获取实时 CVE 数据,按 CVSS 严重性对漏洞进行排序,导出结果为 CSV,并在发现关键威胁时通过 Discord 发送实时告警。
本项目作为综合项目呈现实例,展示了 REST API 集成、JSON 解析、威胁排序逻辑和自动化告警功能。
---
## 目录
- [功能特性](#功能特性)
- [项目结构](#项目结构)
- [前置条件](#前置条件)
- [安装与配置](#安装与配置)
- [配置说明](#配置说明)
- [运行应用](#运行应用)
- [输出结果](#输出结果)
- [架构概览](#架构概览)
- [类参考](#类参考)
- [NVD API 说明](#nvd-api-说明)
- [Discord Webhook 设置](#discord-webhook-设置)
- [扩展项目](#扩展项目)
- [已知限制](#已知限制)
- [依赖项](#依赖项)
---
## 功能特性
- 从 NVD 2.0 REST API 获取最近的 20 条 CVE
- 解析 CVSS v3.1 / v3.0 严重性评分以及 CPE 数据中的受影响产品/厂商
- 按严重性对所有威胁进行排序(最高优先)
- 筛选出高(≥ 7.0)和严重(≥ 9.0)的条目用于导出和告警
- 将排序结果导出为带时间戳的 CSV 文件,存放于 `reports/` 目录
- 通过 Webhook 将严重 CVE 发布到 Discord 频道
- 支持 `--dry-run` 模式,测试时抑制 Discord 告警
- 优雅处理 NVD 速率限制,并给出清晰的错误提示
- API 密钥和 Webhook URL 从环境变量读取,不硬编码在源码中
---
## 项目结构
```
ZeroDayFeedParser/
├── pom.xml
├── reports/ # Auto-created on first run; CSV output lands here
└── src/
└── main/
└── java/
└── com/
└── zeroday/
├── Main.java # Entry point
├── engine/
│ └── ThreatRanker.java # Sorting and filtering logic
├── export/
│ ├── CsvExporter.java # CSV file writer
│ └── DiscordAlerter.java # Discord webhook client
├── feed/
│ └── NvdParser.java # NVD 2.0 API client + JSON parser
└── model/
└── ThreatEntry.java # CVE data model
```
---
## 前置条件
- Java 17 或更高版本
- Apache Maven 3.8+
- 能访问互联网(以连接 `services.nvd.nist.gov`)
- 一个拥有 Webhook URL 的 Discord 服务器(可选,仅用于告警)
- 一个免费的 NVD API 密钥(可选,可将速率限制从 5 次/30秒提升至 50 次/30秒)
---
## 安装与配置
**1. 克隆或下载项目**
```
git clone https://github.com/yourname/ZeroDayFeedParser.git
cd ZeroDayFeedParser
```
**2. 通过 Maven 安装依赖**
```
mvn clean install
```
Maven 将自动拉取三个依赖:
- `jsoup 1.17.2` — HTML/HTTP 工具
- `jackson-databind 2.16.1` — JSON 解析
- `rome 1.18.0` — RSS Feed 支持(预留用于未来的 Feed 解析器)
**3. 设置环境变量(参见[配置说明](#配置说明))**
**4. 运行**
```
mvn compile exec:java -Dexec.mainClass="com.zeroday.Main"
```
---
## 配置说明
ZeroDayFeedParser 使用环境变量来存储所有敏感信息。切勿在源码文件中硬编码凭证。
### NVD API 密钥(推荐,非必需)
如果没有密钥,NVD API 允许 **每 30 秒 5 次请求**。使用免费密钥后,提升至 **每 30 秒 50 次请求**。
注册地址:https://nvd.nist.gov/developers/request-an-api-key
```
\# Windows Command Prompt
set NVD\_API\_KEY=your-key-here
\# PowerShell
$env:NVD\_API\_KEY="your-key-here"
\# macOS / Linux
export NVD\_API\_KEY="your-key-here"
```
### Discord Webhook URL(可选)
如果未设置此变量,`DiscordAlerter` 将记录一条警告并优雅跳过告警,不会导致程序崩溃。
```
\# Windows Command Prompt
set DISCORD\_WEBHOOK\_URL=https://discord.com/api/webhooks/your-webhook-here
\# PowerShell
$env:DISCORD\_WEBHOOK\_URL="https://discord.com/api/webhooks/your-webhook-here"
\# macOS / Linux
export DISCORD\_WEBHOOK\_URL="https://discord.com/api/webhooks/your-webhook-here"
```
---
## 运行应用
### 正常运行
获取 CVE、排序、写入 CSV,并对严重条目发送 Discord 告警。
```
mvn compile exec:java -Dexec.mainClass="com.zeroday.Main"
```
### 试运行模式
抑制 Discord 告警。适用于测试、演示和开发。
```
mvn compile exec:java -Dexec.mainClass="com.zeroday.Main" -Dexec.args="--dry-run"
```
### 控制台输出示例
```
\[Main] Fetched 20 CVEs from NVD.
\[Main] 7 High/Critical CVEs after filtering.
\[CsvExporter] Wrote 7 entries to reports/zeroday-2025-04-19.csv
\--- High / Critical CVEs ---
\[2025-04-18] CVE-2025-21234 9.8 (Critical) apache/tomcat
\[2025-04-18] CVE-2025-20981 8.8 (High) microsoft/windows
\[2025-04-17] CVE-2025-19874 8.1 (High) linux/kernel
...
```
---
## 输出结果
### CSV 报告
每次运行都会在 `reports/` 目录下生成一个以日期命名的 CSV 文件:
```
reports/zeroday-2025-04-19.csv
```
列说明:
| 列名 | 说明 |
|---|---|
| CVE | CVE 标识符(例如 CVE-2025-21234) |
| Severity | CVSS 基础评分(0.0 – 10.0) |
| Label | 严重 / 高 / 中 / 低 |
| Product | 来自 CPE 数据的供应商/产品 |
| Date | NVD 发布日期 |
| Patch Link | 指向 NVD 详情页面的直接链接 |
| Summary | 漏洞的英文描述 |
### Discord 告警格式
对于每个严重评分 ≥ 9.0 的 CVE,将向配置的 Discord 频道发送一条消息:
```
\*\*Zero-Day Alert!\*\* `CVE-2025-21234` scored \*\*9.8\*\* (Critical)
Product: apache/tomcat
Patch: https://nvd.nist.gov/vuln/detail/CVE-2025-21234
```
---
## 架构概览
```
NVD 2.0 REST API
│
▼
NvdParser.java — Fetches JSON, maps each vulnerability to a ThreatEntry
│
▼
ThreatRanker.java — rank(): sorts by severity descending
— filterHighAndAbove(): keeps CVSS ≥ 7.0
│
├──────────────────────────────────────┐
▼ ▼
CsvExporter.java DiscordAlerter.java
Writes reports/zeroday-DATE.csv POSTs webhook for CVSS ≥ 9.0
```
`ThreatEntry` 模型是在各层之间传递的共享数据对象。它故意设计为普通的 Java 对象(无框架注解),以保持模型的可移植性和可测试性。
---
## 类参考
### `Main.java`
入口点。编排完整流水线:获取 → 排序 → 筛选 → 导出 → 告警。接受命令行参数 `--dry-run` 以抑制 Discord 调用。
### `model/ThreatEntry.java`
不可变数据类,代表单个 CVE。字段:`id`、`product`、`summary`、`patchLink`、`severity`(double)、`date`(LocalDate)。
### `feed/NvdParser.java`
HTTP 客户端,面向 NVD 2.0 REST API(`services.nvd.nist.gov/rest/json/cves/2.0`)。解析 JSON 响应树,提取 CVE ID、英文描述、CVSS v3.1 评分(降级到 v3.0)、发布日期以及来自 CPE 匹配数据的供应商/产品。读取 `NVD_API_KEY` 环境变量,若存在则将其作为请求头附加。在 HTTP 403(速率限制)时抛出带有描述信息的 `RuntimeException`,而不是静默返回空结果。
### `engine/ThreatRanker.java`
包含两个刻意分离的方法:
- `rank(List)` — 按严重性降序对所有威胁排序,不进行筛选。由调用者决定导出哪些内容。
- `filterHighAndAbove(List)` — 仅返回 CVSS ≥ 7.0 的条目。
- `getSeverityLabel(double)` — 将评分映射为严重 / 高 / 中 / 低。
### `export/CsvExporter.java`
将 UTF-8 编码的 CSV 写入 `reports/zeroday-DATE.csv`。如果 `reports/` 目录不存在则创建。按照 RFC 4180 转义摘要中的嵌入双引号。在原始评分旁包含严重性标签列。
### `export/DiscordAlerter.java`
为每个 CVSS ≥9.0 的条目发送格式化的 Discord Webhook 消息。从环境变量 `DISCORD_WEBHOOK_URL` 读取 Webhook URL。如果变量未设置或为空,则记录一条通知并返回,不抛出异常。如果 Webhook 返回非 HTTP 204 状态码,则向 stderr 记录警告。
---
## NVD API 说明
### API 版本
本项目使用 **NVD 2.0 REST API**。旧版 1.1 JSON Feed(`nvdcve-1.1-recent.json`)已于 2023 年 12 月退役,返回 404。请勿使用。
本项目使用的实时端点:
```
https://services.nvd.nist.gov/rest/json/cves/2.0?resultsPerPage=20
```
### 速率限制
| 场景 | 限制 |
|---|---|
| 无 API 密钥 | 每 30 秒 5 次请求 |
| 有免费 API 密钥 | 每 30 秒 50 次请求 |
如果超出限制,NVD 返回 HTTP 403。`NvdParser` 捕获此错误并抛出带有清晰消息的 `RuntimeException`,而不是静默返回零结果。
### CVSS 评分
解析器首先尝试 CVSS v3.1,然后降级到 v3.0。如果两者都不存在(某些较旧或有争议的 CVE),严重性默认为 0.0,该条目将被 `filterHighAndAbove` 排除。
### CPE 产品提取
供应商和产品名称从 `configurations` 块中的第一个 CPE 匹配字符串中提取。CPE 格式:`cpe:2.3:a:vendor:product:version:...`。这是尽力而为的做法——有些 CVE 没有 CPE 数据,将显示为 "Unknown"。
---
## Discord Webhook 设置
1. 打开你的 Discord 服务器设置 → 集成 → Webhooks
2. 点击 **新建 Webhook**,给它一个名称(如 "ZeroDay Alerts"),并选择一个频道
3. 点击 **复制 Webhook URL**
4. 将其设置为环境变量 `DISCORD_WEBHOOK_URL`(参见[配置说明](#配置说明))
告警器仅会发布 CVSS ≥ 9.0(严重)的 CVE。高严重性 CVE(7.0–8.9)仅导出到 CSV。
---
## 扩展项目
### 添加第二个 Feed 解析器
在 `com.zeroday.feed` 包中创建一个新类,返回 `List`。CIRCL CVE API 是一个不错的选择——它无需身份验证,并以干净的 JSON 格式返回最近的 CVE:
```
https://cve.circl.lu/api/last/10
```
然后在 `Main.java` 中合并结果,再传递给 `ThreatRanker`:
```
List all = new ArrayList<>();
all.addAll(nvdParser.fetchAndParse());
all.addAll(circlParser.fetchAndParse());
List ranked = ranker.rank(all);
```
### 更改严重性筛选阈值
编辑 `ThreatRanker.filterHighAndAbove()` 中的常量:
```
.filter(t -> t.getSeverity() >= 7.0) // change 7.0 to your desired cutoff
```
### 更改每次获取的 CVE 数量
编辑 `NvdParser` 中的 `resultsPerPage` 查询参数:
```
private static final String NVD\_URL =
"https://services.nvd.nist.gov/rest/json/cves/2.0?resultsPerPage=50";
```
NVD 允许的最大值为每请求 2000 条。
### 定时自动运行
在 Windows 上,使用“任务计划程序”定时执行 Maven 命令。在 Linux/macOS 上,添加 cron 任务:
```
\# Run every 6 hours
0 \*/6 \* \* \* cd /path/to/ZeroDayFeedParser \&\& mvn -q compile exec:java -Dexec.mainClass="com.zeroday.Main"
```
---
## 已知限制
- **HackerOneParser 尚未实现。** 仓库中的类存根不可用。HackerOne 没有免费的公开报告端点。它已被排除在主流水线之外。
- **无持久化去重。** 同一天运行两次工具会导致 CSV 中出现重复行,并且同一 CVE 会收到重复的 Discord 告警。简单的解决方案是在本地文件或 SQLite 数据库中记录已发布的 CVE ID。
- **产品字段是尽力而为的结果。** 并非所有 CVE 都提供 CPE 数据,提取逻辑仅使用第一个 CPE 匹配。涉及多个供应商的 CVE 可能只显示一个供应商。
- **无重试逻辑。** 瞬时网络故障将抛出异常而非重试。生产环境下,应将 HTTP 调用封装在带有指数退避的简单重试循环中。
---
## 依赖项
| 依赖 | 版本 | 用途 |
|---|---|---|
| `org.jsoup:jsoup` | 1.17.2 | HTTP 工具 |
| `com.fasterxml.jackson.core:jackson-databind` | 2.16.1 | JSON 解析 |
| `com.rometools:rome` | 1.18.0 | RSS Feed 支持(预留) |
所有依赖均在 `pom.xml` 中声明,由 Maven 自动解析。Java 内置的 `java.net.http.HttpClient`(Java 11+)用于所有 HTTP 调用——无需额外添加 HTTP 客户端库。
---
## 许可证
本项目作为网络安全综合项目提交。所有源代码均为作者原创。
标签:CVE, CVSS, Discord告警, GPT, JSON解析, JS文件枚举, Maven, NVD, PB级数据处理, REST API, 严重性评级, 二进制发布, 域名枚举, 威胁情报, 威胁情报源, 威胁源, 安全管理, 安全运维, 开发者工具, 开源工具, 数字签名, 数据提取, 渗透测试辅助, 漏洞管理, 漏洞验证, 网络安全, 网络安全监控, 网络调试, 自动化, 隐私保护, 零日漏洞, 驱动开发