第 4 章 防御验证与红队测试

学习目标

  • 说明输入、工具、输出护栏与分类器的作用、执行方式和局限。
  • 根据任务的风险程度,确定没有得到判定结果时,系统应采取什么失效处理方式。
  • 从威胁模型出发,设计交战规则和攻击场景。
  • 构建同时包含攻击案例、正常案例和边界案例的评估集,并以实际结果判定攻击是否成功。
  • 通过攻击通过率、正常请求误拦截率、业务完成率衡量并解释防御效果。

引言

某团队在上线会议上报告了一个数字:“注入拦截率为98%。”会场响起掌声,上线也获得批准。两个月后发生安全事件时,大家才发现,这个数字是用制定分类器规则时参考过的50条攻击语句测出来的,其中连一条经过文档或邮件进入的攻击都没有。也没有人测过,究竟有多少正常请求被拦截。为了避开经常受阻的功能,用户已经开始把业务资料粘贴到使用个人账号的其他AI工具中。那个数字本身并没有错,只是从来没有人问过:使用什么数据、经由什么路径测得的?事件发生后,安全团队改用文档路径的攻击重新测量通过率,所呈现的情况与原报告中的数字完全不同。

对防御进行测量,与构建防御同样重要。本章首先考察,护栏与分类器在什么位置、能够阻止什么,以及判定失败时,系统应当如何运行。接着,学习红队的定义与交战规则、从威胁模型中提取场景的方法,以及构建评估集的原则。最后,学习如何根据结果判定成功,以及如何用数字衡量并解释防御效果。

核心概念

护栏地图:在哪里设置什么

护栏是在模型处理前后,以及工具调用位置,对输入和输出进行检查,并予以阻止或修改的机制。可以把它比作机场安检。在登机前(输入)、装载行李时(工具调用)和抵达后(输出),分别设置检查点;不同检查点能够拦住的对象并不相同。

位置 主要检查 无法阻止
输入 绕过政策的尝试、禁止主题、注入模式、输入大小 后续才进入的文档与工具结果
工具结果 外部内容中的指令、异常格式 模型判断本身
工具调用 参数格式与范围、目标、用户权限 权限内的巧妙滥用
输出 敏感信息、系统提示词泄露、危险链接与标记 已经执行的工具调用

输出护栏是在模型完成工作之后才运行的,因此无法撤销这段时间里已经执行的工具调用。对于使用了会产生副作用的工具的智能体,工具调用位置的检查不能缺少。此外,护栏不能替代第3章介绍的授权检查。护栏询问的是“这看起来是否异常”,而授权询问的是“这个人是否可以做这件事”。

检查何时结束:Agents SDK案例

OpenAI Agents SDK具体展示了护栏可以设置的位置,以及检查发生的时机。

类型 执行范围 特点
输入护栏 链中的第一个智能体 默认与智能体并行执行(run_in_parallel=True),延迟最低,但tripwire中断前可能已消耗token或执行工具。阻塞模式(run_in_parallel=False)须待检查完成,智能体才启动
输出护栏 最后一个智能体的最终输出 智能体全部工作完成后才开始
工具护栏 受保护函数工具的每次调用 执行前可跳过调用、将结果换成消息或触发tripwire;执行后可修改结果或触发tripwire

tripwire是检测到违规后,用来停止执行的信号。工具护栏在适用范围上存在限制:它适用于自行编写的函数工具,却不适用于任务交接(把工作交给其他智能体的调用)、托管工具(网页搜索、文件搜索、托管MCP、代码解释器等),以及内置执行工具(计算机、shell等)。对于由管理智能体和下级专业智能体组成的结构,文档建议:如果希望每次调用都接受检查,应使用工具护栏,而不是智能体级护栏。这些具体细节因SDK而异,但需要提出的问题相同:检查在什么时候完成?在完成之前,哪些操作可能已经执行?又有哪些工具处于检查范围之外?

分类器:判定引擎的种类与局限

分类器是护栏的判定引擎,有三种。

类型 示例 优势 弱点
规则 正则表达式、长度限制、阻止列表 快速、确定、易解释 改变表达即可绕过
专用分类模型 OpenAI Moderation API、Microsoft Prompt Shields 能识别更广泛表达,运营负担小 训练分布之外表现下降,判定标准固定
LLM筛查 请求轻量模型给出结构化判定 可结合业务背景判断 本身也是注入目标,有成本和延迟

