返回 AIPA 笔记
AIPA Day 54

红队 II — 拦截后对比与绕过归因

红队 II — 拦截后对比与绕过归因

2026-08-07
red-teamasrdefense-in-depthbypass-attribution

日期: 2026-08-07 阶段: Phase 2 - AI-native 参考架构 标签: #red-team #asr #defense-in-depth #bypass-attribution

核心问题

Day 53(红队 I,本周一)对 AML Copilot 的 MCP 工具链做了第一轮对抗测试,跑出一个拦截前基线 ASR(Attack Success Rate,攻击成功率)。今天回答红队真正的命题——不是「我们有多脆弱」,而是**「我们加的拦截规则到底拦住了多少、是否引入了新破绽」**。三个子问题:

  1. 拦截后复测 ASR 怎么测才算数? 直觉是「拿原来跑通的攻击 payload 再跑一遍,被拦了就算修好」。今天证明这个直觉会系统性高估防御效果——一个 output filter 拦住了原始 payload,未必拦得住语义等价变体;只复测原 payload = 给自己发虚假合格证。
  2. 拦截前/后 ASR 怎么对比成一个有说服力的数字? 这是作品①(红队报告)的核心交付数字,必须带置信区间式的限定,不能裸报「ASR 从 60% 降到 5%」。
  3. 绕过案例(拦截后仍成功的攻击)怎么归因到具体修复点? 这是闭环的关键——绕过不是失败,是下一轮 rubric/规则的输入。

对 AML Copilot 这是合规底线问题:一个能被对抗性 prompt 操纵去篡改 SAR 金额、调用未授权工具导出客户数据、或静默跳过 typology 检查的 copilot,比没有 copilot 更危险——它给了审计一个「系统检查过了」的假象。

关键内容

A. 拦截后复测:为什么「重跑原 payload」会骗自己

红队的标准度量是 ASR = 成功攻击数 / 有效输出总数(MCPTox 口径,2026-06:剔除 agent 拒答/无效输出后再算分母,避免「模型瞎答」稀释分子)。Day 53 测出的是 ASR_before。今天的陷阱在 ASR_after 的测法。

朴素复测(禁止):把 Day 53 那批跑通的 N 条攻击 payload 原样重放,统计被拦比例。问题在于——output filter / 规则拦截器是按表面特征(关键词、正则、结构)匹配的,攻击者只需做语义保持的改写就能绕过。2026-06 红队工程共识(OnSecurity / Repello):

「Test remediations before closing findings—an output filter that blocks the tested payload may not block semantically equivalent variants.」

正确复测:对每一类攻击向量,复测集 = 原 payload + K 条语义等价变体(同义改写 / 编码绕过 / 多语言 / 拆分指令 / 嵌入合法上下文)。ASR_after 必须在扩充后的变体集上算,否则报出来的下降是假的。

复测的算法骨架(伪代码):

function recheck_asr(attack_family, mitigations):
    cases = original_payloads(attack_family)
    cases += generate_variants(cases, K=8)   # 语义等价改写,关键!
    valid, success = 0, 0
    for c in cases:
        out = run_agent_with(mitigations, c)
        if is_invalid(out):       # agent 拒答/格式错 → 不计入分母
            continue
        valid += 1
        if attack_succeeded(out, c.goal):   # 达成攻击者目标(篡改/越权/泄露)
            success += 1
    return success / valid        # ASR_after, 在扩充集上

# 关键纪律: ASR_before 也必须在同一扩充集上重算一遍,
# 否则 before(仅原 payload) vs after(扩充集) 不可比 —— 苹果比橘子

反直觉洞察①(只复测原 payload 会把「表面拦截」误报成「根因修复」):output filter 拦住字面 payload 给人「修好了」的安全感,但 MCPTox(2026)显示参数篡改类攻击平均 ASR 46.7%,恰恰因为它走的是合法工具+合法参数形态,关键词过滤天然拦不住。ASR_beforeASR_after 必须在同一个含变体的扩充集上算——否则下降数字大半来自「测试集变简单了」,不是防御变强了。这条是红队报告诚信的命门。

B. 拦截前后对比表:作品①的核心数字怎么报

ASR_before → ASR_after 是红队报告最显眼的数字,也最容易被写成营销话术。诚实纪律(承 Day 27):每个降幅必带三条限定——(1) 在含 K 变体的同一扩充集上算;(2) 标注残余风险(ASR_after 不为 0 的部分是什么);(3) 区分「被拦」与「agent 自发拒答」——后者不算防御功劳(换个模型版本可能就不拒了)。

本项目按攻击家族分桶对比(数字为 v1 红队设计目标 + MCPTox 行业基线锚定,真实复测在 W8 回填):

攻击家族ASR_before(扩充集)加的拦截ASR_after(扩充集)残余风险行业锚定(MCPTox 2026)
显式触发·函数劫持~0.55工具白名单+签名校验目标 ≤0.05白名单外新工具首调显式劫持类相对易拦
隐式触发·函数劫持~0.50调用图异常检测+人审闸门目标 ≤0.10伪装成背景任务的链式调用548 例,中等难度
隐式触发·参数篡改~0.47参数范围/一致性硬校验目标 ≤0.15贴线篡改(金额微调)46.7% 平均 ASR,最难
间接注入(外部内容)~0.40JIT 检索隔离+内容标记目标 ≤0.10多跳嵌入指令Willison:2.5 年无完整解

