shlin168/go-nvd

GitHub: shlin168/go-nvd

go-nvd 是一个将 NVD 的 CVE/CPE 数据转储到本地数据库并提供与官方 API 规范兼容的查询服务的 Go 工具,旨在解决 NVD API 速率限制下无法支持高并发查询的问题。

Stars: 13 | Forks: 2

# go-nvd [![Actions 状态](https://github.com/yuin/goldmark/actions?query=workflow:test](https://static.pigsec.cn/wp-content/uploads/repos/cas/96/96516d7a51f21139fae950e3129296fedeb5ab5f68f6a4dd1d280445b5bfdb15.svg)](https://github.com/shlin168/go-nvd/actions/workflows/go.yml) NVD 官方提供了 [CPE](https://nvd.nist.gov/developers/products) 和 [CVE](https://nvd.nist.gov/developers/vulnerabilities) 的 API,两者都有[速率限制](https://nvd.nist.gov/general/news/API-Key-Announcement)。 为了支持高并发查询,`go-nvd` 提供了将 NVD 数据转储到自有数据库并在其上运行 API 服务器的命令,提供与 NVD 相同的 API 规范和部分参数。 **支持的数据库:** - MongoDB ``` API DB (nvd) ┌────────────────┐ ┌───────────┐ http │ ┌────────────┐ │ │ ┌───────┐ │ nvdetl req ———▶ │ │ (get) cve │-│- - - —▶ │ │ cve │ │ (command) ┌───────┐ │ └────────────┘ │ │ └───────┘ │ ◀────────── │ NVD │ http │ ┌────────────┐ │ │ ┌───────┐ │ └───────┘ rsp ◀─── │ │ (get) cpe │-│- - - —▶ │ │ cpe │ │ │ └────────────┘ │ │ └───────┘ │ └────────────────┘ └───────────┘ - - —▶ read —————▶ write / data flow ``` 要使用 Docker 进行尝试,请查看 [playground](#playground) 部分。 ## 注意事项 与官方 NVD API 相比,`go-nvd` 库具有一些显著的特点: - **仅支持部分查询参数:** - **CVE**:`cveId`、`cpeName`、`keywordSearch`(`keywordExactMatch`)、`resultsPerPage`(默认值:`2000`)和 `startIndex` - **CPE**:`cpeName`、`cpeMatchString`、`keywordSearch`(`keywordExactMatch`)、`resultsPerPage`(默认值:`10000`)和 `startIndex` - **强制查询参数:** 在查询字符串中必须至少提供一个查询参数,而官方 NVD API 在未提供参数时会返回所有 CVE/CPE。 - **CVE**:必须提供 `cveId`、`cpeName` 或 `keywordSearch` 之一,否则会引发 `400` 错误 - **CPE**:必须提供 `cpeName`、`cpeMatchString` 或 `keywordSearch` 之一,否则会引发 `400` 错误 - **不同的 CPE 版本匹配逻辑**,可能会导致不同的结果: - 例如,当查询版本介于 `apache:http_server:2.0.0` 和 `apache:http_server:2.0.44` 之间时,应该返回 `CVE-2003-0132`。但是,它应该与部分版本 `apache:http_server:2.0` 匹配吗?NVD 不会返回它,而本仓库将 `2.0` 视为 `2.0.0` 并返回 `CVE-2003-0132`。 ## 数据库 详情请查看 [db.md](docs/db.md)。 ## ETL 详情请查看 [nvd.md](docs/nvd.md): - [`nvdetl`](docs/nvd.md#usage):如何使用该命令将数据转储到数据库 - [从头开始 ETL](docs/nvd.md#etl-from-the-start):如何按正确的顺序将所有数据从 NVD 转储到数据库 ## API **就绪端点:** `nvd/v1/readiness` ### GET: `/nvd/v1/cve` 此 API 模拟了 [NVD CVE API](https://nvd.nist.gov/developers/vulnerabilities),实现了查询字符串中 `cveId`、`cpeName`、`keywordSearch`(`keywordExactMatch`)、`resultsPerPage`(默认值:`2000`)和 `startIndex` 的逻辑。响应格式与官方 NVD API 相同。 **查询示例:** - 通过 `cveId` 查询:`/nvd/v1/cve?cveId=CVE-2006-3240` - 通过 `cpeName` 查询:`/nvd/v1/cve?cpeName=cpe:2.3:a:dotproject:dotproject:*:*:*:*:*:*:*:*` - 通过 `keywordSearch` 查询:`/nvd/v1/cve?keywordSearch=Java Oracle` - 精确匹配:`/nvd/v1/cve?keywordSearch=Java Oracle&keywordExactMatch` **响应格式(200 - 找到):** 与 [NVD](https://csrc.nist.gov/schema/nvd/api/2.0/cve_api_json_2.0.schema) 格式相同 ``` { "resultsPerPage": 1, "startIndex": 0, "totalResults": 1, "format": "NVD_CVE", "version": "2.0", "timestamp": "2022-12-28T15:01:34.530", "vulnerabilities": [...], // CVE list } ``` **响应格式(200 - 未找到):** ``` { "resultsPerPage": 0, "startIndex": 0, "totalResults": 0, "format": "NVD_CVE", "version": "2.0", "timestamp": "2022-12-28T15:01:34.530", "vulnerabilities": [], // CVE list } ``` ### GET: `/nvd/v1/cpe` 此 API 模拟了 [NVD CPE API](https://nvd.nist.gov/developers/products),实现了查询字符串中 `cpeName`、`cpeMatchString`、`keywordSearch`(`keywordExactMatch`)、`resultsPerPage`(默认值:`10000`)和 `startIndex` 的逻辑。响应格式与官方 NVD API 相同。 **查询示例:** - 通过 `cpeName` 查询:`/nvd/v1/cpe?cpeName=cpe:2.3:a:dotproject:dotproject:*:*:*:*:*:*:*:*` - 通过 `cpeMatchString` 查询:`/nvd/v1/cpe?cpeMatchString=cpe:2.3:o:microsoft:windows_10` - 通过 `keywordSearch` 查询:`/nvd/v1/cpe?keywordSearch=Java Oracle` - 精确匹配:`/nvd/v1/cpe?keywordSearch=Java Oracle&keywordExactMatch` **响应格式(200 - 找到):** 与 [NVD](https://csrc.nist.gov/schema/nvd/api/2.0/cpe_api_json_2.0.schema) 格式相同 ``` { "resultsPerPage": 1, "startIndex": 0, "totalResults": 1, "format": "NVD_CPE", "version": "2.0", "timestamp": "2022-12-28T15:01:34.530", "products": [...], // CPE list } ``` **响应格式(200 - 未找到):** ``` { "resultsPerPage": 0, "startIndex": 0, "totalResults": 0, "format": "NVD_CPE", "version": "2.0", "timestamp": "2022-12-28T15:01:34.530", "products": [], // CPE list } ``` ## 指标 ### 服务器 #### HTTP 请求 - `http_request_total{api=...,code=...}`(计数器):每个 HTTP 状态码的请求数 - `api` 包括: - `/nvd/v1/cve` - `/nvd/v1/cpe` - `http_request_duration_seconds`(直方图):请求延迟的直方图 #### 服务 - `get_request_total{api=...,status=...}`(计数器):获取扫描报告和状态的请求数 - `api` 包括: - `/cve` - `/cpe` - `status` 包括: - `found` - `not_found` - `error` # Playground ### 1. 构建 `nvd-tools` 镜像 ``` cd go-nvd GOOS=linux go build -o service/build/bin/ ./... cd service/build docker build -t nvd-tools . ``` ### 2. 以 MongoDB 作为后端数据库启动 查看 [端点](./docs/service.md#endpoints) 了解所有暴露的端口。 #### MongoDB ``` cd service/test docker-compose -f docker-compose-mongo.yaml up -d ``` ### 3. 将示例数据转储到数据库 查看 [用法](./docs/nvd.md#usage) 了解 `nvdetl` 命令的用法: - `-apikey`:如果提供,则使用 API key 查询 NVD - `-wait`:每次向 NVD 发送 API 请求之间的休眠时间 #### MongoDB ``` # 导出 lastModified 在 2023-03-01 和 2023-03-02 之间的 CVE docker run --rm --network go-nvd --entrypoint nvdetl nvd-tools \ -db-type mongo -db-user admin -db-pwd admin -db-endpoint mongo:27017 \ -sdate 2023-03-01 -edate 2023-03-02 -batch 100 -type cve # 导出 lastModified 在 2023-03-01 和 2023-03-02 之间的 CPE docker run --rm --network go-nvd --entrypoint nvdetl nvd-tools \ -db-type mongo -db-user admin -db-pwd admin -db-endpoint mongo:27017 \ -sdate 2023-03-01 -edate 2023-03-02 -batch 100 -type cpe ``` ### 4. 测试 API 端点 #### CVE API ``` curl 'http://localhost:8080/nvd/v1/cve?cveId=CVE-2022-26579' ``` #### CPE API ``` curl 'http://localhost:8080/nvd/v1/cpe?cpeName=cpe:2.3:a:luya:yii-helpers:1.0.0:*:*:*:*:*:*:*' ```
标签:API服务, CVE, EVTX分析, Go, MongoDB, NVD, Ruby工具, 数字签名, 数据同步, 日志审计, 自定义请求头, 请求拦截