epaneral/yara-detection-harness

GitHub: epaneral/yara-detection-harness

一个基于 YARA 的检测即代码框架,通过配对合成语料库和 CI 门禁对规则召回率与误报率进行回归测试。

Stars: 0 | Forks: 0

# yara-detection-harness [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/3195b204c1144914.svg)](https://github.com/epaneral/yara-detection-harness/actions/workflows/ci.yml) 一个用于**生成的文本和代码**的小型、可测试的检测 pipeline:手写的 YARA 规则、带标签的合成语料库,以及一个以召回率和误报率作为构建把关标准的 回归测试套件。 这是“检测即代码”(detection-as-code)。规则存放在版本控制中,每次运行时都会针对 已知的恶意和良性样本对每条规则进行测试,并且一条规则不能仅仅因为编译通过就“过关”——它必须能抓取到它应该抓取的内容,同时对那些看起来很像但并非如此的情况保持沉默。 ## 为什么会有这个项目 大规模的内容扫描在成为威胁情报问题之前,首先是一个数据和精度问题。难点不在于编写一条能针对反向 shell 触发的规则——而在于编写一条既能触发反向 shell,又*不会*误报三行之外碰巧使用了 `>&` 重定向的备份脚本的规则。这个仓库就是围绕这个问题构建的:每一个良性样本都是某个恶意样本的刻意**近似匹配(near-miss)**,因此该测试套件衡量的是精度,而不仅仅是覆盖率。 ## 范围与威胁模型 - **在范围内:** 恶意的*文本和代码*制品——钓鱼工具包标记、凭证收集器、shell/PowerShell 下载器和 stager、数据渗出代码片段。这反映的是内容扫描(生成系统可能被要求生成的那类制品),而不是 PE/二进制恶意软件分析。 - **不在范围内:** 真实的恶意软件二进制文件。语料库完全是合成的并且存放在仓库中,因此磁盘上没有任何实际样本,并且良性/恶意的划分处于完全控制之下。 - **构造上即已去除威胁:** 所有网络指标都使用文档保留的 IP(`192.0.2.0/24`,RFC 5737)以及明显是伪造的 token。这里没有任何东西是可运行的。 ## 布局 ``` rules/ YARA rules, grouped by family (powershell / shell / phishing) corpus/ malicious/ known-positive samples benign/ known-benign near-misses (each shadows a malicious sample) tests/ manifest.yml ground-truth labels + expected matches (single source of truth) test_rules.py the harness enrichment-mcp/ server.py VirusTotal enrichment MCP server (separate component, own deps) test_server.py unit tests for its pure logic (validation, encoding, normalize) ruff.toml lint + format configuration for the Python (harness + MCP server) .github/workflows/ci.yml per-component CI (lint / harness / enrichment-mcp) on every push ``` ## 语料库设计 语料库是成对的。对于每个恶意样本,都有一个良性样本与其共享表面特征但不共享意图: | 恶意 | 良性近似匹配 | 区分因素 | |---|---|---| | IEX + `DownloadString` 执行载体 | 管理脚本:`DownloadFile` 到磁盘 | 执行原语(IEX),而非下载操作 | | `-enc` + 隐藏窗口 | base64 *配置* 解码 | 编码命令 + 窗口抑制组合 | | `bash -i >& /dev/tcp/...` | 带有 `>&` / `2>&1` 重定向的备份 | `/dev/tcp` socket 的使用 | | `bash -i >& /dev/tcp/...` | `/dev/tcp` TCP 端口检查(无交互式 shell) | 交互式 shell(`bash -i`),而非单独的 `/dev/tcp` | | `curl http:// \| bash` | rustup 风格的 `curl https://host \| sh` | 基于 http 的原始 IP 源 | | `$_POST['password']` → `mail(attacker)` | 同源登录处理程序 | 向外的数据渗出,而非捕获行为 | | 携带凭证的 Telegram API | 携带部署状态的 Telegram API | 凭证上下文 | ## 测试套件 `tests/test_rules.py` 完全由 `tests/manifest.yml` 驱动——在其中添加样本和标签,它就会被自动覆盖测试。三道关口: 1. **编译** —— 每个 `.yar` 文件都能编译;损坏的规则会导致构建失败。 2. **召回率** —— 每个恶意样本都能被其预期的规则捕获。 3. **误报** —— 良性样本不产生任何匹配,并且整个良性语料库的总误报率必须保持在 `FP_THRESHOLD`(此处设为 `0.0`)或以下。 该阈值是一个单一常量,因此随着语料库的增长且零误报标准不再现实时,该关口是明确且可调整的。 ``` pip install -r requirements.txt pytest -v ``` 除了检测关口外,CI 还会在 Python(测试套件 + MCP server)上运行 [`ruff`](https://docs.astral.sh/ruff/),作为额外的两道关口:一个**格式检查**(`ruff format --check`)和一个 **lint pass**(`ruff check`,涵盖 pyflakes、bugbear、blind-except、 pyupgrade、async 和 pytest 风格规则)。两者都固定了版本,因此结果只取决于代码,而不是碰巧运行在某个 runner 上的 `ruff` 版本。 ``` ruff format --check . # formatting gate ruff check . # lint gate ``` CI 将这些作为三个独立的任务运行 —— `lint`(全仓库 ruff)、`harness` (规则 + 语料库套件)和 `enrichment-mcp`(MCP server 的单元测试)—— 每个 任务都只配置了它所需的依赖。MCP server 保留了它自己的 依赖集,因此它的测试会独立安装和运行: ``` pip install -r enrichment-mcp/requirements-dev.txt pytest enrichment-mcp -v ``` ## 规则设计说明 编写规则时考虑了 YARA 的匹配引擎,而不仅仅是正确性: - **原子优于通配符。** 条件锚定在具体的字符串上(`/dev/tcp/`、 `api.telegram.org/bot`、IP 正则表达式之前的 `http://`),以便扫描器获得快速的 首次匹配,而不是被迫进行全面评估。没有以 `.*` 开头的 正则表达式,也没有主要由通配符组成的模式。 - **组合优于单一存在。** 几乎每条规则都要求*两个*原语同时出现 (捕获**且**渗出,编码**且**隐藏,获取**且**管道传输至 shell)。单一 特征的规则是误报的来源;近似匹配语料库的存在正是为了 捕获这种失败。 - **每条规则中声明了精度控制手段。** 每条规则的 `meta` 和行内注释都指明了 使其避开良性孪生样本的那一个特征。 ## 路线图(尚未构建 —— 阶段 2) 为了确保可交付,故意将其排除在当前范围之外: - `yaraQA`(Florian Roth)作为性能/质量**关口**接入,而不仅仅是一个运行器。 - 超出 yaraQA 的自定义基于 `plyara` 的检查。 - 双路径接入:一个抓取的静态源 + 一个结构化订阅源。 - 一个对存储的语料库运行新规则的追溯狩猎(retro-hunt)作业。 ## 本项目不包含什么 - 这不是生产级的检测内容 —— 合成语料库,没有真实的误报基准率。 - 未曾基于活体恶意软件进行训练或测试。 - 规则覆盖范围仅用于演示(少数几个家族),旨在展示测试 规范,而非穷尽所有可能。 *作者:Elyse Paneral · 2026*
标签:URL发现, YARA, 云资产可视化, 安全检测, 安全规则引擎, 持续集成(CI), 文本分类, 测试框架, 逆向工具