ARES攻击图引擎深度剖析:如何用BloodHound数据计算到域管最短路径

原创2026-11-05 23:56:591,233 阅读

ARES攻击图引擎深度剖析:如何用BloodHound数据计算到域管最短路径

ARES 是一款面向授权红队行动(authorized red-team engagement)的自动化平台,其攻击图(Attack Graph)引擎能够将 BloodHound / SharpHound 采集的域环境 JSON 数据导入有向图,并用 Dijkstra 算法从当前立足点计算到 Domain Admin(域管理员)的最短攻击路径,帮助攻击者(或防守方)一眼看清"最快拿下域控的路线"。

这篇文章面向新手,用尽量少的代码,讲清楚三件事:

  • 攻击图的节点和边分别代表什么;
  • 边权重如何量化"这条路好不好走";
  • 从 BloodHound 数据导入,到在 CLI 和 Dashboard 上查看最短路径的完整流程。

一、攻击图是什么:把域环境变成一张"地图"

传统上,渗透测试人员拿到 BloodHound 数据后,要在网页版图里手动翻找关系:谁有 SPN、谁对哪个组有 WriteDACL、哪条 ACL 链能通向 DCSync……节点一多,人眼很容易漏掉短路径。

ARES 的做法是把攻击关系建模成一张有向图(底层使用 NetworkX 的 DiGraph):

概念 含义 示例
节点(Node) 主机、用户、组、凭据、哈希、域名、发现项 user:CORP\svc_sql、group:DOMAIN ADMINS
边(Edge) 一次可执行的攻击关系 kerberoastable、member_of、dcsync_path
边权重(Weight) 数值越小 = 这条路越好走 ACL 滥用 0.3、DCSync 0.2
高价值目标 找到通往它的路径就是胜利 Domain Admins、krbtgt、NTDS.dit

引擎的核心定义在 ares/graph/attack_graph.py 的 AttackGraph 类中,其中 HIGH_VALUE_LABELS 列出了域环境中最值得攻击的目标:Domain Admins、Enterprise Admins、Schema Admins、Administrators、krbtgt 和 NTDS.dit。

一个典型的图构建过程(官方文档 docs/ENGINE_FLOW.md 中有完整示例):

CORP.LOCAL (domain)
  └─[has_user]──► svc_sql (user)
       └─[has_spn]──► MSSQLSvc/db01 (service)
            └─[kerberoastable]──► krb5tgs hash

每个节点还带有 risk_score(风险分):域控是 4.0、管理员用户是 5.0、可 Kerberoast 的哈希是 3.5,前端渲染时会据此决定颜色和大小的视觉层级。

二、导入 BloodHound 数据:从 JSON 到图