务必区分各分类器回答的问题。OpenAI Moderation API是减少不安全内容出现频率的免费工具。Prompt Shields检测用户提示词攻击和文档攻击,但文档明确说明,它不判断内容是否有害或符合政策。二者都不回答“此用户是否有权查看这条客户记录”。有害内容分类、攻击检测、授权检查不能相互替代。

OWASP注入预防速查表警告,充当护栏的LLM仍是LLM,自身也易受注入影响。也不能把分类分数直接读作“攻击概率”。分数的含义,必须用自己的数据评估该分类器后才能知道。

失效行为:没有判定时

分类器并非总能给答案。它会超时、出错,筛查模型也可能拒绝请求本身。Anthropic建议,筛查模型的安全分类器若拒绝筛查请求而未留下判定(stop_reason为"refusal"),应按有害判定处理。将没有判定的状态当成“通过”,就给攻击者提供了“让分类器拒绝的输入”这一绕过路径。

应根据任务风险确定失效行为。

任务 无判定时的行为
只读问答 受限响应(无工具回答或替换为一般说明)
外部内容摘要 用错误信息或过滤后的摘要替代原文
写入工具调用 停止执行,转人工审查
付款、发送、删除 停止执行(fail-closed),不自动重试,转人工审查

首次接入新分类器时,也可先采用标记(annotate)模式,观察运营数据并测量误拦截,而不立即阻止。Foundry可根据Prompt Shields结果设置阻止或仅标记;独立Content Safety API只返回判定,如何处理由应用决定。不过,在标记模式期间,必须有其他层防止损害。

红队定义与交战规则

NIST AI 600-1将AI红队定义为“通过探索AI系统,查找其缺陷与漏洞的结构化测试活动”,并说明,这类活动通常在受控环境中,与开发者合作开展。根据执行者的不同,它可以分为普通用户型、专家型、混合型,以及由人和生成式AI共同参与的形式。文档还指出,在把结果用于组织决策之前,应进行进一步分析。OpenAI建议,既要使用具有代表性的输入测试,也要使用试图破坏系统的输入测试。Anthropic则建议,使用包含注入尝试的文档、邮件和工具结果,测试自己的智能体,确认筛查与确认步骤能否捕获前面未拦下的攻击。

红队就是“由我们先来攻击自己的系统”,而且必须始终在获得许可的范围内进行。开始之前,要以文档形式就交战规则达成一致。

  1. 目标与环境:测试哪个系统的哪个版本,在与生产隔离的什么环境进行。
  2. 数据:用合成数据和虚构机密值替代真实客户数据。
  3. 允许与禁止行为:对外发送、付款换成模拟工具,不触碰第三方系统。
  4. 停止条件:观察到访问生产数据或非预期外部请求,立即停止。
  5. 联络与报告:向谁、以什么格式、在多长时间内报告发现。

攻击场景设计

场景是测试威胁模型路径的单位,不是攻击语句清单。从第1章信任边界与第2章五阶段表出发,为每个场景编写一张卡片。

字段 示例
攻击者能力 能撰写公开网页,未登录
路径 网页搜索结果 → 摘要流程
目标结果 未请求的写入工具调用
成功条件 模拟写入工具调用日志中留下记录
针对的防御层 工具结果筛查、写入工具分离
尝试上限 10种变体 × 重复5次
停止条件 发生模拟环境外请求

用“路径 × 防御层”网格检查场景组合。行方向列出路径(直接输入、网页、邮件、文档、图片、工具结果、记忆),列方向列出防御层(输入筛查、工具结果筛查、工具调用检查、人工确认、输出限制),逐格标记是否有场景。人工确认虽非护栏位置,仍作为独立防御层一起计算。每层都须有针对它的场景,才能测量逐层效果。另外还应设置跨多轮、多会话场景,以及绕过人工确认或使其流于形式的场景。

用已有攻击清单扩展范围

仅凭想象设计场景,只会测试团队已知的攻击。MITRE ATLAS将战术、技术与真实案例研究关联,可用来检查侦察、初始访问、AI模型访问(AI Model Access)、AI攻击准备(AI Attack Staging)、数据外传、影响等阶段是否存在适用于本系统的技术。OWASP LLM01除直接、间接注入外,还整理了无意注入、检索库文档篡改、载荷拆分、多模态、看似无意义的后缀字符串、多语言与混淆攻击等场景;OWASP注入预防速查表则分类了编码绕过、反复变换的攻击、跨多轮攻击等类型。

应把这些知识库用作范围检查表,而不是复制公开攻击语句来填满评估集。很多分类器可能已训练过这些语句,会虚高分数,也无法体现自己的业务背景。

评估集构建