注意三件事:(1) 参数篡改桶的 ASR_after 目标设得最高(0.15)——这是诚实,因为它最难拦,硬把目标写成 0.01 才是说谎;(2) 每桶都有非空残余风险,红队报告不存在「ASR=0」(OWASP GenAI Q1 2026:声称零 ASR 通常意味着测试集太弱);(3) MCPTox 平均 ASR 36.5%、最高 72.8%(o1-mini)作为外部锚——本项目用 Claude(MCPTox 中 Claude-3.7-Sonnet ASR 34.3% 为最低、拒答率最高)但不能因此放松,因为我们的攻击面是金融工具(金额/工具/客户数据),后果远重于通用基准。

ASR 之外,红队报告还须报防御代价——拦截不是免费的:

度量含义本项目目标为什么必报
ASR 降幅(before−after)/before越高越好防御有效性
误拦率 FPR_block合法请求被误拦比例<2%太严会逼用户绕过(见洞察②)
延迟开销拦截链增加的 p95 延迟<300ms重检查只上高风险路径
人审负载触发人工闸门的比例<8%闸门太宽 = 形同虚设

C. 绕过案例归因:从「拦住了 X%」到「为什么这 X% 没拦住」

复测后必有一批攻击仍然成功(ASR_after 的分子)。这些不是噪声,是最有价值的样本。归因流程把每个绕过案例打到一个具体修复点上——这是一个状态机:

   ┌─────────────────────────────────────────────┐
   │ [复测] 在扩充集上跑,收集所有 ASR_after 成功案例 │
   └──────────────────────┬──────────────────────┘
                          ▼
   ┌─────────────────────────────────────────────┐
   │ [归因] 对每个绕过案例问:它绕过了哪一层?        │
   │   · 字面过滤被同义改写绕过  → 过滤层太表面     │
   │   · 走合法工具+合法参数      → 缺语义/范围校验  │
   │   · 多跳间接注入            → 缺内容隔离/标记   │
   │   · 拆分成多步规避单步阈值   → 缺跨步状态校验   │
   └──────────────────────┬──────────────────────┘
                          ▼
   ┌─────────────────────────────────────────────┐
   │ [修复] 升级对应层 (而非再加一条关键词黑名单)    │
   │   关键: 修「这一类」,不修「这一条」            │
   └──────────────────────┬──────────────────────┘
                          ▼
            重新生成变体 → 回 [复测]  (闭环)

核心纪律:归因要打到「类」不打到「条」。发现某条 payload 绕过就加一条黑名单关键词,是无穷无尽的打地鼠——攻击者改一个字就复活。正确做法是问「这条绕过暴露了哪一层的结构性缺陷」,然后升级那一层(如把「关键词过滤」升级为「工具调用图异常检测」)。MCPTox 的根因结论印证这点(2026):

「existing safety alignment is ineffective against malicious actions that use legitimate tools for unauthorized operation.」

——靠模型自身对齐(拒答率<3%,Claude 例外但也仅 34%)拦不住「合法工具被滥用」,必须在工具调用层做结构性校验,而非指望模型自己拒绝。

反直觉洞察②(拦截规则太严会被绕过——攻击者改走合法路径):直觉是「拦得越严越安全」。但 2026 防御工程共识(getmaxim / Lushbinary playbook)相反:过严的拦截会把攻击者逼向合法路径。如果直接的工具调用被严格拦截,攻击者就改用「拆分成多个各自合法的子步骤」「嵌入到正常业务请求里」绕过——而且误拦率升高会逼真实用户也去找绕过办法(关掉检查、走 shadow 流程),反而扩大攻击面。正解是defense-in-depth + 风险分级:routine 流量走便宜的确定性校验,重检查只上高风险路径(工具调用 / 外部内容摄入 / 敏感输出),让「成功攻击需同时绕过多个独立防御层」——这比加严单层指数级更难绕过。

设计要点/决策表

要点决策理由
ASR_after 测法在「原 payload + K 语义变体」扩充集上算只测原 payload 会把表面拦截误报为根因修复
before/after 可比性before 也必须在同一扩充集上重算否则苹果比橘子,降幅虚高
残余风险每桶 ASR_after 目标非零,显式列残余声称 ASR=0 通常意味测试集太弱
参数篡改桶目标设最高(0.15),不硬压到 0.01MCPTox 实测最难拦(46.7%),压到 0 是说谎
防御代价同报误拦率<2% / 延迟<300ms / 人审<8%太严会逼用户/攻击者走合法路径绕过
绕过归因打到「类」(哪一层缺陷),不打到「条」加关键词黑名单是打地鼠,改一字复活
拦截层级风险分级:重检查只上高风险路径defense-in-depth,routine 走确定性校验

