nuclide-research/recongraph

GitHub: nuclide-research/recongraph

recongraph 是一款接受多种种子类型输入并输出带类型溯源图的种子多态侦察引擎,通过规则驱动的暴露分类和漂移检测来解决外部资产侦察与监控问题。

Stars: 1 | Forks: 0

recongraph

种子多态侦察引擎:任意种子输入,输出带类型的溯源图。

release license python NuClide

功能安装说明用法种子类型暴露分类适用范围

recongraph 接受六种种子类型(IP、CIDR、Domain、ASN、CertFP、BannerString),并对它们运行探针的不动点迭代。每一项发现都会成为一个带有溯源链的、可回溯至原始种子的类型化节点。被动源会首先运行。仅在被动信号使节点处于模糊状态时,才会触发主动非侵入式探针。当队列清空、达到预算上限,或某次迭代未新增任何节点时,引擎即会停止。一旦稳定,每个 Service 节点都会从规则集中获得一个暴露标签,该规则集会记录触发了哪条规则。 该编排机制与具体探针无关。crt.sh 证书透明度查询是公开树中唯一完全实现的真实探针。`probes.py` 和 `probes_real/` 中的存根标记了其余探针的注册点。 # 功能 - 六种种子类型:IP、CIDR、Domain、ASN、CertFP、BannerString - 类型化溯源图:每个节点都带有可回溯至生成它的种子的溯源链 - 不动点引擎:优先进行被动探测饱和,主动探针受剩余预算限制 - 硬预算上限:实际执行时间(wallclock)、探针开销、唯一主机数、每个 /24 的请求数、每个 ASN 的请求数 - 五种暴露分类:`public_intended`、`public_accidental`、`mgmt_exposed`、`legacy_drift`、`unknown` - 通过 `DRIFT_FROM` 边和 `diff()` 方法检测不同运行之间的漂移 - 沙箱中间人(MITM)检测:当检测到拦截环境时,会将 L7 结论降级为 OPAQUE - 云范围分类器:支持 GCP、AWS、Cloudflare 以及九个云提供商的 rDNS 模式 - /24 和 /20 邻域同质性扫描 - Python 3.8 或更高版本,仅使用标准库,无外部依赖 # 安装说明 ``` git clone https://github.com/nuclide-research/recongraph cd recongraph ``` Python 3.8 或更高版本。仅使用标准库。所有网络 I/O 都位于探针实现内部。引擎、图、预算和分类逻辑都是纯逻辑。 # 用法 ``` from recongraph import Engine, Seed, SeedType engine = Engine() graph = engine.run([Seed(SeedType.IP, "192.0.2.10")]) print(graph.to_json()) ``` 冒烟测试,无网络: ``` python smoke_test.py ``` 参考流水线,干净的网络环境: ``` python upgraded_runs.py ``` # 种子类型 | SeedType | 示例值 | |----------|---------------| | `IP` | `192.0.2.10` | | `CIDR` | `192.0.2.0/24` | | `DOMAIN` | `example.com` | | `ASN` | `AS15169` | | `CERT_FP` | DER 的 sha256 | | `BANNER` | `Server: nginx/1.18` | # 节点和边类型 Nodes(节点):`HOST`、`SERVICE`、`CERT`、`DOMAIN`、`NETBLOCK`、`ORG`、`ASN`。 Edges(边):`OBSERVED_ON`、`ISSUED_FOR`、`RESOLVES_TO`、`ANNOUNCED_BY`、`CO_HOSTED_WITH`、`SHARES_CERT_WITH`、`BELONGS_TO`、`DRIFT_FROM`。 # 暴露分类 图稳定后,每个 Service 节点都会收到一个标签。规则是有序的,匹配到第一个即生效。`legacy_drift` 会在 `mgmt_exposed` 之前触发。 | 分类 | 含义 | |-------|---------| | `public_intended` | http, https, dns, smtp, submission, imaps, pop3s | | `public_accidental` | staging / dev / test 子域名,`.git`,`.env`,`/backup`,`/phpinfo` | | `mgmt_exposed` | ssh, rdp, vnc, ipmi, mysql, postgres, mongodb, redis, elasticsearch, kubelet, etcd, docker-api, ldap | | `legacy_drift` | finger, telnet, gopher, tftp, rsh, rlogin, chargen, qi | | `unknown` | 没有匹配的规则 | # 预算默认值 | 限制项 | 默认值 | |-----|---------| | 实际执行时间(Wallclock) | 300 s | | 探针开销 | 1000 units | | 唯一主机数 | 500 | | 每个 /24 的请求数 | 30 | | 每个 ASN 的请求数 | 100 | # 图输出结构 ``` { "created_at": 1717430400.0, "nodes": [ { "type": "host", "value": "192.0.2.10", "attrs": {}, "provenance": [["seed-id"]], "first_seen": 1717430400.0, "last_seen": 1717430401.2, "exposure": null, "id": "a1b2c3d4e5f60001" } ], "edges": [ { "src": "a1b2c3d4e5f60001", "dst": "b2c3d4e5f6a70002", "type": "resolves_to", "attrs": {}, "first_seen": 1717430401.0 } ] } ``` # 漂移检测 可以对两次运行进行比较。当属性发生改变时,`emit_drift_edges` 会添加 `DRIFT_FROM` 边。`diff` 会返回新增和移除的节点与边。 # 附加模块 | 模块 | 用途 | |--------|---------| | `cloud_ranges.py` | 针对 GCP、AWS、Cloudflare 发布的范围文件进行分类的分类器。支持九个云提供商的 rDNS 模式。每周更新的磁盘缓存。 | | `l7_fingerprint.py` | 原始 HTTP 探针阶梯,带有故障关闭(fail-closed)匹配的标准错误页面签名库,HTTP/2 明文检测。 | | `neighbors.py` | /24 和 /20 同质性扫描,带有判定分类(高度同质意味着共享边缘池,高度异质意味着每个 IP 为单租户)。 | | `tenant_model.py` | `TenantModel` 分类法、`IdentificationConfidence` 级别、用于记录环境阻碍观察的内容的 `EnvironmentalConstraints`。 | | `sandbox_detect.py` | 启动检查:向不相关的参考 IP 发送相同的 payload。相同的响应结构意味着环境正在进行拦截。将基于 L7 推导出的租户结论降级为 OPAQUE。 | `upgraded_runs.py` 是将所有内容整合在一起的参考流水线。 # 添加探针 ``` from recongraph import Seed, SeedType, Finding, ProbeMode, Probe, Node, NodeType def my_probe(seed: Seed, budget) -> Finding: if seed.type != SeedType.IP: return Finding(source="my-probe", mode=ProbeMode.PASSIVE, confidence=0) return Finding( source="my-probe", mode=ProbeMode.PASSIVE, confidence=0.8, nodes=[Node(type=NodeType.HOST, value=seed.value, attrs={})], edges=[], ) registry.register(Probe( name="my_probe", accepts=(SeedType.IP,), mode=ProbeMode.PASSIVE, fn=my_probe, cost=2, )) ``` # 添加暴露规则 ``` def rule_my_thing(node, graph): if node.type != NodeType.SERVICE: return None if some_condition(node): return (ExposureClass.MGMT_EXPOSED, "my_reason") return None classify_graph(graph, rules=[rule_my_thing] + DEFAULT_RULES) ``` # 适用范围 recongraph 不是扫描器。它不扫描范围,不发送利用流量,也不输出无法解释的发现结果。唯一的真实探针 (crt.sh) 是被动且只读的。默认注册表中的所有其他探针都是等待真实实现的存根。无论如何编排都会运行。触发什么完全取决于哪些探针注册了真实实现。 # 我们的其他项目 - [aimap](https://github.com/nuclide-research/aimap) — AI/ML 基础设施指纹扫描器 - [scanner](https://github.com/nuclide-research/scanner) — 用于群体扫描的快速 banner 阶段 - [tiptoe](https://github.com/nuclide-research/tiptoe) — 针对敏感目标的静默、拥塞控制扫描器 - [nu-recon](https://github.com/nuclide-research/nu-recon) — 单主机被动侦察,输出 JSON 报告 - [BARE](https://github.com/nuclide-research/BARE) — 基于扫描发现的语义漏洞模块排名 # 许可证 MIT。NuClide 工具链的一部分。联系方式:[nuclide-research.com](https://nuclide-research.com)
标签:GitHub, Python, 实时处理, 无后门, 资产测绘, 逆向工具