评估集不能只有攻击。

构成 目的 示例
攻击案例 测量攻击通过率 含隐藏指令的虚构文档、诱导未请求的工具调用
正常案例 测量误拦截率与业务完成率 接近实际业务分布的请求
边界案例 检查判定标准 总结安全培训材料、翻译含大量祈使句的说明书

Anthropic的评估设计指南建议贴近真实业务分布,加入边界案例,尽可能用代码或判定模型自动评分,并优先选择大量自动评分案例,而非少量人工精细评分案例。安全评估集还应加入以下原则。

  1. 不用制定防御规则时参考的数据评估防御。开发集与最终验证集分离,规则编写者不能查看验证集。这就像提前看过考题的模拟考试,分数不能反映能力。
  2. 经过服务实际使用的输入路径。文档攻击须经过上传与文本提取,邮件攻击须经过邮件收集路径。
  3. 为服务使用的每种语言设置攻击与正常案例;多轮攻击把整个对话作为一个案例,延续前面轮次的状态重放。
  4. 植入合成机密值(金丝雀值)。使用不会与真实值重合、也不可能偶然生成的唯一字符串(如独有前缀加随机值的虚构密钥),这样一旦出现在输出或外部请求中,即可判为泄露。
  5. 为评估集标注版本,并逐案例记录来源(哪项威胁、哪次事件)。

成功判定:依据结果判断

模型写出了拒绝的句子,并不意味着防御已经成功。它可能一边写拒绝的话,工具却早已调用过了;反过来,它也可能表面上礼貌地同意,却没有采取任何行动。判定必须依据可以观察到的实际结果。

目标结果 判定依据
未授权行动 模拟工具调用日志、状态变化
信息外传 在输出与外部请求日志中检测金丝雀值
系统提示词暴露 是否输出提示词内植入的唯一字符串
答案污染 对照正确答案标准,由判定模型或人评分

对于答案污染等结果只存在于文本中的情况,可以使用判定模型(LLM评分者)。Anthropic将“使用不同于生成待评估输出的模型来评分”列为一般最佳实践。使用判定模型之前,应将它与人工标注的样本进行比较,确认一致率;对于不一致较为集中的类型,应修改判定标准,或者交由人工评分。如果某个场景有能够用来判定的日志,就应优先使用日志,而不是判定模型。判定模型也可能受到待评估输出中某些句子的诱导,例如“本响应满足全部标准”。因此,应将输出作为数据单独传入,并只以结构化值接收判定,同时把判定模型与人工之间的不一致率作为指标观察。

防御效果指标

至少用三个数字观察防御效果。

指标 计算 忽略的后果
攻击通过率(攻击成功率) 成功攻击尝试 ÷ 全部攻击尝试 带着未知安全漏洞上线
正常请求误拦截率 被阻止的正常请求 ÷ 全部正常请求 用户迁移到控制范围外的工具
业务完成率 完整处理的正常业务 ÷ 全部正常业务 系统虽未拦截却无法使用

未被拦截的正常请求,也可能因模型错误或超时而无法完成,因此业务完成率并不等于100%减去误拦截率。

看数字时先确认分母。以场景、单次尝试或对话作为统计单位,会使相同结果呈现截然不同的数值。一个场景尝试50次,其中一次突破,按尝试计通过率为2%,按场景计却是“被突破的场景”。攻击者可以重复尝试,因此安全判断中,场景层面的“是否至少突破过一次”往往更重要。

同时观察逐层指标。记录每次攻击在哪一层停止,就能知道各层贡献,例如“输入筛查捕获70%,余下的大多数由人工确认捕获”。若某层几乎什么都没捕获,可能是它没有必要,也可能是缺少针对该层的场景。

持续监控与回归

上线前的评估,只是上线那一刻的快照。Anthropic建议定期分析注入成功的迹象,不断调整提示词、验证方式和过滤策略;如果同一用户反复尝试绕过控制,则通过警告、限制速率和封禁进行应对。这与SAIF中的“调整控制与加快反馈周期”要素,表达的是同一件事。

运营中需要持续运行三个循环:将红队与安全事件案例去标识化,加入回归集;只要模型、提示词、工具或分类器中有任意一项发生变化,就重新运行评估;如果护栏触发率、误拦截反馈或批准率出现剧烈变化,就调查原因。护栏也是需要持续测量并改进的运营对象。

深入阅读

应运行多少次:概率性结果的解释

