面向云与身份事件响应的取证重建引擎。
面对碎片化的云、SaaS 和身份遥测数据——控制平面日志、登录事件、令牌与授权活动——NV 会重建入侵最可能在账户与服务之间的移动路径,枚举其他最可能的潜在路径,并以经过校准、可解释的置信度报告每一步。它拒绝断言证据无法支持的内容。
检测只告诉你发生了某件事。Nimbus Vestige 告诉你如何发生——以及还可能发生什么。
现代入侵并非“破门而入”,而是“登录进入”。身份如今已成为主要攻击载体,牵涉到绝大多数云 IR 调查,而且大多数入侵跨越多个表面——身份、云、SaaS 以及端点。记录这些入侵的遥测数据碎片化且不一致,这已经迫使响应者只能依靠不完整的数据手工重建事件经过。
手工重建速度缓慢,而且会以可预见的方式失败:响应者会锚定第一个看似合理的叙事,从而错过真正的那个。NV 将重建过程自动化,并直接针对这一失败模式,始终呈现合理路径的排序空间,而非单一叙事。
关键在于,NV 将诚实作为产品。市场公开宣称的敌人是黑盒式置信度——一种在不展示推理过程的情况下就断言结论的工具。NV 生成的每个数字都可追溯到为其赢得分数的具体证据,凡是无法支持的内容都会被保留,而不是猜测。
NV 不是检测器、扫描器、审计器,也不是攻击执行工具。这些工具告诉你某件事发生了,并对其进行衡量。NV 则逆向工作——从模式出发,跨越碎片化的身份资产,对机制进行溯因重建。
蓝队不断再生;红队趋于商品化。 进攻性工具发现的是有限、可修补的漏洞集合,并且正在融入自动化 CI/CD 安全流水线。重建入侵如何发生永远不会终结——攻击者不断发明新手法,因此这种需求是永久且自我更新的。
引擎与底层基础设施无关。 核心逻辑——从模式重建机制,并带有校准置信度和停止护栏——首先落地于云/身份领域,但后续可移植到网络、端点和 OT。目标可以改变,而无需重写核心论点。
重建助力加固。 一旦你知道他们是如何进入的——以及还有哪些门是开着的——你就能构建防御。未走但可能走的路径是一份加固待办清单,其价值往往超过重建本身,因为大多数入侵利用的是可预防的暴露,而非新颖的技战术。
它在全新入侵上也能优雅降级——而这正是最关键的突发事件。签名/规则引擎在零日攻击面前会陷入盲区;NV 的溯因核心仍能产出最可能的路径,并诚实标记为较低置信度。
诚实是一道护城河。 带校准、基于案例的置信度以及排序的备选方案,正是市场所宣称想要的,也是黑盒竞争者在结构上无法在不重新设计的情况下提供的。
原始提供商日志 → 标准化事件/实体图 → 重建引擎 → JSON → GUI。``` O365 / Entra audit logs nv_extract_identity_events.py AWS CloudTrail (IAM/STS/S3) nv_extract_cloudtrail_events.py (ingest + normalize) ▼ normalized identity events (JSONL) ← one event model, any substrate │ nv/graph.py (typed per-actor timelines) ▼ reconstruction engine ├─ nv/patterns.py known layer: ATT&CK identity pattern library ├─ nv/providers.py provider packs: per-substrate op→ATT&CK vocab (Entra + AWS) ├─ nv/validation.py Phase 3: provenance + integrity gate on every pattern ├─ nv/feeds.py live ATT&CK STIX / TAXII / Sigma clients + scheduler ├─ nv/confidence.py evidence-corroboration scorer (calibratable weights) ├─ nv/calibration.py fit + measure confidence against labeled ground truth ├─ nv/reconstruct.py most-likely chain + ranked competing paths + trust floor └─ nv/scope.py authorized-scope gate (refuses unauthorized tenants/accounts) │ run_nv.py ▼ reconstruction.json ──► nv_gui.html (embedding canvas + two-column view + trust slider)
GUI 是一个**纯视图层** — 它渲染引擎输出,并让分析师移动
信任下限。它本身不包含任何重建逻辑。
---
## 置信度模型(整个产品的可信度)
每一步都带有 [0, 1] 区间内的置信度,通过**证据佐证**构建:```
confidence = per-technique base rate
+ bonus for each independent corroborating signal
(source IP, device, successful outcome, temporal adjacency, broad-consent flags)
− penalty for missing signals (e.g. no source IP to corroborate origin)
路径分数以几何平均组合其各环节,因此一个薄弱环节会诚实地拉低整条路径,而不会被平均掉。
上述所有权重——每项技术的基准比率、每个信号的加成、缺失惩罚——都位于 nv/confidence.py 中的单个 PARAMS 表中。这些是 NV 的 v1 先验,并且它们是可校准的:nv/calibration.py 可以针对带标签的 ground truth 重新拟合它们,引擎将加载拟合结果;未提供校准时,则回退到 v1 先验(见下文)。
暂扣规则内置于引擎的输出契约中,而不仅仅是 UI。低于下限时,步骤会被暂扣。拖动下限正是诚实与覆盖权衡的具象化:向上代表严格/高信任,向下代表宽松/高覆盖。默认下限是一个编辑决策,决定分析师介入之前 NV 的位置。
v1 权重是合理的,但它们只是先验。nv/calibration.py 会针对带标签的 ground truth——即我们知道哪些事件属于入侵、哪些事件为良性的事件——对它们进行调优,并且关键在于会衡量调优是否真的起到了作用;只有当校准降低了校准误差、而不只是挪动数字时,该校准才会被采纳。
校准后的置信度只意味着一件事:NV 对某个步骤的置信度应当等于该步骤确实位于攻击路径上的概率。因此,每个带标签事件的置信度都被视为预测概率,随后由校准框架进行拟合:
已验证/暂扣阈值属于策略而非校准,因此保持原样。
它会报告 Brier 分数、对数损失、ECE、AUC、可靠性表,以及信任下限扫描(每个下限下的真实步骤召回率对比良性误报率),并给出校准前后的对比——从而使诚实与覆盖之权衡一目了然,而不仅仅是一个数字。```bash
python3 calibrate.py --labeled run_labeled.jsonl --origin live
--run-label "badzure-2026-07 tenant-x" --out calibration.json
python3 calibrate.py --out calibration.json
python3 run_nv.py events.jsonl out.json --authorize t.onmicrosoft.com
--calibration calibration.json
**真实来源。** 诚实的输入来自在真实租户中运行 BadZure / MAAD-AF 所产生的遥测数据,通过将统一审计日志与攻击工具自身的活动记录进行关联来标注(工具导致的每个事件都在审计日志中;其他一切都是良性的——参见 `nv/calibration.py` 中的 `LABELED_SCHEMA`)。在你将其指向真实运行之前,`eval/calibration_cases.py` 提供一个具有文档化形状的 **代理** 语料库,并且从中拟合出的每个产物都会在出处中标记 `source="proxy"`,因此代理拟合永远不会被误认为是真实运行拟合。`calibration.proxy.json` 就是捆绑的代理产物。
在捆绑的代理语料库上,拟合结果有明显改进——Brier 0.398 → 0.045,ECE 0.576 → 0.081,AUC 0.81 → 0.91,并且在 0.60 阈值下的良性误报率从 0.69 骤降至 0.00(v1 先验对良性活动过于自信)。代理刻意保持保守;真实租户运行才会产生你应当实际部署的权重。
## 信任完整性(阶段 3)
两个首要控制机制保护推演过程免受不良输入的影响:
- **授权范围门控**(`nv/scope.py`)——NV 拒绝在授权列表之外的任何环境上运行。对于每个获准调查的环境,使用 `--authorize <tenant-domain>` 运行。
- **模式源验证**(`nv/validation.py`)——没有任何模式能未经以下检查就进入库中:(1) 受信任来源允许列表,(2) 内容校验和/防篡改检查,(3) 模式格式良好性,(4) 有效的 ATT&CK 风格技术 ID。每个被接纳的模式都保留审计记录;被拒绝的会附带原因记录在日志中。被投毒或格式错误的源会在上游被阻止,无法制造错误的推演结果。这正是引擎应用于证据的同样怀疑态度,现在也应用于模式本身。
---
## 保持知识更新(领先于攻击者的演进)
推演引擎的时效性取决于其模式库以及处理库中从未见过内容的能力。NV 在设计上通过**两条独立的战线**来解决过时问题:
### 1. 已知层通过经验证的更新管道保持新鲜
该库并非硬编码——`nv/patterns.py` 通过 `nv/validation.py` 加载每一个模式(包括内置集),因此外部源通过同一条受信任路径进入。按计划拉取这些源的实时网络客户端在 `nv/feeds.py` 中实现,并由 `update_feeds.py` 驱动。源按信任级别划分:
- **MITRE ATT&CK(STIX)**——权威的技术分类法。连接器读取 ATT&CK STIX 索引,拉取最新的企业版发布,并刷新 NV 推理的每个操作的权威技术名称和战术——丢弃任何其技术已被 ATT&CK 撤销或弃用的操作。NV 保留操作→技术绑定和基础概率先验的所有权;ATT&CK 拥有分类法。
- **通过 TAXII 2.1 的经审核 CTI**——一个完整的 discovery → api-root → collection → objects 客户端。从经审核的 CTI 集合中拉取 STIX attack-pattern 对象,并刷新 NV 跟踪的技术。权重低于 ATT&CK。
- **Sigma 社区规则集**——作为 git 归档拉取;每条指定 O365/Entra 操作并带有 `attack.tXXXX` 标签的云/身份规则都会成为操作→技术候选,基础概率从规则自身的严重性 `level` 推导,然后按社区源权重缩小。不匹配的规则会附带原因被跳过,绝不会猜测。
在操作冲突时,并集在提交前按信任等级升序排列,因此权威的 ATT&CK 绑定始终优先于社区绑定;较低层级的内容仍被接纳并作为佐证记录在审计中。`update_library(candidates)` 通过验证重新摄取整个集合,并原子化地重建库,因此被投毒的源永远不会使库处于半更新状态。
**两个允许列表,而不是一个。** 验证已经在源标签上把关;连接器额外增加网络层 *主机* 允许列表,因此连接器只能通过 TLS 从受信任主机获取——这是源允许列表在传输层的对应物,也是防止源 URL 被劫持或输错的防护措施。每次获取都会将原始负载 sha256、URL 和时间记录为出处,以便后续重新拉取时检测上游变更。
**为什么随着源的增长,验证层变得更加重要:** 你越是自动化更新,自动更新管道就越成为伪装下的信任风险——错误或被投毒的源会注入虚假模式并制造错误的推演结果。NV 将摄取过程视为对抗性的:对每个模式、每次更新都应用允许列表、校验和、模式检查和审计跟踪。
### 2. 溯因层覆盖尚无任何源命名的内容
源总是滞后于最新的攻击手法。溯因核心就是兜底:当观察到的操作与**任何**库模式都不匹配时,NV 不会丢弃它——而是从第一性原理重建最可能的路径,并以降低的置信度将其标记为 `no known match`。这在评估套件(`eval/ground_truth_cases.py`)中得到验证,其中一个特意设为未知的托管身份令牌窃取步骤被捕获、正确排序,并诚实地降权至信任底线以下。
这两点共同意味着 NV 永远不会完全过时:已知层通过抗投毒管道跟踪已发布的前沿,而溯因层使工具不会对前沿尚未赶上的入侵行为失明。
### 建议的更新频率
`nv/feeds.py` 为每个源携带各自的更新节奏,`update_feeds.py` 只拉取到期的内容,因此可以直接放入 cron 或 systemd 定时器:
- ATT&CK STIX — 90 天(每年有几次官方发布)。
- CTI/TAXII — 7 天(随源发布),始终经过验证。
- Sigma — 30 天。```bash
# run whatever is due, keeping state under ./.nv_feeds (cron-friendly)
python3 update_feeds.py
# force all feeds now but only report what would change
python3 update_feeds.py --force --dry-run
# run fully offline against captured fixtures (no network)
python3 update_feeds.py --offline eval/fixtures --force
在任何库变更后,重新运行 eval/run_eval.py 以确认已知攻击形态仍然
可以重构,运行 eval/validation_cases.py 确认门控仍然拒绝错误输入,并
运行 eval/feeds_offline_test.py 确认馈送路径端到端完好。
nv_gui.html 中展示的重建结果基于一个公开研究数据集
——invictus-ir Office 365 统一审核日志语料库——并非来自任何公司的实时
租户。 它存在的意义是让引擎能够在无需任何人配合的情况下,
端到端地被演示和自用测试。要真正使用 NV,组织需要接入自己的 Entra/M365
审核数据,如下文所述。任何专有或客户数据都不会包含在本项目
的任何地方。
NV 可以在你运行它的任何地方运行;你的日志永远不必离开你的环境。四个步骤:
1 — 导出你的审核日志。 NV 读取 Microsoft 365 统一审核日志。来源可以是:
Microsoft Purview(审核搜索 → 导出 CSV)、Search-UnifiedAuditLog
Exchange Online PowerShell cmdlet、Microsoft Graph 的 auditLogs / signIns
端点,或 Sentinel/SIEM 导出的 OfficeActivity 和 SigninLogs。
2 — 将其规范化 为 NV 所依赖的事件模型:```bash python3 nv_extract_identity_events.py your_audit_export.csv your_events.jsonl
这会保留登录、同意授予、服务主体和角色更改以及邮箱
访问——包括 NV 从未命名的身份操作,因此它们仍能到达
溯因层——并丢弃其余部分。它读取带有标准 `AuditData`
列的 CSV,或 JSON/JSONL,其中每条记录都是一个 `AuditData` 对象(即
invictus-ir 研究语料库所提供的形状)。
**3 — 重建,范围限定。** 引擎拒绝在你未明确授权的
租户上运行:```bash
python3 run_nv.py your_events.jsonl reconstruction.json \
--authorize yourtenant.onmicrosoft.com
4 — 查看。 打开 nv_gui.html,点击 ⤒ 加载 reconstruction.json,将其指向
引擎刚生成的文件——同一界面随后会显示您的事件、您的
实体和置信区间。嵌入画布上的每个点,点击后都会重新运行
针对该实体的重建。
该引擎与底层平台无关——只有操作词汇是特定于提供商的
(nv/providers.py)。针对 CloudTrail,AWS 路径也是同样的三个步骤:```bash
python3 nv_extract_cloudtrail_events.py cloudtrail.json aws_events.jsonl
python3 run_nv.py aws_events.jsonl reconstruction.json --authorize aws:123456789012
摄取过程保留 IAM/STS/登录事件(包括新增的 IAM 操作,使其到达溯因层)以及 S3 对象读取,并将范围门控设定在 AWS **账户** 而非租户域。相同的溯因核心、置信度模型和信任下限保持不变。
GUI 还带有 **演示数据横幅** 和应用内“连接您自己的数据”指南,因此任何打开它的人都会明白,在接入自己的数据之前,重建结果均为公开的示例数据。
## 项目布局```
run_nv.py reconstruction engine entrypoint (scope-gated)
nv_extract_identity_events.py ingest: M365/Entra unified audit log -> event model
nv_extract_cloudtrail_events.py ingest: AWS CloudTrail -> event model [iteration 3]
update_feeds.py pull + validate threat-intel feeds on a cadence [iteration 1]
calibrate.py fit confidence weights from labeled ground truth [iteration 2]
nv/ the engine package
graph.py patterns.py validation.py confidence.py reconstruct.py scope.py
providers.py per-substrate op->ATT&CK vocabulary packs (Entra + AWS) [iteration 3]
feeds.py ATT&CK STIX / TAXII 2.1 / Sigma clients + scheduler [iteration 1]
calibration.py metrics + parameter fit [iteration 2]
eval/ evals + offline fixtures (no network, no tenant)
nv_gui.html pure view layer (loads engine reconstruction.json)
calibration.proxy.json bundled proxy calibration artifact [iteration 2]
从项目根目录运行所有内容,以便 nv 包可被导入。
python3 nv_extract_identity_events.py auditrecords.csv nv_identity_events.jsonl
python3 run_nv.py nv_identity_events.jsonl reconstruction.json
--trust-floor 0.6 --authorize your-tenant.onmicrosoft.com
使模式库保持最新并调整置信度:```bash
python3 update_feeds.py # pull + validate feeds that are due
python3 calibrate.py --labeled run.jsonl --origin live --out calibration.json
python3 eval/run_eval.py # attack shapes reconstruct correctly python3 eval/validation_cases.py # poisoned patterns are rejected python3 eval/feeds_offline_test.py # feed connectors + scheduler (offline) python3 eval/providers_aws_test.py # AWS chain reconstructs through the same engine python3 calibrate.py # calibration harness on the bundled proxy corpus
---
## 状态
**在真实数据上端到端运行**(invictus-ir O365 数据集),覆盖完整计划:
| 阶段 | 项目 | 状态 |
|---|---|---|
| 1 | 规范化事件/实体模型 | 完成 |
| 1 | 摄取 + 规范化(Entra/M365 滩头阵地) | 完成 |
| 2 | 已知层(ATT&CK 模式库) | 完成 |
| 2 | 证据佐证置信度模型 | 完成 |
| 2 | 输出契约中的信任下限 | 完成 |
| 2 | 溯因核心(未知层) | 完成,经评估验证 |
| 2 | 排名后的竞争性假设 | 完成 |
| 3 | 模式来源验证层 | 完成 |
| 3 | 授权范围控制 | 完成 |
| 3 | 实时源连接器(ATT&CK STIX / TAXII / Sigma)+ 调度器 | 完成 |
| 4 | 真实引擎输出上的双栏界面 | 完成 |
| 4 | 嵌入 / 相似度画布 | 完成 |
| 4 | 画布驱动的逐实体重建(点击重新运行整条链) | 完成 |
| 4 | GUI 加载引擎 `reconstruction.json`(将其指向你的文件) | 完成 |
| 4 | 多提供商底层(AWS CloudTrail,经评估验证) | 完成 |
| 5 | 美学 / 主题设计 | 完成 |
| 5 | 置信度校准工具集 + 引擎集成 | 完成 |
### 坦率的已知差距(后续迭代)
- **实际租户校准数值。** 校准*工具集*是完整的,
界面已得到验证,但随附的 `calibration.proxy.json` 是基于文档描述的
代理数据形态拟合的。可部署的权重需要针对真实的
BadZure / MAAD-AF 运行来运行该工具集——这是采用者需要执行的操作步骤。
- **基于源驱动的词汇增长。** 连接器会刷新 NV 已经推理的
操作;让某个源*引入*一个新操作(并将其接入
初始/枢轴/采集分类)是未来的工作。
- **第二提供商的深度。** AWS 已作为底层无关性的证明(包 + 摄取 + 评估)
加入,但仅限 IAM/STS/S3。扩展 AWS 包、添加提供商特定的
源连接器,以及第三个底层(GCP、Okta)是后续步骤。
---
## 许可证
Nimbus Vestige 在 **PolyForm 非商业许可证 1.0.0** 下以**源代码可用**形式发布
(参见 [LICENSE](https://gitlab.com/dobybaxter127/nimbus-vestige/-/blob/main/LICENSE))。整个工具——重建引擎、两个提供商摄取模块、
GUI 和评估工具集——均可免费查看、运行,并可用于任何**非商业**目的:
个人项目、研究、教育、非营利组织和评估。在做决定之前,请逐行阅读。
**商业使用需要付费许可证**——用于你出售或托管的产品或服务中、用于
营利性公司的生产或内部系统,或用于付费的事件响应或客户项目。参见
[COMMERCIAL-LICENSE.md](https://gitlab.com/dobybaxter127/nimbus-vestige/-/blob/main/COMMERCIAL-LICENSE.md)。
---
### 作者
Doby Baxter 2026