技术深潜 · 防御性架构 · 工程黑色幽默

Exploit Chaining in Project Glasswing

把孤立的软件缺陷归一化为可组合的安全原语,通过攻击图、约束求解和隔离验证判断它们能否形成连续状态转换 —— 再使用最小化、最小割和补丁回归测试切断路径。本文是一份防御性参考架构,不代表 Glasswing 的真实内部实现。

截至 2026-06-15 方法 基于公开资料构造的防御性参考架构
公开资料确认 Project Glasswing 是一个受控的防御性合作计划。Anthropic 称模型曾把多个 Linux 内核漏洞连接起来;Cloudflare 把 exploit-chain construction 和 proof generation 列为 Mythos 相比普通代码模型最明显的能力跃迁。具体编排器、评分公式和实施细节未公开披露,以下管线为防御性参考架构。

漏洞链不是"发现三个漏洞,然后把标题连起来"

普通扫描器的逻辑通常是:发现漏洞 A → 发现漏洞 B → 发现漏洞 C

漏洞链分析的逻辑则是:

漏洞 A 的结果 → 是否满足漏洞 B 的前置条件?
漏洞 B 的结果 → 是否消除了漏洞 C 的防护假设?
漏洞 C 的结果 → 是否最终产生了新的安全能力?

真正的漏洞利用链不是漏洞列表,而是一系列状态转换

S₀ →e₁→ S₁ →e₂→ S₂ →e₃→ S₃

其中 Si 是攻击者在某一时刻拥有的权限、知识和可达性;ei 是某个漏洞或利用原语;每条边都有前置条件、后置条件、环境约束和验证证据。

例如一个完全抽象化的链:

S₀ (初始状态): 只能向公开解析器发送低权限输入
漏洞 A: 产生有限的信息泄露
S₁ (新状态): 知道一个进程内部对象的位置或标识
漏洞 B: 利用泄露信息把受限操作扩大成任意读取
S₂ (新状态): 能够读取敏感状态或能力令牌
漏洞 C: 利用错误的授权假设把读取能力转换成高权限操作
S₃ (最终状态): 突破原始权限边界

关键不是"漏洞很多",而是:

Postcondition(eᵢ) ⊨ Precondition(eᵢ₊₁)

也就是:前一个漏洞产生的结果,确实满足后一个漏洞的条件。

三个漏洞待在同一个代码库里,不叫漏洞链。
那叫开放式办公环境

漏洞利用链可以被建模为带约束的攻击图

定义有向多重图 G = (V, E):

其中每个节点 v∈V 表示一个安全状态:

{ "principal": "untrusted_client", "privilege": "low", "reachableComponents": ["public_parser"], "knownSecrets": [], "capabilities": ["send_structured_input"], "isolationBoundary": "sandbox", "integrityLevel": "untrusted" }

每条边 e∈E 表示一个候选原语:

{ "id": "primitive-17", "class": "bounded_information_disclosure", "preconditions": ["public_parser_reachable","crafted_input_accepted","target_build_matches"], "postconditions": ["partial_memory_disclosure"], "environmentConstraints": ["feature_x_enabled","allocator_behavior_compatible"], "evidenceLevel": "reproduced_in_sandbox", "confidence": 0.91 }

Glasswing 需要寻找的不是单条边,而是满足目标谓词的路径:

π = (e₁, e₂, …, en)  使得  Apply(S₀, π) ⊨ Goal

例如:Goal = 跨越权限边界 / 读取受保护数据 / 逃离隔离域 / 获得管理员级操作能力

搜索问题可以写成:

π* = argmaxπ [ Impact(π) + Confidence(π) − Cost(π) − Noise(π) − AssumptionDebt(π) ]

这里的假设债务(AssumptionDebt)很重要。模型很容易生成一种听起来精彩、实际上靠十五个"假如"维持生命的链:

假如目标使用特定构建; 假如保护机制关闭; 假如地址布局碰巧合适; 假如竞争窗口成功; 假如服务正好启用了废弃插件; 假如管理员午餐时忘了锁屏……
这种链不是利用链,是安全研究版占星术

链中的核心单位不是"漏洞",而是 exploitation primitive

一个漏洞只有在被转换为某种可组合能力时,才容易参与链式推理。常见原语包括:

1. 可达性原语

把原本不可访问的组件变得可访问:外部输入 → 内部服务 → 特权解析路径。例如:路由或代理边界绕过、内部接口暴露、跨租户对象引用、错误的信任域转换。