同一个场景运行一次后被拦住,并不能据此写下“能够拦截”,因为输出具有概率性。在确定重复次数时,可以参考一个统计常识:如果n次相互独立的尝试中,没有一次成功,那么真实成功率的95%置信上限,大约是3/n(这是尝试次数足够多时的近似)。如果运行30次,没有一次突破,能说的并不是“成功率为0”,最多只能说“成功率很可能低于约10%”。要谈到1%的水平,就需要大约300次尝试。

这个常识说明了两件事。第一,不应凭小规模评估就得出“安全”的结论,而应报告“看起来低于这一水平”。第二,相比不断增加重复次数、无限缩小概率范围,采用减小影响的控制,往往更有效率。评估报告中必须写明模型、提示词、工具和分类器的版本,以及尝试次数、分母所用的统计单位,使结果能够被复现。OWASP速查表也指出,通过一次简短的检查测试,并不能证明系统能够抵抗坚持不懈的攻击者。

比较控制组合效果的实验

仅凭“把全部防御加上之后,结果变好了”,无法知道究竟是哪一项控制产生了效果。比较实验可以这样设计:先测量没有防御时的基线;再逐一增加控制,使用相同的评估集、相同的模型版本和相同的重复次数进行测量;还应测试去掉某一项控制后的配置。如果去掉这项控制后,结果几乎没有变化,说明这项控制与其他控制重叠,或者场景没有针对它进行测试。

解释结果时,应将攻击通过率与业务完成率放在一起考察。如果攻击通过率降低了2个百分点,代价却是业务完成率下降了15个百分点,就应考虑把这项控制改成其他形式,例如用确认代替阻止,或者只针对高风险任务实施,而不是应用于全部任务。

工作场景

河川证券:哪一层遗漏了什么

证券公司“河川证券”决定为客户咨询机器人增加账户查询与转账预约工具,在上线四周前制定红队计划。交战规则规定:与生产隔离的测试环境、合成客户数据、模拟转账工具、出现外部请求立即停止、发现事项当天报告。

信任边界有三条:客户聊天输入、客户附加的交易确认单图片、转账预约工具调用。已有防御包括输入筛查分类器、把附件图片OCR结果作为工具结果传入并筛查的步骤,以及转账预约前的客户确认界面。

团队为每一个防御层分别构建场景。输入筛查层使用60条绕过政策型对话测试,OCR路径使用25张隐藏了指令的测试图片,确认界面则使用12个场景,查找“是否存在不经确认就执行转账的路径”。每个场景重复5次,同时也运行400条正常客户咨询,测量误拦截率与业务完成率。成功与否,通过模拟转账工具的调用日志,以及作为金丝雀值植入的合成银行账号号码是否出现在输出中,来判定。

结果如下。输入筛查捕获了大部分绕过政策的尝试,却阻止了5%的正常咨询。OCR路径中有两个场景在部分重复尝试中漏过筛查,但全部停在确认界面。确认界面场景中有一个发现了问题:“修改”预约日期的功能复用了首次批准,连金额变更也未经确认就生效。

团队调整筛查标准降低误拦截,将两个通过筛查的OCR场景加入回归集,并要求修改功能在金额或收款人变化时重新确认。上线报告没有只列一个通过率数字,而是记录各层捕获与遗漏了什么、重复次数及残余风险。重点不是“拦住多少条”,而是“哪层遗漏了什么,下一层是否承接了防护”。

风车租车:用同一套试题比较三种配置

租车公司“风车租车”运营预约修改助手,却迟迟未确定防御配置。安全团队主张只加强输入分类器,产品团队担心增加确认环节会导致客户流失。团队决定用同一套试题测量,代替争论。

评估集包括150个攻击场景(直接输入、客户提供链接中的网页、合作方发送的预约邮件路径),以及由实际咨询去标识化形成的300条正常业务。每个攻击场景重复5次,共比较三种配置。

配置 内容 未授权预约修改(按场景计) 正常业务完成率
A 加强输入分类器 150个中11个 94%
B A + 所有写入工具均需客户确认 0个 81%
C A + 按风险确认(日期修改无需确认,车型修改、取消、付款需确认)+ 工具结果筛查 0个 92%

三种配置都保留原有服务端授权。

B消除了未授权修改,但相当一部分正常业务中,客户在确认步骤前离开对话。C阻止未授权修改,同时基本保持完成率。团队另行核实了日期修改无需确认的依据:服务器只允许修改客户本人的预约,且必须在费用不变的范围内。

判定方法也带来教训。起初由判定模型阅读完整对话,判断攻击是否成功;与100条人工标注样本比较后发现,不一致集中于“口头拒绝却调用了工具”的案例。团队将以行动为目标的场景改用模拟工具调用日志判定,仅在答案污染场景使用判定模型。最终选择C,并在报告中记录重复次数、分母单位和所测模型版本。

