mar0ls/bladedr
GitHub: mar0ls/bladedr
面向 Linux 的无 Agent 威胁检测与响应平台,通过 SSH 探针和可选 eBPF 传感器实现主机安全扫描与实时威胁监测。
Stars: 0 | Forks: 0
适用于 Linux 的无 agent 威胁检测与响应,包含可选的 eBPF 层。
无 agent 模式采用 Sandfly 风格;eBPF 层封装了 Tetragon。独立实现,非 fork。
设计说明请参见 [DESIGN.md](DESIGN.md)。
## 组件
- **bladedr-probe** — 在目标上运行的静态、临时收集器。携带 CEL 引擎,针对 `/proc` 快照评估规则,并返回结果。仅限 Linux;`--snapshot-file` 可在任何平台上重放已捕获的快照(测试、开发)。
- **bladedr-server** — 清单、扫描编排、规则引擎、REST API、Web 控制台(身份验证 + RBAC)。默认使用内存存储;生产环境使用 Postgres + pg_search (BM25)(`internal/store/migrations/`)。
- **bladedr-sensor** — eBPF 层(阶段 2)。轻量级 Tetragon 封装:加载策略,将命中映射为观测数据,并将其发布到服务器。通过 SSH 部署,以 systemd unit 运行。
扫描通过 SSH 进行:加密密封的凭证存储,位于 `internal/scan/ssh.go` 的 `SSHTransport`,首次使用时锁定 host key。规则采用 YAML + CEL(`internal/rules/builtin/`),可通过 `BLADEDR_RULES_DIR` 或 API/UI 覆盖。
基线/漂移、集群罕见性以及风险模型构建于原始观测数据之上;ECS/JSON 导出可接入 SIEM。
## 快速开始
```
make build # server + probe
make demo # scan against the bundled malicious snapshot
make build-probe-linux # cross-compile the static probe for Linux
```
手动操作:
```
BLADEDR_PROBE_BIN=./bin/bladedr-probe \
BLADEDR_PROBE_EXTRA="--snapshot-file testdata/malicious-snapshot.json" \
./bin/bladedr-server
curl -X POST localhost:8080/api/v1/hosts -d '{"hostname":"web-01","primary_ip":"10.0.0.5"}'
curl -X POST localhost:8080/api/v1/hosts/
/scans
curl "localhost:8080/api/v1/observations?host="
curl "localhost:8080/api/v1/observations?q=rootkit" # BM25 text search on Postgres
```
## 存储
默认使用内存存储。对于 Postgres:
```
docker compose up -d
psql "postgres://bladedr:bladedr@localhost:5432/bladedr" -f internal/store/migrations/0001_init.sql
```
## 配置
| 变量 | 默认值 | 含义 |
|-----|---------|---------|
| `BLADEDR_ADDR` | `:8080` | 监听地址 |
| `BLADEDR_PROBE_BIN` | `bladedr-probe` | 用于 LocalTransport 的 probe 二进制文件 |
| `BLADEDR_RULES_DIR` | (内置) | 从目录加载规则,而不是使用嵌入式规则 |
| `BLADEDR_PROBE_EXTRA` | – | 额外的 probe 参数(开发/测试) |
| `BLADEDR_DATABASE_URL` | – | Postgres DSN;未设置 = 使用内存存储 |
| `BLADEDR_NODE_KEY` | (临时) | 用于凭证密封的 base64 节点密钥(`-keygen` 生成) |
| `BLADEDR_PROBE_LINUX_AMD64` | – | linux/amd64 probe 路径(SSH 扫描) |
| `BLADEDR_PROBE_LINUX_ARM64` | – | linux/arm64 probe 路径(SSH 扫描) |
| `BLADEDR_ADMIN_PASSWORD` | (自动生成) | 初始管理员密码 |
| `BLADEDR_INGEST_TOKEN` | – | sensor 用于发布事件的共享 bearer token |
| `BLADEDR_SECURE_COOKIES` | `false` | 在会话 cookie 上设置 `Secure` 标志(需要 TLS) |
## 部署
服务器可在任何地方运行;扫描目标始终为 Linux(通过 SSH)。
```
docker build -t bladedr-server .
docker run -p 8080:8080 -e BLADEDR_DATABASE_URL=... -e BLADEDR_NODE_KEY=... bladedr-server
```
针对 Linux ATT&CK / EDR-T 矩阵的检测覆盖率:[COVERAGE.md](COVERAGE.md)。
## 规则
规则是数据(YAML + CEL),而不是代码——无需重新编译即可编写检测。有效规则集合将合并三层,后者的优先级更高(用户规则可以覆盖,或者通过设置 `enabled: false` 来禁用具有相同 ID 的内置规则):
1. 内置 —— 嵌入在二进制文件中(`internal/rules/builtin/`)。
2. 文件系统 —— 设置 `BLADEDR_RULES_DIR=/path` 以使用版本化的规则包。
3. 数据库 —— 通过 API/UI POST 一条规则;经过 CEL 验证后,在下一次扫描时生效。
```
curl -X POST :8080/api/v1/rules --data-binary '
id: my-loader-watch
title: "Process named loader"
category: process
severity: medium
foreach: processes
when: '\''item.comm == "loader"'\''
evidence: { pid: item.pid, comm: item.comm }'
curl :8080/api/v1/rules # user/DB rules
curl :8080/api/v1/rules/active # merged active set
curl -X PATCH :8080/api/v1/rules/my-loader-watch -d '{"enabled":false}'
curl -X DELETE :8080/api/v1/rules/my-loader-watch
```
一条规则包含可选的 `foreach` 集合(支持如 `persistence.systemd_units` 的点分路径)、一个 CEL `when` 条件,以及 `evidence`/`dedup` 表达式。
快照字段:`processes`、`listening_sockets`、`persistence.*`(cron、systemd_units、authorized_keys、ld_preload)、`kernel_modules`、`suspicious_files`、`accounts`、`kernel_log`、`pam_modules`、`pth_files`、`immutable_files`、`hidden_modules`、`facts.*`。
## 基线与漂移
bladedr 为每台主机的稳定状态(监听端口、kernel 模块、账户、authorized key、cron、systemd unit)保留基线。首次扫描设定基线;后续扫描会与其进行比对,并为任何新增项触发 `baseline-new-*` 告警——例如新的 UID-0 账户、新的监听器或新的 key。
集群罕见性评分可作为补充:如果某个项目仅存在于整个集群的极小部分中,将会触发严重性较低的 `fleet-rare-*` 线索。这两种检测都是确定性的,无需训练数据。
```
curl :8080/api/v1/hosts//baseline
curl -X DELETE :8080/api/v1/hosts//baseline # reset; next scan re-establishes it
```
## 风险评分
多项式朴素贝叶斯模型(位于 `internal/risk`,纯 Go 实现)会根据你将其视为真实威胁的可能性,对未处理的发现进行排名。它基于分诊结果进行训练——`acknowledged` = 真实,`false_positive` = 噪音(排除 `resolved` 状态,因为其含义模糊)——并且仅使用结构化特征(规则、类别、严重性、来源、MITRE 技术/战术)以及粗略的证据分类(如 `path:tmp` 对应 `path:home`,`uid:root`),从不使用受攻击者控制的路径。因此,它学习的是技术特征,而不是字面上的 IOC。它只负责排名,不负责检测。
`/risk/stats` 会进行交叉验证(留一法),并报告已标记的数据集是否足够大、平衡且可分离,从而决定是否可信。在这两种类别都存在之前,评分将回退到规则的静态分数。纯净的集群产生的阳性结果很少,因此该模型也可以在攻击模拟靶场([poligon/](poligon/))中进行训练:`make lab` 会植入已知技术并写入 `poligon/dataset.jsonl`。设置 `BLADEDR_RISK_DATASET` 以将它们混合进来;`/risk/stats` 会报告生产环境与实验室数据的比例。
```
curl :8080/api/v1/risk/stats # is there enough labelled data to trust it?
curl :8080/api/v1/risk/observations # open findings ranked, with the driving features
```
## eBPF 层(阶段 2)
无 agent 扫描看到的是处于静态的痕迹;而 sensor 能实时看到动作(执行、注入、容器逃逸、无文件攻击、C2)。`bladedr-sensor` 封装了 [Tetragon](https://github.com/cilium/tetragon):它加载 `linux-probe-shield` TracingPolicy,消费 Tetragon 的 JSON 流,将每次命中映射为观测数据(从策略注释中获取严重性/MITRE 信息)并批量发布。这些数据将进入同一个 `observations` 表(`source=ebpf_sensor`),因此它们可以原封不动地流经分诊、风险模型、UI 和导出流程。一台主机可以被设定为 `scan_only` 或 `scan_plus_sensor`。
```
make sensor # cross-build the Linux sensor
scripts/deploy-sensor.sh user@host # run Tetragon + sensor on a host
curl ':8080/api/v1/observations?source=ebpf_sensor'
```
需要 Docker 和支持 BTF 的 kernel(Tetragon 作为特权 container 运行)。所有检测逻辑都存在于策略中;sensor 仅负责转发事件。服务器推送路径会将其安装到 `/opt/bladedr`,并将 sensor 作为 systemd unit 运行(配置 `Restart=always`,ingest token 存放在权限为 0600 的 `EnvironmentFile` 中)。
## 身份验证与角色
控制台和 API 需要身份验证。全新的安装会创建一个管理员账户(密码来源于 `BLADEDR_ADMIN_PASSWORD`,或自动生成并打印一次)。在 `/ui/login` 登录;该会话可作为 cookie(UI)或 `Authorization: Bearer `(API)使用。
角色:admin(所有权限 + 用户/凭证)、operator(读取 + 分诊/扫描/规则/sensor)、viewer(只读)。只有管理员才能创建用户和分配角色。eBPF sensor 使用 `BLADEDR_INGEST_TOKEN` 进行机器到机器的身份验证。安全事件(登录、用户/角色变更、sensor 部署、RBAC 拒绝)会记录到审计日志中——可通过 `GET /api/v1/audit` 或管理员的 Audit 页面查看。
```
curl -X POST :8080/api/v1/login -d '{"Username":"admin","Password":"…"}' # -> {token}
curl :8080/api/v1/hosts -H "Authorization: Bearer "
```
Cookie 设置为 `HttpOnly` + `SameSite=Lax`。在 TLS 环境下,需设置 `BLADEDR_SECURE_COOKIES=1`。请保密 `.bladedr.env`(已被 gitignored)——它保存了部署的密钥。
## 凭证与 SSH
凭证使用 Curve25519 密钥(NaCl sealed box)进行密封;只有节点密钥(`BLADEDR_NODE_KEY`)才能解密它们,因此数据库永远不会保存可用的明文密钥。密钥通过 API 执行的是只写操作。SSH host key 会在首次使用时被锁定。
```
./bin/bladedr-server -keygen # mint BLADEDR_NODE_KEY
curl -X POST :8080/api/v1/credentials -d '{"username":"root","auth_type":"ssh_key","secret":""}'
curl -X POST :8080/api/v1/hosts -d '{"primary_ip":"10.0.0.5","ssh_port":22,"credential_id":"","arch":"amd64"}'
curl -X POST :8080/api/v1/hosts//scans
```
标签:AMSI绕过, Docker镜像, EVTX分析, Go, PE 加载器, Ruby工具, 威胁检测, 子域名变形, 安全, 日志审计, 测试用例, 请求拦截, 超时处理