导入入口是 ingest_bloodhound() 方法(ares/graph/attack_graph.py#L734-L781),它接受单个 JSON 文件或包含多个 JSON 的目录,同时兼容 BloodHound CE(v5+)和旧版(v4)两种格式:

  • 自动识别 computers、users、groups、domains、sessions 等数据块;
  • 每个对象上的 ACE(访问控制项)会被逐条解析;
  • 只有命中危险权限白名单的 ACE 才会被画进图里,包括:GenericAll、GenericWrite、WriteOwner、WriteDacl、AllExtendedRights、ForceChangePassword、AddMember、ReadLAPSPassword、ReadGMSAPassword、DCSync、Owns、AddAllowedToAct 等(见 ares/graph/attack_graph.py#L885-L908)。

同时,具备 Kerberoast 条件的用户(has_spn=true)会自动连出一条 kerberoastable 边;关闭了预认证的账号(dontreqpreauth=true)则连出 asreproastable 边——这意味着导入完成后,图里已经隐含了大量现成的攻击机会。

导入结果是一个统计 dict:nodes_added(新增节点数)、edges_added(新增边数)、file_count(处理文件数),方便快速判断数据是否导入成功。

ARES Dashboard 攻击图页面:PERIMETER INGRESS 到目标主机的攻击路径被锁定高亮,右侧显示妥协状态与发现

上图是 ARES Dashboard 的 Graph 页面:路径高亮(PATHWAY LOCKED)直接展示从入口网关到目标主机的攻击路径,右侧面板同步展示妥协状态与漏洞发现。

三、边权重设计:怎么量化"这条路好不好走"

攻击图最有意思的部分,是给每条攻击边打一个 0~1 的难度权重,数值越小代表越容易利用。这样"最短路径"就不再是最少跳数,而是综合难度最低的路径。

引擎内置的权重表(_RIGHT_WEIGHTS,ares/graph/attack_graph.py#L893-L898):

攻击边 权重 直观理解
member_of(组成员关系) 0.1 天然存在的联系,几乎零成本
dcsync_path(DCSync 通道) 0.2 拿到即全域哈希,但前置条件苛刻
asreproastable 0.2 无需任何凭据即可请求
ACL 滥用(ACE) 0.3 一步提权,成功率较高
ReadLAPSPassword 0.5 读取本地管理员密码
AddMember 0.6 把自己加进目标组
ForceChangePassword 0.7 强制重置密码接管账户
WriteDacl / WriteOwner 0.8 可篡改任意对象的 ACL
GenericAll 0.9 万能写权限,路径最"粗"

理解规则很简单:权重越小的边,越应该优先出现在推荐路径里。比如一条 用户 →(0.1)→ 组 →(0.2)→ NTDS 的链,总难度只有 0.3,远好过一条需要 GenericAll(0.9) + ForceChangePassword(0.7) 的链。

四、计算到域管的最短路径:Dijkstra 实战

图构建完成后,路径计算由三个方法配合完成(docs/ENGINE_FLOW.md 有方法速查表):

  1. shortest_path_to_da():自动定位图中 DOMAIN ADMINS 节点,从所有普通用户节点出发(最多尝试 50 个,避免大图卡死),用 nx.shortest_path(weight="weight") 跑 Dijkstra,返回全局最短的那条路;
  2. find_path(source, target):按人类可读的标签(如 jsmith、Domain Admins)模糊查找两个节点并计算路径,比手填节点 ID 友好得多;
  3. path_to_report(path):把路径转换成人类可读的分步报告,每步标注用了哪个攻击模块(如 ad.kerberoast、ad.dcsync),并给出路径总难度分 total_score(分数越低越容易打)。

另外 top_paths(n) 会一次性列出通往所有高价值目标中最简单的 N 条路径,按难度升序排列——这是"给我 5 条最值得打的路"的标准答案。

CLI 两分钟上手

命令行子命令 graph 注册在 ares/cli/typer_main.py,两条命令即可看到全部结果:

# 查看某 campaign 中难度最低的 5 条攻击路径
ares graph show <campaign-id> --top 5

# 查询两个指定节点之间的最短路径
ares graph path <campaign-id> --from svc_sql --to "Domain Admins"

输出会给出路径长度、总难度分和每步使用的攻击模块,例如:

Path 1  svc_sql → NTDS:CORP  score=0.3
  svc_sql  ──[member of]──► CORP  via ad.enum_acl
  CORP  ──[dcsync → all hashes]──► NTDS:CORP  via ad.dcsync

Dashboard 与 API 端点

图形化端点定义在 ares/api/server.py:

端点 作用
POST /graph/{campaign_id}/bloodhound 导入 BloodHound JSON,导入后自动计算 shortest_to_da 并随响应返回
GET /graph/{campaign_id}/attack-paths 查询最短路径 / Top N 路径(支持 source、target、top_n 参数)
GET /graph/{campaign_id} 返回 Dashboard 可视化所需的节点、边与配色图例

其中 campaign 视图的节点/边组装逻辑在 ares/api/graph.py 的 build_campaign_graph(),前端渲染页位于 frontend/src/features/graph/GraphPage.tsx。Dashboard 中各模块产生的数据会自动汇入这张图,模块目录如下图所示:

ARES 模块目录界面:70+ 内置模块按 AD、云、横向移动等分类列出,这些模块的产出即攻击图的数据源

ARES Dashboard 的模块目录:76 个内置模块的运行产出(主机、用户、ACL、凭据)正是攻击图的数据来源。

五、导出与数据安全的两个细节

多格式导出:to_d3_json() 直接对接 Dashboard 的 D3.js 力导向图;to_graphml() 兼容 Gephi / yEd;to_dot() 兼容 Graphviz(无 pydot 时自动退化为手写 DOT 生成),见 ares/graph/attack_graph.py#L707-L730。

敏感信息剥离:图在持久化或返回前端前,会经过 _safe_graph_value() 清洗(ares/graph/attack_graph.py#L50-L62),凡是键名命中 password、hash_value、nt_hash、cracked_value、token 等敏感字段的值都会被整段丢弃。这保证了"图上能看到路径,但看不到密码"——对需要把图截图放进报告的团队来说,是很实用的安全护栏。

六、总结:一条数据的完整旅程

把全文串起来,BloodHound 数据在 ARES 里的旅程是:

  1. ingest_bloodhound() 解析 JSON,只保留危险 ACE 与可利用特征,生成节点和带权边;
  2. shortest_path_to_da() 用 Dijkstra 在"难度"度量下找到通往 Domain Admins 的最优链;
  3. path_to_report() 把路径翻译成带攻击模块标注的分步报告;
  4. 通过 ares graph CLI、REST API 或 Dashboard Graph 页面查看,并可导出为 GraphML / DOT 交给 Gephi 继续分析。

对于刚接触攻击面分析的同学,建议先跑 ares graph show 看看真实环境里的路径输出,再对照边权重表理解"为什么这条路径被排在第一位"——这就是 ARES 攻击图引擎的精髓:把"哪条路最快"从经验判断变成了可计算、可排序、可导出的工程问题。

登录后查看全文
ARES