gengen008/threat-hunting

GitHub: gengen008/threat-hunting

一个零依赖的 Python 威胁狩猎工具包,通过网络流量和 DNS 日志的多维度启发式分析,帮助安全分析师发现 C2 通信等高级威胁模式。

Stars: 0 | Forks: 0

# 威胁狩猎:命令与控制 (C2) 流量模式 一个无依赖的 Python 工具包,用于在网络流量和 DNS 日志中狩猎命令与控制 (C2) 流量模式——包括规律间隔的 Beaconing、DNS 隧道 / DGA 式数据外发、罕见且持久的通信目标、低速慢速会话,以及重用单一 TLS 指纹的轮换基础设施。 它内置了一个带有标签的合成流量生成器(因此无需外部 pcap 数据即可完整运行和测试整个 pipeline)、一系列测试(用于衡量针对已知真实情况的实际检测召回率/误报率),以及一份独立的交互式 HTML 狩猎报告。 **实时演示报告:** https://gengen008.github.io/threat-hunting/ *(每次向 `main` 分支推送代码时由 CI 自动基于 `data/` 中的示例数据集重新生成)* ## 为什么是“狩猎”,而不是“检测” IDS/IPS 会基于特征码做出非黑即白的拦截/放行决策。威胁狩猎则不同:它是**假设驱动、有人参与的排查**。这个工具包不会断言“主机 X 已被感染”——它会呈现*值得分析师审查的异常*,并根据有多少个独立的弱信号指向同一台主机来对其进行排名。这种理念影响了这里的每一个设计决策:检测器是基于启发式且可解释的(每个评分都附带了产生该评分的证据),并且输出的是供人类查看的排名报告,而不是自动化的修复触发器。 ## 检测内容 | 技术 | 狩猎假设 | MITRE ATT&CK | |---|---|---| | **Beaconing** | `(src, dst)` 对以可疑的*规律*间隔(到达时间间隔的变异系数较低)进行通信——这是脚本化 `sleep(N) + jitter` C2 植入物的特征,有别于突发性的人类驱动流量。 | [T1071](https://attack.mitre.org/techniques/T1071/) 应用层协议,[T1573](https://attack.mitre.org/techniques/T1573/) 加密通道 | | **DNS 隧道 / DGA** | 一台主机以较高的频率发出大量具有高熵、极少重复的子域名 DNS 查询——这符合将数据编码到 DNS 标签中的行为,而不是正常的、有利于缓存的查找。 | [T1071.004](https://attack.mitre.org/techniques/T1071/004/) 应用层协议:DNS,[T1568.002](https://attack.mitre.org/techniques/T1568/002/) 动态解析:DGA | | **罕见 + 持久的目标** | 网络上几乎没有其他主机与之通信的目标,却被某一台主机*反复*联系——一次性的罕见流量属于正常的长尾浏览噪音,而反复出现的罕见流量看起来就像是私有通道。 | [T1071](https://attack.mitre.org/techniques/T1071/),[T1090](https://attack.mitre.org/techniques/T1090/) 代理 | | **低速慢速会话** | 一个保持打开状态长达数小时,但每秒只渗出少量数据的连接——这不是正常的下载/流媒体行为,而是符合空闲的 C2 保活机制或缓慢的数据外发。 | [T1029](https://attack.mitre.org/techniques/T1029/) 定时传输,[T1071](https://attack.mitre.org/techniques/T1071/) | | **TLS 指纹重用** | 一个单一的罕见 JA3 客户端 TLS 指纹被同一台主机用于*许多不同的目标*——恶意软件通常自带一套 TLS 协议栈,因此即使运营者轮换前端域名/IP(fast-flux、重定向器轮换),其指纹也会保持不变。 | [T1568](https://attack.mitre.org/techniques/T1568/) 动态解析,[T1573.002](https://attack.mitre.org/techniques/T1573/002/) 加密通道:非对称加密 | 所有五个检测器的发现结果会按主机汇总为 0-100 的综合**风险评分**,该评分会对技术*多样性*给予奖励——一台触发了三个不相关检测器的主机,其信号强度远高于一台仅在阈值附近触发一次检测的主机(参见 `threat_hunting/scoring.py`)。 ## 架构 ``` flowchart LR subgraph Input A[Zeek conn.log / DNS log CSV] G[Synthetic generator\nwith ground truth] end A --> IO[io_utils.py] G --> IO IO --> D1[beaconing.py] IO --> D2[dns_tunneling.py] IO --> D3[rare_destination.py] IO --> D4[long_session.py] IO --> D5[fingerprint_reuse.py] D1 & D2 & D3 & D4 & D5 --> S[scoring.py\ncomposite risk score] S --> R[report.py\nHTML hunt report] S --> I[ioc.py\nIOC CSV export] ``` 每个检测器都是一个纯函数 `list[ConnRecord|DnsRecord] -> list[Finding]`,没有共享状态,因此可以独立地进行测试、调优或替换——参见 `threat_hunting/detectors/`。 ## 项目结构 ``` threat_hunting/ models.py ConnRecord, DnsRecord, Finding, HostRiskProfile stats.py entropy, coefficient of variation, percentile helpers generator.py labeled synthetic C2 traffic generator io_utils.py CSV loaders/writers (real Zeek/SIEM export or synthetic) detectors/ beaconing.py dns_tunneling.py rare_destination.py long_session.py fingerprint_reuse.py scoring.py per-host composite risk scoring ioc.py de-duplicated IOC roll-up + CSV export report.py self-contained interactive HTML report cli.py `generate` / `hunt` / `demo` commands data/ committed sample dataset (25 hosts, 12h, 4 malicious) tests/ pytest suite, incl. recall/false-positive validation .github/workflows/ CI: run tests, build report, deploy to GitHub Pages ``` ## 快速开始 需要 Python 3.10+。运行时具有**零外部依赖**——只需要 `pytest`,且仅用于运行测试套件。 ``` python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt # pytest, for tests only # 一步完成生成 + hunt + report,并与 ground truth 进行核对: python -m threat_hunting.cli demo --report report.html --iocs iocs.csv # 或者分步进行,针对已提交的 sample dataset: python -m threat_hunting.cli hunt --conn data/conn.csv --dns data/dns.csv \ --report report.html --iocs iocs.csv # 或者将其指向你自己的 Zeek conn.log / dns.log CSV export: python -m threat_hunting.cli hunt --conn my_conn.csv --dns my_dns.csv --report report.html ``` 在浏览器中打开 `report.html`——它是完全独立的(Chart.js 从 CDN 加载;其他所有内容都是内联的)。 ### CLI 参考 ``` threat_hunting.cli generate --hosts 40 --hours 48 --malicious 4 --seed 1337 --outdir data/ threat_hunting.cli hunt --conn CONN.csv [--dns DNS.csv] [--report report.html] [--iocs iocs.csv] threat_hunting.cli demo --hosts 40 --hours 48 --malicious 4 --seed 1337 --report report.html ``` `demo` 还会额外打印哪些真实的恶意主机被捕获或遗漏,下面的准确率数据就是这样产生的。 ### 自带数据格式 `--conn` CSV 列:`ts,src_ip,dst_ip,dst_port,proto,duration,orig_bytes,resp_bytes,ja3`(`ja3` 可选)。`--dns` CSV 列:`ts,src_ip,query,qtype`(`qtype` 可选)。这些与 Zeek 的 `conn.log`/`dns.log` 字段集相匹配,因此从 Zeek 导出到 CSV 通常是直接映射。 ## 测试 ``` pytest -v ``` 30 个测试涵盖了:统计辅助工具、针对手动构建的正例/负例案例的每个检测器(包括每个阈值旨在拒绝的擦边案例——例如,时间长但吞吐量高的会话、流行但持久的目标、常见的浏览器 TLS 指纹)、综合评分行为、生成器的确定性,以及针对合成数据集运行完整 pipeline 并断言**实际召回率和已知真实情况的误报率**的端到端检查——而不仅仅是“它在运行中没有崩溃”: ``` test_default_dataset_full_recall_zero_false_positives 4/4 malicious hosts caught, 0/36 benign hosts flagged test_recall_is_robust_across_seeds recall >= 75%, FP rate <= 15% across 4 additional seeds ``` ## 部署 CI (`.github/workflows/ci-deploy.yml`) 在每次推送时运行测试套件,然后——只有在测试通过后——对提交的示例数据集运行 `hunt`,以重建 `docs/index.html` 并通过 `actions/deploy-pages` 将其部署到 GitHub Pages。没有任何生成的内容被提交到仓库;实时报告是上一次成功测试运行的构建产物。 ## 局限性与诚实的注意事项 这是一个狩猎/排查辅助工具,而不是生产级的检测技术栈: - **仅限合成数据。** 未捆绑真实的恶意软件 pcap(出于许可/安全原因);生成器的良性流量模型是简化的,因此实际环境中的误报率会有所不同。在信任评分之前,请根据您自己网络的基线验证阈值。 - **已注册域名提取功能很原始**(最后两个 DNS 标签),这对于像 `co.uk` 这样的多部分公共后缀是错误的。在生产使用时请替换为 `tldextract`/`publicsuffix2`。 - **阈值是启发式常量**,不是从数据中学习的(参见 `detectors/` 中每个文件顶部的模块级常量)——在部署之前,请针对您自身环境的正常流量对它们进行调优。 - **JA3 需要 TLS 可见性**(解密代理或 TLS 指纹传感器);仅从流元数据中无法推导出来。 ## 许可证 MIT — 参见 [LICENSE](LICENSE)。
标签:IP 地址批量处理, Python, 安全规则引擎, 异常检测, 无后门, 网络流量分析, 逆向工具