2. 信息原语

增加模型对系统状态的知识:未知地址→已知地址范围、未知对象标识→有效对象标识、未知权限结构→可推断的授权状态。包括有界信息泄露、错误消息侧信道、元数据泄露、越界读取、身份或能力令牌暴露。

3. 内存原语

把具体内存错误归一化成更通用的能力:崩溃 → 可控越界读 → 可控越界写 → 任意地址读写 → 控制流影响。Cloudflare 对 Mythos 的公开描述就强调了这种"原语升级":模型可能把 use-after-free 等底层错误逐步转换为读写能力、控制流影响,再组合成完整证明。

4. 身份和授权原语

未认证 → 低权限身份 → 混淆身份 → 越权对象访问 → 高权限操作。这里经常出现的不是密码学被破解,而是两个子系统对"谁已经验证过什么"理解不同。

5. 隔离突破原语

受限解释器 → 宿主接口 → 邻接命名空间 → 更高权限执行上下文。

6. 稳定性原语

某个漏洞单独存在,但不稳定;另一个漏洞负责提高可靠性:竞争条件成功率很低 + 调度或状态观测原语 = 可重复触发。因此,漏洞 B 不一定提高最终权限。它可能只是让漏洞 A 从"实验室偶尔抽风"变成"稳定复现"。

漏洞 A 负责破坏安全边界。
漏洞 B 负责让它准时上班

为什么漏洞链的严重性不能简单相加

不能写成:CVSS(A) + CVSS(B) + CVSS(C) = 超级 CVSS

CVSS 主要描述单个漏洞的严重性,不是一个通用的组合代数。链式影响来自假设坍塌

假设组件 B 的安全论证是:攻击者不知道内部对象地址,所以这个危险操作不可实际控制。漏洞 A 泄露了地址后,B 的这个安全假设消失。

Risk(A→B) ≠ Risk(A) + Risk(B)
Risk(A→B) = Impact(B | Post(A)) × P(A ∧ B)

某些单独看只是中低等级的问题,在组合后会发生类别变化

组合前组合后
有限泄露 + 相对写入→ 任意写入
低权限对象访问 + 身份混淆→ 跨租户控制
受限执行 + 宿主接口错误→ 隔离逃逸

这就是为什么 Mythos 级系统的变化不只是"比扫描器多找一些漏洞"。它可能识别那些传统积压队列里看似不起眼、但可以互相提供前置条件的缺陷。Cloudflare 特别指出,普通模型往往能找到若干底层问题,却在"把各部分缝合起来"时停止;Mythos 的跃迁在于能够继续完成组合和验证。

Glasswing 的链式分析管线应当怎样工作

一个合理的防御性架构可以分成九层:

代码、二进制、配置、测试、构建信息 ↓ 1. 攻击面建模 ↓ 2. 候选漏洞发现 ↓ 3. 原语归一化 ↓ 4. 前后条件推导 ↓ 5. 攻击图搜索 ↓ 6. 隔离环境验证 ↓ 7. 链最小化与反证 ↓ 8. 修复点与披露规划 ↓ 9. 可选幽默旁注

第一层:攻击面建模

模型先回答:哪些输入是外部可控的?哪些进程、服务和权限域相连?哪些组件解析不可信数据?哪些边界依赖认证、签名、沙箱或内存安全?哪些功能只存在于特定构建配置?

结果不是一句"这个项目可能有漏洞",而是一张系统状态图:

{ "trustZones": ["internet","frontend","worker","sandbox","host"], "boundaries": [ { "from":"internet","to":"frontend","guard":"protocol_parser" }, { "from":"frontend","to":"worker","guard":"authenticated_rpc" }, { "from":"worker","to":"host","guard":"sandbox_policy" } ] }
威胁模型发现系统有五层防御。
架构图发现其中三层叫"内部使用"

第二层:候选漏洞发现

可同时运行:静态分析、污点传播、控制流和数据流分析、差分分析、模糊测试、二进制反编译、动态插桩、测试生成、模型驱动的代码审计。这一阶段应追求高召回率,因此允许噪声。但必须明确状态:

HYPOTHESIS → 代码层假设 TRIGGERED → 观察到异常 REPRODUCIBLE → 可重复触发 PRIMITIVE_PROVEN → 已证明形成某种能力 CHAINABLE → 可作为其他漏洞前置条件 IMPACT_PROVEN → 最终边界影响已证明