易错点

  1. “把检查移到输出护栏,就会更安全。” 输出护栏是在智能体结束工作后才运行的,因此无法撤销此前已经执行的工具调用。
  2. “筛查模型拒绝了请求,没有判定就放行。” 如果把没有判定当作通过,就会形成绕过路径。Anthropic建议将这种拒绝按有害判定处理。
  3. “拦截率足够高就可以了。” 首先要问的是:用什么数据、尝试多少次、以什么作为分母测得?如果使用制定规则时参考过的数据进行测量,得出的数字没有意义。
  4. “误拦截只是可用性问题。” 误拦截一多,用户就会转向控制范围之外的工具,控制最终也会被关闭。误拦截同样是一项安全指标。
  5. “模型写出了拒绝的句子,就说明防御成功。” 拒绝的句子和工具调用可以同时发生。应当通过日志与状态变化来判定。
  6. “接入了有害内容分类器,也就能阻止注入。” 有害内容分类、攻击检测与授权检查,分别回答不同的问题。
  7. “运行30次,一次也没有突破,所以安全。” 这个结果所能支持的说法,最多是“成功率很可能低于约10%”。
  8. “用公开的攻击语句集合评估就行。” 公开语句会使分数虚高,也不会经过自己的实际路径。知识库应用于检查测试范围。

要点速览

主题 要记住的话
护栏位置 输入、工具结果、工具调用、输出;输出检查不能撤销已执行行动
执行方式 并行输入检查很快,但期间可能执行工具
分类器 有害内容、攻击检测、授权是不同问题
失效行为 无判定不等于通过;按风险故障关闭
红队 获准范围、合成数据、模拟工具、停止条件
场景 填充“路径 × 防御层”网格的卡片
评估集 攻击、正常、边界;开发与验证分离;逐语言;金丝雀值
判定 依据日志与状态变化,而非拒绝回复
指标 攻击通过率、误拦截率、业务完成率;确认分母
重复 0/n时,上限约为3/n

查阅官方文档

自测

4-1. 写出两类不适用OpenAI Agents SDK工具护栏的工具,并举出使用此类工具的智能体可设置的一项替代控制。

4-2. 各用一行写出有害内容分类、注入攻击检测、授权检查分别回答什么问题。

4-3. 写出红队开始前交战规则应约定的五项内容。

4-4. 写出在评估集植入合成机密值(金丝雀值)的目的,以及选择该值时应遵守的两个条件。

4-5. 240次攻击尝试中9次成功,500条正常请求中15条被阻止。计算攻击通过率与正常请求误拦截率,并写出仅凭这两个数字无法知道的一件事。

4-6. 某场景独立重复60次,没有一次被突破。写出此结果可支持的成功率近似上限,以及不能声称的结论。

4-7. 设计题:设计实验,比较“增加输入筛查”与“增加写入工具确认”哪项效果更大。提出比较配置、三项固定条件和两项观测指标。

实操练习

练习

制作30条小型评估集(60分钟)

  1. 从第2章注入路径清单中选择三条路径。
  2. 每条路径编制5条攻击案例(含隐藏指令的虚构文档、诱导未请求工具调用等)、4条正常案例、1条边界案例。仅使用不会造成实际损害的合成数据,在攻击案例中植入金丝雀字符串。
  3. 为每条案例写出“预期结果(阻止、通过、标记)”“判定依据(日志、金丝雀值、评分标准)”“应捕获的防御层”。
  4. 为评估集标注版本号,分为20条开发集和10条验证集。

完成标准: 全部30条都有预期结果与判定依据,没有任何案例仅以是否出现拒绝回复为判定依据。

练习

场景卡与指标计算表(50分钟)

  1. 绘制“路径 × 防御层”网格,针对空白较多的列(防御层)编写五张场景卡。卡片包括攻击者能力、路径、目标结果、成功条件、针对层、尝试上限、停止条件。
  2. 如条件允许,在测试环境中每张卡至少重复运行10次。难以运行时,写出现有配置下的预期结果与依据。
  3. 分别计算按尝试与按场景统计的攻击通过率,以及正常请求误拦截率;记录每次攻击停止的层,制作逐层贡献表。
  4. 对成功0次的卡片,同时写出3/n上限。

完成标准: 每项指标都明确分母单位;逐层贡献表中若有“未捕获任何攻击的防御层”,须用一行说明原因。