jiaying-wang091/threat-actor-intelligence-tracker
GitHub: jiaying-wang091/threat-actor-intelligence-tracker
将 MITRE ATT&CK、AlienVault OTX 和 CISA KEV 三大威胁情报源自动关联并实体解析到统一可探索数据集中的交互式 Streamlit 应用。
Stars: 0 | Forks: 0
# 威胁行为者情报追踪器
一个交互式的 Streamlit 应用程序,它将 **MITRE ATT&CK Enterprise**(威胁行为者、技术、恶意软件/工具)、**AlienVault OTX**(最近的威胁情报 pulse 和指标)以及 **CISA 已知漏洞利用 (KEV)** 目录关联到一个可探索的数据集中:
```
Threat Actor → Alias → TTP → Malware/Tool → OTX Pulse → CVE → CISA KEV status
```
## 项目目的
安全团队和研究人员经常需要回答这样的问题:*"这个威胁组织使用什么技术,他们部署什么恶意软件,目前是否有人在报告他们的最新活动,以及他们利用的任何漏洞是否在 CISA KEV 列表中?"* 如今要回答这个问题,意味着需要手动交叉引用 MITRE ATT&CK、威胁情报源和 KEV 目录。
此项目自动构建这种关联,具备**自由文本威胁情报与规范 MITRE ATT&CK 行为者身份之间的实体解析**,每个数据点都有完整的来源归因,以及对每个推断(而非确认)关系的明确置信度标签。
**此应用程序中的任何内容都不是模拟、样本或伪造数据。** 每个表格、图表和 KPI 都是根据从三个引用的公共来源获取的数据计算得出的。如果某个来源不可用,受影响的页面将显示明确的错误/空状态,而不是替换为占位符数据。
## 架构
```
threat-actor-tracker/
├── app.py # Streamlit entrypoint: Overview / KPIs
├── pages/
│ ├── 1_Actor_Explorer.py # Single-actor deep dive
│ ├── 2_TTP_Matrix.py # ATT&CK tactic x technique matrix
│ ├── 3_Intelligence_Feed.py # Filterable OTX pulse feed
│ ├── 4_Relationship_Graph.py # NetworkX/PyVis relationship graph
│ └── 5_Vulnerability_Enrichment.py # CISA KEV dashboard
├── src/
│ ├── config.py # Env/config loading, constants, source labels
│ ├── fetch_mitre.py # MITRE ATT&CK STIX 2.1 download + parse + load
│ ├── fetch_otx.py # OTX pulse fetch (paginated, retried, cached) + load
│ ├── fetch_kev.py # CISA KEV JSON download + parse + load
│ ├── transform.py # All SQL queries/aggregations used by pages
│ ├── entity_resolution.py # Alias normalization + 3-stage matching
│ ├── database.py # SQLite schema (single source of truth) + access layer
│ ├── validation.py # Safe field access, date parsing, sanitization, checks
│ └── logging_config.py # Centralized logging setup
├── data/ # SQLite DB, raw source cache, logs (gitignored contents)
├── tests/
│ ├── test_entity_resolution.py
│ ├── test_kev_enrichment.py
│ └── test_data_validation.py
├── requirements.txt
├── .env.example
├── .gitignore
└── LICENSE
```
**数据流:** `src/fetch_*.py` 模块从外部 API 下载(带有本地缓存、重试和超时),解析响应,并通过 `src/database.py` 增改插入到 SQLite 中。`src/entity_resolution.py` 在摄入 OTX 期间,根据 MITRE 派生的别名表解析 OTX pulse 文本。`src/transform.py` 包含 UI 使用的每一个 SQL 查询 —— 页面从不编写原始 SQL。`pages/` 中的每个 Streamlit 页面都是 `transform.py` 之上的一个轻量级展示层。
## 数据来源
| 来源 | 提供的内容 | Endpoint |
|---|---|---|
| **MITRE ATT&CK Enterprise (STIX 2.1)** | 规范的行为者、别名、技术/子技术、战术、恶意软件、工具、关系、外部参考 | `raw.githubusercontent.com/mitre/cti` |
| **AlienVault OTX** | 最近的 pulse、发布日期、标签、指标、CVE/恶意软件引用 | `otx.alienvault.com/api/v1` |
| **CISA KEV Catalog** | CVE 丰富:供应商/产品、添加日期、截止日期、所需行动、已知勒索软件使用情况 | `cisa.gov/.../known_exploited_vulnerabilities.json` |
这三个都是免费的公共来源。OTX 需要一个免费的 API key;MITRE 和 CISA KEV 不需要身份验证。
## 截图
_在本地运行应用后在此处添加截图,例如:_
- `docs/screenshots/overview.png`
- `docs/screenshots/actor_explorer.png`
- `docs/screenshots/ttp_matrix.png`
- `docs/screenshots/intelligence_feed.png`
- `docs/screenshots/relationship_graph.png`
- `docs/screenshots/vulnerability_enrichment.png`
## 本地设置
需要 Python 3.10+(使用 3.11/3.12 测试过;路径是跨平台的,可以在 macOS、Linux 和 Windows 上运行)。
```
git clone
cd threat-actor-tracker
python3 -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
pip install -r requirements.txt
```
### `.env` 设置
1. 获取免费的 AlienVault OTX API key:
(登录 → Settings → API Integration → 复制你的 key)。
2. 复制示例 env 文件并填写:
cp .env.example .env
3. 编辑 `.env`:
OTX_API_KEY=your_real_key_here
`.env` 已在 `.gitignore` 中列出,永远不会被提交。应用程序仅通过 `src/config.py` 中的 `os.getenv("OTX_API_KEY")` 读取此 key,并且该 key 永远不会在 UI 中的任何地方被打印、记录或显示(请参阅 `config.masked_otx_key()`,这是唯一引用过其部分/掩码形式的地方)。
### 数据刷新命令
通过直接运行每个摄入模块来填充(或刷新)本地 SQLite 数据库。**首先运行 MITRE** —— OTX 实体解析依赖于它构建的别名表。
```
python -m src.fetch_mitre # canonical actors, techniques, software (~1-2 min)
python -m src.fetch_otx # recent pulses + entity resolution (requires OTX_API_KEY)
python -m src.fetch_kev # CISA KEV catalog
```
每个命令都会打印摄入记录的 JSON 摘要并记录到 `data/logs/app.log`。刷新状态/时间戳也存储在 `refresh_log` 表中,并显示在应用程序的 Overview 页面和侧边栏中。
下载的原始源数据缓存在 `data/raw/` 和 `data/cache/` 下,具有可配置的 TTL(请参阅 `.env.example`),因此在成功运行后不久重新运行提取命令将重用缓存,而不是重新请求 API。在 Python shell 中将 `force=True` 传递给 `download_mitre_bundle()` / `download_kev_catalog()`,或者删除 `data/raw/` 下的相关文件,以强制重新下载。
### 运行应用
```
streamlit run app.py
```
Streamlit 将在 `http://localhost:8501` 打开应用程序。使用侧边栏在 Overview 页面和五个功能页面之间导航。
## 验证步骤
运行自动化测试套件:
```
pip install pytest # already in requirements.txt
pytest tests/ -v
```
根据规范,本项目的测试套件涵盖:
- **实体解析** (`tests/test_entity_resolution.py`):规范化规则、三阶段匹配优先级,以及五个必需的别名验证示例(APT29, Cozy Bear, NOBELIUM, Midnight Blizzard, The Dukes —— 全部为 MITRE ATT&CK G0016 别名),以及跨行为者消歧和不伪造匹配保证。
- **KEV 丰富** (`tests/test_kev_enrichment.py`):针对与真实源 schema 完全相同的 fixture 数据进行 CISA KEV 解析/加载,包括五个 CVE 验证测试(Log4Shell, EternalBlue, Heartbleed, MOVEit, Citrix ADC)。
- **数据验证** (`tests/test_data_validation.py`):安全字段访问、日期解析、HTML 清理、空值率/重复检测助手,以及数据库 schema 不变量(外键强制执行、表白名单)。
要在运行所有三个刷新命令后验证实时、完全填充的数据库,请在项目根目录中打开一个 Python shell:
```
from src.database import table_row_count
for t in ("actors", "actor_aliases", "techniques", "actor_techniques",
"software", "actor_software", "pulses", "indicators",
"vulnerabilities", "pulse_actors", "pulse_vulnerabilities"):
print(t, table_row_count(t))
```
Streamlit UI 中显示的每个数字都是通过 `src/transform.py` 中的 SQL 查询实时计算的 —— 没有 KPI、图表或表格使用硬编码值。你可以通过检查 `src/transform.py` 来确认这一点:每个函数都对本地 SQLite 数据库执行 `SELECT` 操作。
## 部署
### Streamlit Community Cloud
1. 将此仓库推送到 GitHub(根据 `.gitignore`,不会包含 `.env`)。
2. 在 [share.streamlit.io](https://share.streamlit.io) 上,创建一个指向此 repo、分支和 `app.py` 作为 entrypoint 的新应用。
3. 在应用程序的 **Settings → Secrets** 中,添加:
OTX_API_KEY = "your_real_key_here"
`src/config.py` 通过 `os.getenv` 加载 `OTX_API_KEY`,Streamlit Cloud 会自动将 TOML secrets 作为环境变量注入,因此在本地和云部署之间不需要进行任何代码更改。
4. 部署。请注意,Streamlit Community Cloud 的文件系统是短暂的 —— SQLite 数据库需要在每次重新部署后通过运行提取模块来(重新)填充,或者通过将它们连接到计划作业/启动钩子(超出此模板的范围)来实现。
### 其他平台
任何可以运行 `pip install -r requirements.txt` 然后运行 `streamlit run app.py` 并暴露 `OTX_API_KEY` 环境变量的平台都将完全相同地工作(Render、Railway、Fly.io、自我管理的 VM 等)。
## 限制与已知数据质量风险
- **OTX pulse 质量参差不齐。** OTX 是一个众包的威胁情报平台;pulse 质量、标签一致性和行为者归因因作者而异。本项目不会根据感知的质量对 pulse 进行编辑或过滤。
- **模糊匹配的行为者关联未得到确认。** 由 `fuzzy` 匹配方法(置信度:`low`)产生的任何 pulse 到行为者的链接都是基于相似性的猜测,而不是经过验证的关联,并且在 UI 中出现它的任何地方都做了相应的标记。它永远不应被视为等同于 MITRE 确认的关系。
- **从 OTX pulse 提取的 CVE 是基于正则表达式的**,扫描 pulse 标题、描述和标签以查找 `CVE-YYYY-NNNN` 模式。这可能会错过间接引用的 CVE(例如仅通过漏洞名称),并且无法验证匹配的 CVE 除了被提及之外是否确实与 pulse 的内容*相关*。
- **MITRE ATT&CK 不提供结构化的“原产国”字段**用于入侵集合。本项目故意**不**尝试从自由文本描述中推断来源(这些描述通常讨论带有大量保留意见的来源指控)。除非集成了未来的结构化、可引用来源,否则对于基本上所有行为者,`origin` 字段都为 `NULL` → 显示为 `"Unknown"`。
- **OTX API 速率限制和分页限制**(默认情况下在 `fetch_recent_pulses` 中为 `max_pages=20`)意味着在极大量的时期内可能无法捕获回溯窗口内的每个 pulse;应用程序会显示回溯窗口和上次刷新时间戳,以便用户判断新鲜度。
- **每个 pulse 的指标提取是有限的。** 指标需要每个 pulse 发出第二次请求(`OTX_MAX_DETAIL_FETCHES`,默认每次刷新 150 个),因为 OTX 的批量搜索 endpoint 无法可靠地返回它们。在单次刷新中超出该预算的 pulse 仍然会获得基于标题/描述/标签的 CVE 和行为者提取,只是没有指标级别的数据,直到随后的刷新抓取它们。
- **自动/Sentinel pulse 分类是基于前缀的**(标题以如 "IMMEDIATE THREAT" 或 "Sentinel:" 之类的标记开头),而不是通用的垃圾/质量分类器。不匹配这些前缀的合法低信号分析师 pulse 如果包含 CVE、行为者匹配或恶意软件/活动关键字,仍然会出现在主信息流中;相反,具有不寻常自动风格标题的真正有价值的 pulse 可能会被错误分类。Raw / Automated Feed 视图的存在正是为了不让任何内容被永久隐藏。
- **STIX bundle 大小**:MITRE Enterprise ATT&CK bundle 有几兆字节和数万个 STIX 对象;根据硬件不同,解析大约需要一分钟的时间。
- **SQLite 是单写入的。** 此模板设计用于本地/单用户使用或小规模部署;它不适用于并发的多用户写入访问。
## 关于归因不确定性的道德说明
威胁行为者归因本质上是不确定的、有争议的,并且通常具有政治敏感性。本项目:
- 将 MITRE ATT&CK 的行为者/别名数据视为规范参考,因为它是经过社区审查并明确注明来源的,但并不声称 MITRE 的数据是绝对无误或完整的。
- 从不将低置信度(模糊)文本匹配升级为陈述的事实。在显示行为者关联的每个点,UI 都对匹配方法和置信度进行了明确说明。
- 除非在所使用的源数据中明确且直接地引用了该来源,否则不会推断或显示任何行为者的可疑原籍国 —— 请参阅上面的限制。实际上,这意味着大多数行为者的来源都将显示为 `"Unknown"`,这是故意的,而不是一个 bug。
- 旨在作为了解威胁情报关联 pipeline 如何工作的研究和学习工具,而不是作为操作安全决策的权威归因来源。
## 推荐的简历条目
## 许可证
请参阅 [LICENSE](LICENSE) (MIT)。
标签:CISA KEV, Cloudflare, GPT, Kubernetes, MITRE ATT&CK, Streamlit, 只读文件系统, 威胁情报, 安全规则引擎, 开发者工具, 漏洞管理, 特权检测, 访问控制, 逆向工具