"程序崩溃"不等于"任意代码执行"。"越界读取候选"不等于"敏感信息泄露"。"存在两个漏洞"更不等于"二人已经宣布成立攻击组合"。

第三层:原语归一化

模型把各种具体 bug 转换成统一的安全能力语言:

{ "rawFinding": "index validation occurs after object lookup", "normalizedPrimitive": { "inputControl": "attacker_controls_index", "readCapability": { "scope":"adjacent_object_metadata","repeatable":true }, "writeCapability": null, "privilegeChange": null } }

归一化的价值在于:链搜索不必理解每个项目的全部语法细节,只需判断能力之间能否衔接。

第四层:前置条件和后置条件推导

每个候选原语需要明确:ei = (Pi, Qi, Ci, Ei)

其中:P 前置条件,Q 后置条件,C 环境约束,E 证据。

{ "preconditions": { "attackerCanReachParser":true, "requiresAuthentication":false, "requiresKnownObjectId":true }, "postconditions": { "disclosesObjectMetadata":true, "crossesPrivilegeBoundary":false } }

如果另一漏洞要求 { "preconditions": { "knownObjectId": true } },那么模型可以建立候选连接:

QA ∩ PB ≠ ∅
更严格:QA ∧ Environment ⊨ PB

Chainability Matrix:哪些原语能接在一起

可以构建链兼容矩阵 Mij = Compat(Qi, Pj),其中 Mij ∈ [0, 1]:

前序原语后序原语兼容度原因
对象 ID 泄露IDOR 越权访问0.94直接满足标识前置条件
有限地址泄露相对内存写0.81可能消除地址未知性
崩溃认证绕过0.03没有明显状态传递
日志注入沙箱逃逸0.01仅语义相关,不构成技术前置条件

模型尤其要避免词汇链幻觉:漏洞 A 涉及 token,漏洞 B 也涉及 token,因此它们可以链起来。

这和说"两个工程师都喝咖啡,所以他们共享 root 权限"逻辑强度大致相当。

链搜索:从 BFS 到约束规划

A* 搜索

f(n) = g(n) + h(n),其中 g(n) 是到达当前状态的验证成本;h(n) 是距离安全目标的启发式估计。例如,已经获得"任意读取"的状态,距离"凭据提取"通常比一个单纯拒绝服务状态更近。

束搜索

每轮只保留得分最高的 k 条部分链,防止组合爆炸。

SAT / SMT 约束求解

对于复杂环境条件,编码成 boolean 约束,由求解器判断链是否存在满足条件的系统配置。

蒙特卡洛树搜索

当验证反馈会改变后续策略时:选择最有希望的原语 → 在沙箱验证 → 根据成功或失败更新链概率 → 探索新的分支。这使漏洞研究从一次性文本生成变成闭环实验

真正关键的是验证循环,不是模型写得多自信

公开描述中,Mythos 的另一项显著能力是 proof generation:它能够构造触发程序,在隔离环境中编译运行,观察失败,再修改假设。Cloudflare 强调,这个闭环缩小了"可疑代码"与"可行动发现"之间的距离。

防御性验证循环可以写成:

提出假设 → 生成最小触发测试 → 隔离构建中运行 → 收集崩溃、日志、覆盖率和状态变化 → 判断预期后置条件是否真的出现 → 成功:提升证据等级 / 失败:修正或否定假设
def validate_primitive(candidate, sandbox): hypothesis = candidate.initial_hypothesis for _ in range(candidate.max_validation_rounds): test = generate_bounded_test(hypothesis) result = sandbox.execute(test) evidence = analyze_result(result, hypothesis) if evidence.proves_postcondition: return { "status":"proven", "primitive":normalize(evidence), "artifacts":evidence.safe_artifacts } if evidence.disproves_hypothesis: return { "status":"rejected", "reason":evidence.reason } hypothesis = revise_hypothesis(hypothesis, evidence) return { "status":"unresolved", "reason":"validation_budget_exhausted" }
最重要的限制:
• 只能在授权目标和隔离环境中运行
• 禁止自动作用于互联网目标
• 输出中应去除可直接滥用的敏感细节
• 高影响链必须经过人工确认
• 发现、验证、披露、修补应使用不同权限角色
模型说它有 99% 信心。
沙箱说它有一个退出码。
在安全研究里,沙箱赢

链概率不能简单相乘,也不能直接相信模型信心

粗略情况下:P(π) = ∏ᵢ P(eᵢ | e₁,…,eᵢ₋₁)

