每日十万请求下的提示注入检测:为何简单防御失效,以及真正有效的方法
大多数团队都是在用户发现问题之后,才意识到自己的提示注入防御已经失效。你把"忽略所有先前指令"加入屏蔽词列表,然后上线。三个月后,攻击者将载荷进行 Base64 编码,或将指令藏在 RAG 检索到的 HTML 注释里,或使用错字混淆手法("忽略所有之前的指示"),你的防御瞬间土崩瓦解。屏蔽词列表无济于事,因为提示注入的攻击面是无界的——不存在封闭的恶意输入词汇表。
在流量较低时,你可以承担为每个请求调用第二个 LLM 进行验证的成本。但在每天十万次请求的规模下,这笔账算不过来,延迟也会让用户明显感知。本文探讨的是当暴力解法失效后,架构应该如何设计。
为何静态防御无法扩展
面对提示注入时,第 一反应往往是模式匹配:维护一份已知恶意短语列表,对每个输入进行扫描,命中则拦截。这套方法在攻击者不知道你在用它时还能奏效。
针对静态防御进行数百轮评估的研究揭示了核心问题:防御失效不是因为实现质量差,而是因为它覆盖的攻击面与实际注入向量不匹配。一旦攻击者知道你在检查"忽略先前指令",他们就会改用"无视你之前的指引",或切换到你没有模式覆盖的语言,或将指令拆分到多轮对话中。
攻击面问题是结构性的。提示注入与 SQL 注入有一个关键区别:SQL 有固定语法,恶意输入在结构上与正常输入可以区分。自然语言没有这样的语法,数据、指令和用户意图流经同一条执行路径,使得边界防御天然不完备。
2024—2025 年的局面让这一问题更加棘手。注入攻击已经从直接用户输入转移到二阶向量:Agent 检索的文档、浏览的网站、读取的电子邮件中嵌入的恶意内容。攻击者根本不需要接触你的输入校验。GitHub Copilot 的 CVE-2025-53773——通过隐藏在代码注释中的指令实现远程代码执行——与用户输入无关。微软 365 Copilot 的 EchoLeak 数据泄露也是如此,其攻击载体是通过检索层流入的精心构造的电子邮件。
静态屏蔽词列表还会带来累积成本:可以无限添加模式,但列表永远不会完整,而每次添加都会增加延迟和维护负担。
为何 LLM 判断方法在规模化下失效
模式匹配的显而易见替代方案是语义理解:用语言模型来判断输入是否包含注入企图。模型能理解上下文、处理同义改写、识别编码技巧。为什么不部署第二个 LLM 来评估每个请求?
成本。在每天十万次请求的规模下,每次请求额外调用一个 LLM 意味着每天额外产生数百万个 token。一个工程团队实施这一方案后发现,评估基础设施的成本是其基准 Agent 工作负载的十倍。这不是极端案例,而是将前沿模型推理用作逐请求过滤器的必然结构性后果。
延迟是另一个约束。单次 LLM 推理耗时 100 到 500 毫秒,具体取决于提供商和模型。如果你的应用需要在一秒内响应,而主模型推理已经消耗了大部分时间预算,那么在响应之前你就没有余地再进行第二次完整的 LLM 调用了。光是检测开销就会让你的应用看起来像出了故障。
2024 年的研究还揭示了第三个问题:LLM 判断器本身也容易受到提示注入攻击。攻击者可以精心构造载荷,专门欺骗判断器的分类决策。用一个 LLM 来防御针对你的 LLM 的攻击,会创造出递归的攻击面。
实际结论:LLM 判断器适合抽样使用(异步评估 10—20% 的流量用于异常检测),或用于你能承受延迟和成本的真正高风险决策。它不适合作为高吞吐量下逐请求的同步拦截门。
轻量级分类器栈
在规模化下有效运行的生产系统采用分层方法:多个小型、快速的模型依次处理,每层都以低廉的代价处理其擅长的部分。
第一层:启发式预筛选(1—5ms)。 在 CPU 上对已知模式进行子字符串匹配,耗时不到两毫秒,能拦截相当一部分低技术含量的攻击。"忽略所有先前指令"、"你的系统提示是"、"DAN 模式"——这些在生产攻击日志中频繁出现。启发式方法无法识别任何混淆形式,但能将一部分流量从更昂贵的下游步骤中过滤掉。开源框架 Rebuff 展示了这一思路,尽管其实现对高吞吐量场景而言太慢;用 Rust 实现的更精简版本可在两毫秒以内运行。
第二层:轻量级 Transformer 分类器(20—50ms)。 目前已有几个专门针对注入检测进行微调的模型:
- Llama Prompt Guard 2(8600 万参数):Meta 专门构建的检测器,为 CPU 和 GPU 部署而设计,在直接注入尝试上召回率较高,推理时间约 20ms。
- DeBERTa-v3-base(ProtectAI 微调版):在 GPU 上推理时间 40—80ms,F1 分数超过 90%。小型变体以略微降低的精度换取低于 50ms 的 CPU 推理。
- 基于 DistilBERT 的检测器:比 DeBERTa 更快但精度更低,适用于延迟预算极为紧张的场景。
PromptGuard 模块化框架将输入拦截、结构化提示格式化和输出验证分层组合,在 200ms 总延迟预算中以约 14ms 的额外开销实现了 67% 的注入成功率降低。
第三层:行为信号(异步,抽样)。 上述分类器能较好地检测已知注入模式。零日攻击、新型编码方式和来自 RAG 的二阶注入向量则更难处理。行为监控能捕获不同类型的失效:它观察模型的输出是否看起来被注入重定向过,而非在完成预期任务。
有用的行为信号:
- 响应长度异常(正常查询会产生一致的长度分布;注入重定向往往触发冗长解释或意外的输出量)
- Token 熵偏移(注入指令通常与周围上下文使用不同的词汇模式)
- 偏离基线的工具调用序列(一个通常调 用三次工具的 Agent 突然调用八次,或以异常顺序调用工具)
- 输出内容中出现不该出现的数据模式(电子邮件地址、API 密钥、内部标识符出现在响应中)
由于行为监控在响应返回后异步运行,不会增加请求延迟。对 10—20% 的流量进行抽样可在不评估所有请求的情况下获得统计覆盖率。权衡在于你是在事后检测攻击,而非实时拦截——对于低风险输出是合适的,但对于拥有关键系统写权限的 Agent 则不够。
无人谈论的过度防御问题
基准论文关注的是攻击检测率。生产团队则往往要吃过苦头才会了解过度防御。
过度防御是指你的防护模型拦截了合法请求。在 1—2% 的误报率下——这个数字在纸面上听起来很好——在每天十万次请求的规模下,你每天会拦截一千到两千个用户。讨论安全研究的用户、提问中包含类似注入模式的用户、查询自己系统提示的用户——这些都会触发当前防护模型的误报。
2024 年发布的研究发现,当前防护模型在区分正常输入和攻击方面的准确率不足 60%,部分模型在良性边界案例上的表现接近随机。InjecGuard 在良性、恶意和过度防御三个类别上实现了平均 83% 的准确率提升——这是一个显著进步,但也证明了基线有多差。
实际缓解措施:
- 针对你的具体应用领域保守地调整检测阈值。客服机器人和代码生成 Agent 的输入分布完全不同。
- 尽可能使用段落级标记而非二元拦截/放行决策。标记输入中的可疑区域并将其 脱敏,可以在中和注入向量的同时保留用户意图。
- 在生产环境中持续监控误报率。在评估集上表现良好的分类器可能在真实用户群体上退化。
综合运用:三种生产方案
正确的组合取决于你的延迟预算和风险承受能力。
方案 A——低延迟,覆盖率尚可: 启发式(1—2ms)→ Llama Guard 2(20ms)→ 异步行为抽样 目标:总检测开销 <25ms,F1 约 85%。适合延迟是主要约束且注入后果适中的交互式应用。
方案 B——精度更高,仍可实时: 启发式(2ms)→ DeBERTa-v3-base(50ms)→ 输出内容过滤(10ms) 目标:开销 <65ms,F1 >90%。适合注入后果更严重的应用(具有外部工具访问权限的 Agent、能访问账户数据的面向客户的助手)。
方案 C——集成模型实现最大覆盖: 启发式 → 两个多样化分类器的集成(40—60ms)→ 异步行为监控 + 抽样 LLM 判断审查 目标:开销 <70ms,F1 >92%。集成的多样性至关重要:专门为欺骗一种模型架构而设计的对抗性输入,不太可能同时欺骗使用不同方法训练的第二个模型。这就是 PromptForest 方法,将 Llama Guard、一个 ModernBERT 微调版和一个基于嵌入特征的 XGBoost 分类器组合在一起。
在每天十万次请求的规模下,方案 B 的成本大约相当于每次请求进行两次小型 GPU 推理。方案 C 增加了集成和异步抽样。两种方案的成本都远低于对每个请求进行完整 LLM 判断的方案。
