关于 review-attack-path
review-attack-path 是用于 SubImage 攻击路径分析的技能,供安全分析人员检查已知路径、从资产追踪相关路径或寻找尚未建模的后续跳转。它要求以图数据证据区分已确认、推断与假设,并可按需叠加未持久化的情景模拟。
主要功能
- 01逐步解读已知攻击路径
- 02从资产查找相关路径
- 03探测未建模的后续跳转
- 04运行预览模式情景模拟
- 05按证据等级标示结论
- 06创建工单或发送通知
适用场景
- 01评估攻击路径终端资产的影响
- 02检查某资产参与的攻击路径
- 03从路径终点寻找横向移动可能
- 04模拟资产失陷后的潜在路径
MCP 相关
通过 subimageRunCypher 等 SubImage 工具读取图数据与模式,并调用情景模拟、工单和通知工具。技能面向 SubImage 的 MCP 工具工作流。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ subimagesec/ skills --skill review-attack-path安装后在 Claude Code 中输入/review-attack-path确认已加载。
详细介绍
审查攻击路径
功能说明
针对 SubImage 攻击路径引擎和底层 Neo4j 图的三种模式:
- 遍历已知路径,用通俗语言说明路径,指出最敏感的终端资产,并提出最快的修复方案。
- 从资产切入,查找该资产所在的路径,并审查其中风险最高的路径。
- 搜寻 n+1 扩展:探查路径终端节点之后的图,找出引擎尚未建模的可信后续步骤,并以内联候选转换的形式呈现。
可选的假设情景模拟可叠加到上述任一模式中。
适用场景
✅ 用户有来自 SubImage UI 或列表响应的攻击路径 ID。
✅ 用户有一个资产,想知道它是否位于任何路径上。
✅ 用户想扩展现有路径:“从这里查找横向移动”“评估 的爆炸半径”“接下来可能发生什么”。
✅ 用户想进行假设分析:“如果攻击者攻陷 X,会发生什么?”。
✅ 用户刚完成 subimage-mcp:investigate-cve 并确认了切入点。
❌ 用户想查看完整路径目录:只需列出 (:AttackPath:Signal) 并概述,不必逐步分析。
❌ 用户想了解引擎背后的静态规则集:发现项请使用 subimage-mcp:triage-new-findings,或查阅文档。
前提条件
路径、路径步骤以及 n+1 探测都会通过 subimageRunCypher 读取图;架构探索则由 subimageListModuleSchemaNodes 和 subimageGetNodesSchema 提供支持。假设情景模拟会先使用 subimageGetScenarioCapabilities,再使用 subimageCreateAttackPathScenario;这两个工具运行引擎,而不是读取图。工单和通知后续操作使用 subimageListLinearTeams、subimageCreateTicket、subimageSendNotification。
必需输入
选择一种入口模式,并收集对应的值。如有任何信息缺失,请明确询问用户。
| 入口模式 | 必需值 | 缺失时询问 |
|---|---|---|
| 遍历已知路径 | <ATTACK_PATH_ID> | “攻击路径 ID 是什么?查看 SubImage 中某条路径时,可在 URL 中找到;也可以用 Cypher 列出活动路径并选择一条(参见模式 A)。” |
| 从资产切入 | <ASSET_ID>(资源 ARN 或完全限定 ID) | “资产 ID 是什么?AWS 资产请提供资源 ARN,GCP/Azure 资产请提供完全限定 ID,也可以提供 SubImage 详情页 URL。” |
| 搜寻 n+1 扩展 | 一个起始 <ATTACK_PATH_ID> 或 一个已知为目标终端节点的 <ASSET_ID> | “n+1 搜寻应从哪里开始:从特定路径的终端节点开始,还是从一个应视为已被攻陷的资产开始?” |
对于假设情景,还需收集:
| 值 | 缺失时询问 |
|---|---|
<NODE_LABEL> | “起始节点标签是什么?(例如 AWSEC2Instance、AWSS3Bucket、User。)” |
| 要授予的能力 | “要模拟攻击者具备哪些能力?先运行 subimageGetScenarioCapabilities,查看此节点标签支持哪些有效能力。” |
判断准则(调用任何工具前请阅读)
图是事实依据。请保持审慎。
- 每项输出都要区分三个置信度层级。通过内容所在的章节隐式标记每项陈述:
- 已确认:由攻击路径引擎直接返回,或由命中具体带标签行的 Cypher 查询直接返回。
- 推断:通过有文档记录的架构关系组合两项已确认事实,并由支持该关联的 Cypher 探测提供依据。
- 假设:假设情景的结果,或没有具体行作为依据的图结构观察。务必明确说明。
- 不得臆造标签、关系、转换或安全语义。如果架构中未显示某种关系,则该路径不存在。
- 图中的相邻关系不代表可利用性。两个节点之间存在关系是必要条件,但并非充分条件。
- 宁可漏掉薄弱的想法,也不要报告错误的信息。错误的转换报告比不报告更糟。
- 如果证据薄弱或含糊,请明确说明。不要掩盖不确定性。
工作流程
模式 A:遍历已知攻击路径
-
阅读路径中按顺序排列的步骤。攻击路径是一个
:AttackPath:Signal,其步骤按位置关联到该路径:MATCH (a:AttackPath:Signal {id: '<ATTACK_PATH_ID>'})-[h:HAS_STEP]->(s:AttackPathStep) OPTIONAL MATCH (s)-[:FROM]->(src) OPTIONAL MATCH (s)-[:TO]->(dst) RETURN a.title AS title, a.criticality_score AS criticality, h.position AS position, s.transition_id AS transition, s.capability AS capability, s.description AS description, collect(DISTINCT src.id) AS from_ids, collect(DISTINCT dst.id) AS to_ids ORDER BY position使用
s.description,它是渲染后的步骤文本。s.templated_description仍包含未渲染的占位符,不适合用于展示。该查询按构造限定为单条路径的步骤,因此无需使用LIMIT。此处使用
FROM|TO是正确的连接方式,因为这些是步骤展示的端点,而且路径 ID 已知。若要查找哪些路径涉及某个资产,则不应使用这种连接方式;请参见模式 B。 -
将路径拆分为四个部分:
- 初始入侵:入口节点,以及攻击者借此入侵的方式。
- 关键跳转:1 到 3 个会实质改变攻击者处境的转换(权限提升、网络可达范围扩大、数据访问)。
- 终端节点:链条中的最后一个节点。
- 最终影响:攻击者此时掌控的对象或能够执行的操作。
-
将每次转换改写为通俗易懂的句子(“攻击者从
X转到Y,原因是<转换中的原因>”)。不要重新罗列 JSON。 -
按影响排序:生产环境 / 客户数据 / 特权身份 > 内部环境 / 开发环境 > 沙盒。
模式 B:从资产切入
-
查找涉及该资产的路径。资产通过
AttackerCapacity参与其中,因此连接方式是先通过REASON|ON连接到该 capacity,再通过GRANTS连接回步骤:MATCH (n {id: '<ASSET_ID>'})-[:REASON|ON]-(c:AttackerCapacity) <-[:GRANTS]-(:AttackPathStep)<-[:HAS_STEP]-(a:AttackPath:Signal) WHERE coalesce(a.status, 'active') IN ['active', 'accepted'] RETURN DISTINCT a.id AS id, a.title AS title, a.criticality_score AS criticality, a.context_type AS context, coalesce(a.status, 'active') AS status ORDER BY criticality DESC, id LIMIT 20不要将其改写为
(:AttackPathStep)-[:FROM|TO]->(n)。FROM和TO是派生边,用于保存步骤展示的端点:TO来自步骤自身的 capacity,FROM来自上一步的 capacity。资产可以是某个 capacity 持有它的REASON,却从未成为端点;按端点匹配时,这类资产恰好会返回“无路径”。对于渲染已知路径,端点连接方式是正确的,这正是模式 A 的做法;但它不适用于发现路径。对状态使用
coalesce并非防御性填充:路径 Signal 可能没有status属性,而这种情况仍视为活跃。返回
context_type,而不是按其筛选,这与产品自身的查找行为一致。若用户要求查看整个环境的情况,或者同一路径按每个 context 重复返回,则将范围缩小到'default'。 -
如果结果为空:“目前没有已知攻击路径涉及
<ASSET_ID>。该资产仍可能受到引擎尚未建模的路径威胁。要我从此资产开始运行 n+1 扩展搜索(模式 C)吗?”只有使用上述 capacity 连接方式,这种说明才可靠。 -
如果结果非空:选取排名最高的 1 到 3 条路径,并对每条路径运行模式 A。
模式 C:寻找 n+1 扩展
这是分析员模式新增的功能:检查路径的终端节点,并探查图,以确定是否存在引擎尚未建模的可信后续步骤。
- 选择要扩展路径的终端节点(或者,如果用户指定了
<ASSET_ID>,则直接使用它)。 - 检查架构中该节点旁边有哪些内容:
注意关系类型和目标标签。subimageListModuleSchemaNodes(module="<module-of-the-node>") subimageGetNodesSchema(node_names=["<TerminalLabel>"]) - 对每种合理的关系,运行一个小型 Cypher 探查,以确认确实存在实际行(见下文 Cypher 规则)。可信 n+1 类别示例:
- 横向移动:从已攻陷的计算实例出发,通过安全组/VPC 对等连接/共享服务账户访问可达的对等节点。
- 权限提升:从非管理员身份出发,查找可有效授予管理员权限的角色或策略边(
iam:PassRole、AssumeRole、组成员关系、具有星号权限的自定义角色)。 - 数据窃取:从任何已攻陷的计算实例出发,查找具有敏感数据标签或允许公开读取的可达存储。
- 跨账户/跨租户:信任关系、跨账户角色代入、联合身份桥接。
- 在报告任何内容前,应用下方的 5 项检查清单。
- 在输出中列出每个可信扩展(格式见下文)。递增计数器,并在最终输出中提及计数。
模式 D:假设场景(叠加)
仅当用户提出请求时(“如果 X 被攻陷会怎样”“模拟授予 Y”)。
- 使用
subimageGetScenarioCapabilities(node_label="<NODE_LABEL>")发现有效能力。 - 告诉用户有哪些可用能力,并询问要授予哪些能力。
- 使用
subimageCreateAttackPathScenario(..., preview_only=true)。始终传入preview_only=true:用户可以检查结果,而不会将其持久化为真实路径。 - 使用模式 A 遍历生成的路径。
图探查的 Cypher 规则
以下规则同样适用于上述模式 A 和模式 B 查询,以及模式 C 探查:
subimageRunCypher不接受查询参数,因此<ATTACK_PATH_ID>和<ASSET_ID>必须以内联字面量的形式传入。替换前转义反斜杠和单引号;ARN 和完全限定的 GCP/Azure ID 可能包含这些字符,未转义的撇号会导致语句出错。- 无论写入什么
LIMIT,工具最多返回 100 行,并同时报告真实的total_count。这远高于此处所需的数量,但如果探查触及该上限,请引用total_count,而不是当前页的行数。 - 攻击路径的关系清单是封闭的。步骤的关系为
<-[:HAS_STEP]-、-[:GRANTS]->、-[:FROM]->、-[:TO]->;能力的关系为<-[:GRANTS]-、-[:ON]->、-[:REASON]->,以及指向其他能力的REQUIRED。不存在(:AttackPathStep)-[:ON]->或(:AttackPathStep)-[:REASON]->;这两种关系都从能力节点引出。 - 始终为探索性查询设置上限:
LIMIT 5。范围更大的扫描会消耗令牌,却不会增加有效信息。 - 先从宽泛查询开始,再逐步细化。第一个查询确认结构存在;第二个查询获取具体行。
- 对于文本匹配,优先使用
toLower(prop) CONTAINS "term",而不是正则表达式。 - 切勿使用无界可变长度路径(
-[*]->)。请限制范围:最多使用-[*1..3]->。 - 在据此推理前,先确认标签和关系确实存在于实际行中。如果
MATCH (a:Foo)-[:BAR]->(b)返回 0 行,则该关系仅为概念关系;不要将其描述为可利用的关系。 - 如果
subimageRunCypher返回 0 行,这本身就是已确认的事实:该租户中不存在此关系。
何时呈现候选扩展
仅当以下五项全部成立时,才在输出中包含候选项:
- 此租户图中的真实行支持源标签和目标标签(而不只是架构)。
- 图中存在它们之间的关系(Cypher 探测至少找到一行)。
- 攻击者当前所处的位置在合理情况下允许执行此步骤(能力、网络可达性、身份)。
- 此步骤能带来有意义的新影响、新权限或新可达范围(而不只是“另一个相同类型的节点”)。
- 现有转换中显然尚未对该步骤建模(检查相似节点类型之间的几条现有路径)。
任意一项不成立,就不要呈现该项。请在内部说明原因,然后继续。
候选扩展格式
将每个候选项呈现为一个子块,并准确包含以下字段:
- context:
Attack path analysis: <用户请求,用一句话概述> - problem:
Potential missing transition: <SourceLabel> can reach <TargetLabel> via <relationship>, enabling <impact>. Transition type: <lateral-movement | privilege-escalation | data-exfiltration | cross-account>. Evidence: <N> matches. Cypher pattern: <one-line MATCH>. - workaround:
partial - workaround_detail:
The current path stops at <terminal node>, but graph evidence suggests the attacker may continue to <target> via <mechanism>. - suggested_improvement:
Add a transition from <SourceLabel> to <TargetLabel> under conditions: <list of validated conditions>.
输出
针对每条已检查的路径(模式 A 和 B):
# Attack path: <short title>
**Criticality**: <score / category> ; **Steps**: <N>
## In plain English
The attacker starts at [[entity:<Label>:<id>|<short>]] (<one-line context>).
1. <transition 1 in plain language>
2. <transition 2 in plain language>
3. ...
N. The chain ends at [[entity:<Label>:<id>|<short>]] which gives them <impact>.
## What this means
- **Initial compromise**: <one line>
- **Key pivot(s)**: <one line, naming the transitions that mattered>
- **Terminal impact**: <one line, naming what the attacker now controls>
- **Most sensitive impacted asset**: [[entity:<Label>:<id>|<short>]] (<why it matters>)
- **Why this path is exploitable today**: <rooted in the actual transitions, no speculation>
## Fastest remediation
<one or two concrete actions in priority order. Name the policy, the SG rule, the secret, the role.>
## What to do next
- Mitigate: <action>; owner: <team or `unknown`>
- Re-run after the change: SubImage refreshes paths on the next sync.
模式 C 之后,追加:
## n+1 extension hunt
- probes run: <count>
- credible extensions found: <count>
- candidate extensions surfaced: <count>
<for each surfaced candidate, render the five-field sub-block from "Candidate extension format" above>
如果模式 C 未发现可信内容,请明确说明:“没有可信的 n+1 扩展得到图证据支持。终端节点 <id> 当前并未与任何通过五项检查的对象相邻。”
始终使用 [[entity:<Label>:<node.id>|<display>]] 标记实体,以便聊天界面链接到实体。
可选后续操作
如果用户希望创建工单:
- 使用
subimageListLinearTeams()获取团队 ID。 - 使用
subimageCreateTicket(team_id=..., title="Mitigate: <path title>", description="<the narrative + remediation>")。
创建前确认团队。subimageSendNotification 也遵循相同规则:先确认频道。
反模式
- 将原始转换列表作为 Markdown 表格返回。聊天系统提示禁止将工具数据如此呈现,而且这也无助于让路径易于理解。
- 对修复方案含糊其辞(如“检查 IAM 策略”)。请指出具体的策略、规则和资源。
- 猜测引擎未生成的转换(“攻击者也可以……”)。如果用户提出要求,请使用 Cypher 探测运行模式 C;没有证据时,绝不要声称存在扩展。
- 只进行一次薄弱探测就报告转换设想。请执行五项检查;任意一项不成立,都不要报告。
- 一次响应中检查 5 条以上路径。用户只会处理排名最高的 1 或 2 条;更多内容只会沦为背景噪声。
- 在假设场景中忘记设置
preview_only=true。不带此标记的形式会保存场景,而用户初次查看时通常并不希望如此。 - 将架构中的关系视为已确认可利用性。先探测,再报告。
参考资料
- 工具指南(由
subimageReadMe始终加载):第 4 领域“攻击路径分析”,第 1 领域“知识图谱探索”(Cypher)。 - 常用于跳转至此处的漏洞分诊配套技能:
subimage-mcp:investigate-cve。 - 架构:https://app.subimage.io/docs/architecture/attack_path