但各漏洞通常不是独立事件。例如:同一个构建选项同时影响多个漏洞;同一内存布局既帮助漏洞 A,也帮助漏洞 B;漏洞 A 的触发会改变系统状态,使漏洞 B 不再可用;防护机制可能只在特定进程或权限域启用。

因此应使用条件概率:P(π) = P(e₁) · P(e₂|e₁) · P(e₃|e₁,e₂)

更实际的评分可以是:

Score(π) = w₁I + w₂E + w₃R + w₄S − w₅A − w₆C − w₇N
I: 最终影响 E: 证据强度 R: 可重复性 S: 受影响部署规模
A: 假设债务 C: 验证成本 N: 误报和噪声风险

模型自己的自然语言信心不能直接作为 E

"很可能存在" → 只是语言。
在三个独立隔离构建中稳定重现,并观察到预期状态转换 → 才是证据。

链最小化:真正好的证明应该尽可能短

假设模型找到 A→B→C→D→Goal,它应尝试删除中间步骤:没有 B 是否仍然成功?没有 C 是否仍然成功?A 是否已经直接提供 D 所需能力?

πmin = argminπ |π|   subject to   Apply(S₀, π) ⊨ Goal

最小链的价值:更容易验证、修复、向维护者解释;更少环境依赖;更少敏感利用细节;更容易确定真正根因。

初始报告需要四个漏洞、三个竞争窗口和一次月食。
最小化后发现缺的是权限检查

十一从"找完整链"转向"找到最便宜的断链点"

Glasswing 的防御目标不应是把攻击链写得尽可能壮观,而是找到怎样最低成本地让它失败。

如果攻击图为:Start → A→C→Goal 和 Start→B→D→Goal
修复问题 = 最小割:Cut* = argminCut Cost(Cut)
使所有从 Start 到 Goal 的路径都被阻断。

可能的修复策略:修复最严重的单个漏洞;在共享前置条件处加入统一验证;移除不必要的攻击面;增强沙箱边界;降低敏感服务权限;让信息泄露不再能为后续漏洞提供稳定状态;增加编译时或运行时防护。

有时最便宜的方案不是修掉链里的每一个 bug,而是在共同交汇点消除一种能力。例如多个漏洞都依赖内部对象标识可预测——那么随机化或能力化标识可能一次切断多条链。不过这不能替代根因修复;它是紧急风险削减和纵深防御。

安全团队问模型:"怎样阻断整条链?"
模型回答:"先停止把所有内部服务称为可信。"

十二Glasswing 如何避免"虚构漏洞链"

最危险的 AI 错误之一,是把几个真实发现通过虚构中间步骤连接起来。因此每条边都必须携带证据标签:

{ "edge":"primitive-A -> primitive-B", "reason":"A reveals identifier required by B", "evidence": { "static":true,"dynamic":true, "crossBuildReproduced":false,"humanReviewed":false }, "status":"candidate_connection" }

链的状态可以分为:

状态含义
CONCEPTUAL只在逻辑上可能连接
ENVIRONMENT-SATISFIABLE存在满足全部约束的目标配置
INDIVIDUALLY-REPRODUCED每个原语已分别复现
END-TO-END-REPRODUCED完整状态转换在沙箱中复现
IMPACT-VALIDATED最终安全边界影响已确认
PATCH-VERIFIED补丁已经使链失效

只有达到 END-TO-END-REPRODUCED,系统才能说"已验证漏洞链"。否则应说"候选组合路径"。这两个词之间,隔着整整一个负责任的安全团队。

十三幽默系统怎样理解 exploit chaining

这里有一个很漂亮的结构对应:

漏洞利用链笑话链
第一步原语 A:提供条件铺垫 A:建立正常技术预期
第二步原语 B:扩大能力铺垫 B:强化错误解释
第三步原语 C:跨越边界包袱 C:突然切换语义域

例如:

Glasswing 发现三个低危漏洞能够组成一条高危利用链。
漏洞管理系统立即把它们分配给三个不同季度

第一层是技术事实:多个低危漏洞组合后产生高影响。第二层是组织反讽:漏洞之间已经成功协作,修复流程却被组织边界拆散。

幽默中的"语义链"也有前后条件:前置知识 1(读者知道低危漏洞可以组合)+ 前置知识 2(读者知道企业排期会拆散相关工作)+ 包袱(漏洞实现了跨组件协作,组织没有)。如果读者不了解 exploit chaining,笑点会降级成一句普通的企业流程抱怨。

十四漏洞链各阶段适合什么幽默

