copyleftdev/vervet
GitHub: copyleftdev/vervet
vervet 是一款 Rust 实现的单二进制对手模拟工具,通过 Ed25519 签名授权与防篡改证据链,为 LLM 编排红队演练提供安全可审计的执行层。
Stars: 0 | Forks: 0
**vervet** 是一款单二进制对手模拟工具,专为红队、
紫队、检测工程师和 AI/LLM 安全协调器设计。模型
决定下一步操作;而 vervet 提供的是狭窄、强类型、可审计且能实际运行的
底层原语。
它是 Infection Monkey 的反向设计:没有中央服务器,没有代理集群,也没有隐藏的
控制平面。CLI 即契约。协调器调用 `describe`,触发一个
授权的 `emulate
` 动词,接收 vq1 证据信封,
并可以通过 `report` 将回执整合到 ATT&CK 覆盖率中。
## 概览
| 面 | 关键点 |
|---|---|
| Runtime | Rust 2024 workspace,CLI 优先,无需服务器 |
| 协调器契约 | `describe` 暴露动词、技术和所需的输入 |
| 授权 | 在每次状态更改操作前检查 Ed25519 签名的清单 |
| 证据 | 带有内容寻址句柄的 vq1 回执 |
| 可审计性 | blake3 链接的审计条目使时间线编辑变得可见 |
| 覆盖率 | `report` 将回执整合到 MITRE ATT&CK 战术和技术中 |
| 安全姿态 | 超出范围的请求会类型安全地失败并拒绝,返回退出码 `2` |
## 设计中心
现代 AI 代理可以规划安全演练,但它们仍然需要具有
真实边界的狭窄执行层。vervet 围绕三个约束构建:
| 约束 | 实现 |
|---|---|
| LLM 应该确切知道它可以调用什么 | `vervet describe` 输出机器可读的契约 |
| 技术不应按约定运行 | `Gate::authorize` 生成技术所需的不可伪造的 `Grant` |
| 证据应经得起审查 | 回执携带类型化的摘要以及链接到前驱句柄的审计条目 |
## 循环
```
signed scope manifest
|
v
describe -> emulate -> receipt.vq1 -> report
| |
| +-- content-addressed evidence
+-- authorize -> engage -> emit
```
每条更改状态的路径都会流经 `authorize -> engage -> emit`。这
是该项目的核心特性:相同的边界控制着网络发现、
远程服务检查、有效账户断言和密码喷洒模拟。
### 1. 签署范围清单
清单是一次演练的签名授权:哪些 CIDR、哪些
技术,以及哪个时间窗口。签名密钥由授权方持有,
vervet 永远不会持有。
```
{
"engagement_id": "acme-2026-q2",
"operator": "dj@codetestcode.io",
"authorized_cidrs": ["10.10.0.0/24"],
"excluded_cidrs": ["10.10.0.1/32"],
"technique_allowlist": ["T1046", "T1110.003"],
"valid_from": 0,
"valid_until": 4102444800
}
```
```
cargo run -p vervet-scope --example sign -- claims.json > manifest.json
```
该命令将授权方的公钥打印到 stderr。该授权会通过带外
传递给网关;嵌入在清单中的密钥将是自签名的,因此
是可伪造的。
### 2. 发现契约
```
vervet describe
```
```
{
"tool": "vervet",
"protocol": { "schema": "vq1", "version": "0.1.0" },
"verbs": ["describe", "schema", "emulate", "report", "explain", "help"],
"authorization": "every engagement requires an Ed25519-signed scope manifest",
"techniques": [
{
"id": "T1046",
"name": "Network Service Discovery",
"tactic": "discovery",
"inputs": ["target", "ports (default 445,22,3389 = SMB,SSH,RDP)"]
}
]
}
```
### 3. 模拟一个技术
```
vervet emulate T1046 \
--manifest manifest.json \
--authority 4cb5abf6ad79fbf5abbccafcc269d85cd2651ed4b885b5869f241aedf0a5ba29 \
--target 10.10.0.5 \
--ports 22,80 \
--store ./runs
```
输出是一个回执:一个 vq1 证据信封加上
将授权和交战记录为链接操作的审计链。
```
{
"envelope": {
"header": { "schema": "vq1", "version": "0.1.0" },
"summary": {
"name": "Network Service Discovery",
"attack_id": "T1046",
"tactic": "discovery",
"engagement_id": "acme-2026-q2",
"observation_count": 0
},
"handles": {}
},
"audit": [
{
"seq": 0,
"engagement_id": "acme-2026-q2",
"action": "authorize T1046 target=10.10.0.5",
"prev": "ev:genesis"
},
{
"seq": 1,
"engagement_id": "acme-2026-q2",
"action": "engage T1046 observations=0",
"prev": "ev:412c0a8637502e7a"
}
]
}
```
超出清单范围的请求会失败并返回退出码 `2`:
```
denied: target is not within any authorized CIDR
denied: target falls within an excluded CIDR
denied: technique is not in the manifest allowlist
```
### 4. 报告覆盖率
```
vervet report --store ./runs --engagement acme-2026-q2
```
```
{
"schema": "vq1-coverage",
"tactics": { "discovery": ["T1046"] },
"techniques": [
{
"id": "T1046",
"name": "Network Service Discovery",
"tactic": "discovery",
"engagements": 1,
"observations": 0,
"detection": "unobserved"
}
],
"totals": { "engagements": 1, "techniques": 1, "observations": 0 },
"detection_note": "detection is unobserved — vervet does not see your blue team; feed SIEM evidence to populate"
}
```
## 动词
CLI 表面有意保持得足够小,以便代理进行推理,
同时又足够严格,以便人工操作员进行审计。
| 动词 | 用途 |
|---|---|
| `describe` | 输出机器可读的协议、动词和技术输入 |
| `schema` | 以 JSON Schema 格式打印演练回执契约 |
| `emulate ` | 授权、触发一项技术并输出带审计的回执 |
| `report ` | 将回执整合到 ATT&CK 覆盖率中,或从 `--store` 读取 |
| `explain` | 从回执中解析单个证据句柄 |
| `help` | 面向用户的 CLI 帮助;`-V` / `--version` 用于输出版本信息 |
## 技术
当前的注册表是刻意保持紧凑的。每个条目都映射到 MITRE ATT&CK,
并实现为一个经过审查的树内原语。
| ATT&CK id | 名称 | 战术 |
|---|---|---|
| `T1046` | 网络服务发现 | discovery |
| `T1021` | 远程服务 | lateral movement |
| `T1078` | 有效账户 | initial access |
| `T1110.003` | 密码喷洒 | credential access |
每项技术都是 `vervet-techniques/src/` 中的一个独立文件。添加一项
技术意味着添加该文件加上一行 `mod`;`describe`、`schema` 和
分发都会读取注册表。
## 授权模型
- **`Grant` 是不可伪造的。** 它没有公开的构造函数;只有
`vervet_scope::Gate::authorize` 才会生成它。
- **技术无法绕过范围。** 技术接收 `&Grant`,因此在
已批准清单之外的操作会被类型系统阻止。
- **注册仅在编译时进行。** 技术通过
`inventory` 注册;没有动态插件加载。
- **审计链是防篡改的。** 每个条目都提交给前一个
条目的 blake3 句柄,因此删除或修改会破坏随后的每一个链接。
## 凭据验证
凭据访问技术通过可插拔的 `Verifier` 判断尝试。
默认构建仅提供协议级别的探测。SSH 探测执行
真实的 RFC-4253 版本交换,确认服务并捕获其 banner,
但最多只到达 `ssh_confirmed`;它不断言凭据的有效性。
`--features ssh-auth` 构建添加了 `SshAuth`,这是一个凭据断言后端,
它通过 `ssh2` 执行真实的密码身份验证并返回
`valid` / `invalid`。密码材料永远不会写入证据。
## 构建
默认构建保持精简和协议级别。断言凭据的 SSH 功能是
可用的,但这是一个显式的 feature flag。
```
cargo build --release
cargo build --release -p vervet-cli --features ssh-auth
```
需要 Rust 1.88+ 和 edition 2024。默认二进制文件依赖
轻量,仅提供协议探测;`ssh-auth` 是可选的,以保持默认构建精简。
## 测试
默认测试套件是封闭的:没有 Docker,也没有外部服务。
```
cargo test --workspace
cargo test -p vervet-scope
```
受 Docker 控制的凭据测试演练了真实的 SSH 后端和完整的
`authorize -> engage -> emit` pipeline:
```
cargo test -p vervet-verify --features ssh-auth
cargo test -p vervet-e2e --features ssh-auth
cargo test -p vervet-cli --features ssh-auth
```
## Crate 布局
| crate | 用途 |
|---|---|
| `vervet-core` | 基础类型:ATT&CK id、vq1 信封、内容寻址证据 |
| `vervet-scope` | 签名清单、IPv4 CIDR 范围、不可伪造的授权、审计链 |
| `vervet-technique` | `Technique` trait 和 `inventory` 注册表 |
| `vervet-techniques` | 每个 ATT&CK 技术对应一个独立的实现文件 |
| `vervet-verify` | 可插拔后端,用于将尝试判定为 `Verdict` |
| `vervet-engage` | 每次技术触发使用的一条路径:authorize -> engage -> emit |
| `vervet-report` | 纯粹基于回执的 JSON 覆盖率汇总 |
| `vervet-store` | `//.json` 下的内容寻址运行存储 |
| `vervet-cli` | 动词表面 |
| `vervet-e2e` | 针对真实服务的 Docker 支持的端到端测试 |
## 不变量
- **每个文件一个概念。** `mod.rs` 仅进行重导出,CI 通过
`scripts/check-line-budget.sh` 强制执行 200 行的源码预算。
- **回执是自描述的。** `report` 不需要查找注册表;
摘要携带了技术名称、ATT&CK id 和战术。
- **检测结果绝不会被夸大。** vervet 报告 `unobserved`,从不
报告 `undetected`,因为它无法看到您的蓝队。
## 许可证
AGPL-3.0-or-later。参见 [LICENSE](LICENSE)。
主题: 对手模拟 · 突破与攻击模拟 · MITRE ATT&CK · 红队 · 紫队 · 检测工程 · 安全自动化 · Rust · CLI · AI · LLM-agent · 网络安全标签:AI安全, BAS, Chat Copilot, Cloudflare, MITRE ATT&CK, Rust, 可视化界面, 攻防模拟, 网络流量审计, 请求拦截, 通知系统