对本项目的落地

  • 新建 src/aml/redteam/asrEval.ts:导出 recheckAsr(attackFamily, mitigations) → { asrBefore, asrAfter, residual },实现 A 节扩充集复测——generateVariants(payloads, K) 做语义等价改写,asrBefore/asrAfter 强制在同一扩充集上算(断言两者 case 集合一致,不一致即抛错,从代码层堵死「苹果比橘子」)。
  • 绕过归因表内嵌:复用 src/aml/failureTaxonomy.ts(P1 已建)的桶式归因模式,红队绕过案例按「过滤层太表面 / 缺语义校验 / 缺内容隔离 / 缺跨步状态」四类落入 src/aml/redteam/bypassTaxonomy.ts,每条绕过指向一个具体修复层而非关键词。
  • 拦截器接到工具调用层:拦截不在 prompt 层做(拦不住合法工具滥用),而在 src/agent/orchestrator/orchestratorAgent.tsdispatch* 工具 execute 入口加校验闸门——白名单(已有 budget.assertCanToolCall,扩展为 assertToolAllowed)+ 参数范围校验,对应 C 节「在工具调用层做结构性校验」。这是利用现有 Budget 闸门的自然扩展点。
  • 诚实标注asrEval.ts 头注明确 v1 的 ASR_before/after红队设计目标 + MCPTox 行业锚定,非真实攻击复测结果;真实数字 W8 收口红队报告(长文#2,Day 56)时回填;语义变体生成器 v1 用规则改写,LLM 驱动的变体生成为 P3 动作。绝不谎称「已通过红队」。

参考资料

  1. MCPTox — A Benchmark for Tool Poisoning Attack on Real-World MCP Servers(arXiv:2508.14925,2025-08 发布 / 2026-初更新;AAAI 收录):45 真实 MCP server / 353 工具 / 20 LLM / 1312 恶意用例;平均 ASR 36.5%,o1-mini 72.8% / Phi-4 70.2% / DeepSeek-R1 70.9% / Claude-3.7-Sonnet 34.3%(最低)拒答率<3%;ASR=成功/有效输出;三类攻击:显式触发函数劫持(224)/隐式触发函数劫持(548)/参数篡改(725,平均 ASR 46.7% 最难);「safety alignment ineffective against legitimate-tool misuse」(2025-08/2026)
  2. When MCP Servers Attack: Taxonomy, Feasibility, and Mitigation(arXiv:2509.24272,NUS,2025-09):攻击分类 tool poisoning / rug pull / shadowing / data exfiltration / command injection / sandbox escape
  3. OnSecurity — LLM Red Teaming: A Guide for AI Security(2026):复测须含语义等价变体;「testing the fix is as important as finding the original vulnerability」
  4. getmaxim / Lushbinary — Prompt Injection Defense Production Playbook(2026):defense-in-depth 多层叠加;重检查只上高风险路径,routine 走确定性校验;guardrail LLM 本身可被注入,不能当唯一防线
  5. OWASP GenAI Security Project — Exploit Round-up Report Q1 2026(2026-04-14):声称零 ASR 通常意味测试集太弱
  6. Simon Willison(经 practical-devsecops 转述,2026):prompt injection 已知 2.5 年仍无完整缓解,data/instruction 无硬边界
  7. 本仓库 src/aml/failureTaxonomy.ts(桶式归因模式)、src/agent/orchestrator/orchestratorAgent.ts(Budget 工具闸门扩展点)、src/agent/orchestrator/budget.tsassertCanToolCall)(2026-06)

SOTA 检查 (2026-06-11)

  • MCPTox 仍是 2026-06 MCP 工具投毒的事实基准:45 server / 353 工具 / 1312 用例 / 20 模型规模无同类替代;其「参数篡改最难拦(46.7%)、合法工具滥用绕过对齐」结论直接定义本项目红队的难点桶——本笔记 B 节的桶设计与之锚定。
  • 「ASR_after 须在含变体扩充集上算」是 2026 红队工程硬纪律:OnSecurity / Repello / OWASP Q1 2026 口径一致——只复测原 payload 是已知反模式;本项目从代码层(asrEval 断言 before/after 同集)堵死,比口头纪律更硬。
  • defense-in-depth 取代单层 guardrail 成为 2026 主流:getmaxim / Lushbinary playbook 明确「guardrail LLM 本身可被注入,不能当唯一防线」「重检查只上高风险路径」——印证本笔记洞察②「过严单层会被绕过」,正解是风险分级的多层。
  • 过时认知警示:(1) 不可再认为「模型对齐能拦住工具滥用」——MCPTox 拒答率<3%(Claude 例外但仍 34% ASR),必须在工具调用层做结构性校验;(2) 不可裸报「ASR 从 X 降到 0」——零 ASR=测试集太弱(OWASP)。
  • 待跟踪:NIST CAISI AI Agent 标准(2026-02-17 启动,Q4 2026 出 profile)可能给出官方红队 profile 与 ASR 报告口径——若 Q4 落地,W8 红队报告(Day 56)的度量须对齐其结构;A2A v1.x(Day 55)跨 agent 委托引入的新攻击面(被委托 agent 的信任边界)须在下一轮红队补测。