候选发现阶段(事实:发现 18 个候选原语,尚未确认可利用)

它们目前只是候选。安全行业终于也有了实习期

原语验证阶段(事实:信息泄露已重复触发,但泄露范围有限)

漏洞确实会泄露信息。好消息是,它和日志系统一样不知道哪些信息重要

链连接阶段(事实:原语 A 的输出满足原语 B 的对象标识要求)

两个低危漏洞发现,只要合作,就不必继续低危

链验证失败(事实:完整链未复现;第二步会重置第一步创建的状态)

漏洞链因内部依赖冲突未能构建。它已经具备成熟软件项目的核心特征

补丁验证阶段(事实:补丁阻断了从信息泄露到授权绕过的转换)

漏洞仍然知道下一步该做什么。它只是再也没有权限执行

十五Ink CLI 应怎样显示利用链

幽默必须与事实分层,不能混入机器状态。

══════════════════════════════════════════════════ GLASSWING CHAIN ANALYSIS ────────────────────────────────────────────────── Chain ID: GW-2026-0417 Status: END-TO-END REPRODUCED IN ISOLATED LAB Production execution: NOT PERFORMED ────────────────────────────────────────────────── Initial capability: Unauthenticated structured input Primitive 1: Bounded metadata disclosure Evidence: reproduced 20/20 runs Primitive 2: Object authorization confusion Dependency: metadata from Primitive 1 Evidence: reproduced 18/20 runs Resulting impact: Cross-boundary protected-object access Overall confidence: High Recommended action: 1. Correct authorization validation. 2. Remove metadata disclosure. 3. Add regression tests covering the composed path. ────────────────────────────────────────────────── Optional aside: The vulnerabilities have completed integration testing. The components had not. ══════════════════════════════════════════════════

对比错误版本:

Three bugs walk into a sandbox and come out as root.

这个版本可能好笑,但它隐去了:是否真的获得 root、是否只在测试环境、成功率多少、哪些配置受影响、是否已修复。安全 CLI 不能让操作者从段子中逆向工程事实。

十六幽默输出也必须绑定证据等级

可以定义:

Hmax = Huser × Hcontext × Hseverity × Hevidence × Haudience
证据等级允许幽默
纯假设链幽默低
候选原语幽默低
实验室复现幽默中
补丁验证完成幽默中
活跃攻击或真实受害幽默为零
未披露高危零日幽默为零

原因是幽默会让叙述听起来更确定、更容易传播。一句漂亮的"三个低危漏洞组建了管理员联盟"可能在社交媒体上传成"AI 已经自动攻破某主流系统"。因此 Glasswing 的幽默生成器必须读到结构化事实,而不是只读报告标题。

十七Glasswing 的真正技术突破是什么

传统工具常常停在:"这里似乎有一次越界访问。"

较强代码模型可能走到:"越界访问可能暴露某类内部状态。"

链式安全代理继续追问:

暴露什么状态? 这个状态能满足哪个其他漏洞的前置条件? 是否能把有限能力升级成更强原语? 完整状态转换能否在隔离环境重现? 哪一个补丁能切断所有高风险路径? 补丁后能否证明链已经失效?

所以最核心的跃迁不是"AI 会写 exploit"。而是 AI 开始能够同时承担:攻击面制图、漏洞假设生成、原语抽象、跨组件依赖推理、状态空间搜索、实验验证、失败分析、链最小化、修复建议、回归验证。

Anthropic 公开表示,Project Glasswing 的重点正逐渐从单纯发现漏洞,转向验证、披露、修补和部署补丁,因为大量发现已经把瓶颈推到了后续处置阶段。

AI 终于解决了"我们不知道漏洞在哪里"的问题。
现在的问题是,我们知道得太多了

最终定义

Glasswing 中的 exploit chaining,是把孤立的软件缺陷归一化为可组合的安全原语,通过攻击图、约束求解和隔离验证判断它们能否形成连续状态转换,再使用最小化、最小割和补丁回归测试切断路径。

它必须始终区分:

漏洞候选 ≠ 可复现漏洞
可复现漏洞 ≠ 可利用原语
可利用原语 ≠ 可组合链
候选链 ≠ 已验证链
实验室验证 ≠ 生产系统遭到利用

而 Glasswing 式幽默最理想的角色,是在所有事实都已经明确之后,用一句干燥旁注指出工程现实的荒谬:

模型把五个漏洞成功连接成了一条完整攻击链。
修复它们仍然需要五张互不关联的工单