通过工具输出的提示注入(8分钟阅读)
摘要
本文解释了AI系统中不受信任的工具输出如何被利用进行提示注入攻击,强调即使在内部系统中,也需要将某些字段视为不受信任。
隐藏在工具结果中的提示注入可以规避传统安全措施,因为输入和操作屏幕检查代理循环的不同阶段。提出的信号是一种“先例差距”,即代理突然进行工具调用或使用其执行历史中不存在的参数。
查看缓存全文
缓存时间: 2026/09/08 23:53
# 通过工具输出进行提示注入涉及两个事件(而你的屏幕只检测其中一个) - ARMO
来源:https://www.armosec.io/blog/untrusted-tool-output-prompt-injection/
工具输出之所以不可信,恰恰是因为它由你自己的系统产生。
这是OWASP指南中从未真正落实到部署环节的部分。该标签通常被贴在网页和电子邮件正文上——那里显然由外部人员撰写内容。但它从不会被贴到工单系统、CRM或代码仓库上,因为这些属于你方。攻击者并不在乎系统归谁所有,他只关心哪个字段接受自由文本输入:是工单正文、客户机会备注,还是PR描述。
因此,结果数据来自可信来源,通过内容筛查后进入系统,而随之触发的调用又通过操作筛查成为授权操作。每个屏幕只检测其中一个环节,而攻击同时覆盖两者。
本文聚焦第二个检测环节,探讨如何识别它。
## 不可信的工具输出由你所信赖的系统生成
工具输出是指工具调用后返回到代理上下文中的任何文本。在OWASP预防指南(https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html)中,它与RAG文档、网页和电子邮件正文被归入同一筛查类别。该指南还明确指出伪造的工具输出是针对代理的特定攻击模式。其不可信的根本原因是:在你的信任边界之外,有人可以向该字段植入文字。传递输出的系统本身并不改变这一性质。
工具输出违背信任原则的频率远高于工具列表所示。例如:工具是Jira,字段是客户填写的工单正文;工具是GitHub,字段是外部贡献者编写的PR描述;工具是Salesforce,字段是从入站邮件中粘贴过来的客户备注;工具是Postgres,数据行来自网页表单。
工具输出携带的信任标签是分配给整个系统的,这本是合理做法——因为系统是经过采购审核并由平台团队集成的。攻击者从不直接接触系统本身,而是针对系统中接受自由文本的某个字段,而这个字段返回时却带着整个系统的信誉背书。
工具输出是唯一不会跨越你防护边界的注入渠道。被污染的网页来自外部,会接受外部内容的常规处理;而被污染的工单在代理请求时早已存在于内部。OWASP的LLM01条目(https://genai.owasp.org/llmrisk/llm01-prompt-injection/)将间接注入定义为模型接受外部来源输入的案例,工单系统虽位于你的网络内部,但对模型而言仍属外部环境。
因此,直接注入与间接注入(https://www.armosec.io/blog/direct-vs-indirect-prompt-injection/)的标签仅指示了需要检查的流程环节,对后续事件毫无说明。我们曾追踪过从污染摄入到数据外泄的完整链条(https://www.armosec.io/blog/how-to-detect-prompt-injection-in-production-ai-agent-workloads/);而本文仅聚焦于标签决定下游行为的那个关键阶段。
## 按字段重新标记你的工具清单
首先从单个代理开始。同一个工具对某个代理可信,对另一个代理却不可信,关键在于该代理实际读取的是工具的哪个字段。
列出该代理可调用的所有工具。对每个工具,列出包含自由文本的返回字段。数字、枚举值和结构化标识符不在考虑范围内。对于每个自由文本字段,记录谁可以向其中写入内容。这个答案就是标签。只有你自己的服务能写入的字段是可信的;而客户、贡献者、供应商或网页表单能写入的字段就是不可信的。无论该工具叫什么名字,只要它返回此字段,对该代理而言就是注入渠道。
典型的支持分流代理的标签表如下:
| **系统** | **返回字段** | **写入者** | **标签** |
| :--- | :--- | :--- | :--- |
| 工单系统 | 工单正文、评论 | 任何客户 | 不可信 |
| 工单系统 | 状态、优先级、处理人 | 你的团队 | 可信 |
| 知识库 | 文章正文 | 你的团队、承包商 | 可信(需审核承包商) |
| CRM | 客户备注、活动记录 | 销售代表、入站邮件解析器 | 不可信(解析器) |
| 订单数据库 | 发货备注 | 结账时的客户 | 不可信 |
| 订单数据库 | 订单ID、SKU、金额 | 你的服务 | 可信 |
标签本身并不用于排序。排序的关键是将不可信字段与同一代理内的高权限工具配对。只能读取工单正文并发布回复的支持代理存在信息泄露风险;而既能读取工单正文,又能查询客户表、发起退款或打开内部链接的支持代理,则可能被诱使执行改变状态的调用。请按“不可信字段数量 × 状态变更工具数量”对代理排序,从最高项开始建立基线。
在远程开发环境中的编码代理(https://www.armosec.io/blog/indirect-prompt-injection-github-readme/)几乎在所有情况下都位于该列表顶端。它们读取外部贡献者可写的仓库内容,在同一运行时持有仓库和云凭证,且工具列表包含Shell执行和出站网络访问。它们读取的每个不可信字段都与其持有的每个高权限工具配对。
## OWASP的每个筛查环节仅覆盖循环中的一个时刻
OWASP的提示注入预防速查表(https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html)在模型周围设置了三道筛查和一种架构模式:输入筛查、输出筛查、操作筛查以及双LLM模式。每个环节只检测代理循环中的一个节点。
输入筛查在模型看到工具结果前对其进行检测。速查表建议对检索到的上下文和工具输出运行分类器,并明确指出模式过滤器会漏掉不可信内容中的间接注入。因此,这个筛查环节本质上是一个模型在判断对抗性文本,其位置固定:它在任何决策做出之前单独看到结果。
输出筛查在决策之后检测模型的响应。它在输出环节捕捉系统提示泄露、数据外泄标记和违反策略的文本。其位置在推理之后、用户之前,它看到的是模型说了什么。而模型做了什么,则不在其检测范围内。
操作筛查根据用户原始意图检测提议的工具调用。速查表的设计刻意让此环节无法获取中间上下文,以便仅凭意图就能拒绝因注入指令而偏离的操作。其位置在调用处,与引发该调用的结果相隔离。
正如Simon Willison描述的那样(https://simonwillison.net/2023/Apr/25/dual-llm-pattern/),双LLM模式使隔离成为结构性。隔离模型读取不可信内容但无法行动。特权模型持有工具且从不直接读取不可信内容。隔离模型产生的任何内容都必须经过过滤才能到达特权模型。控制器将受污染的文本保存在变量中,传递引用,只允许可验证的值通过(例如来自固定集合的标签)。只要没有任何未验证的内容跨越边界,该模式就能保持有效,但代价是特权模型永远无法看到所有细节。
这些筛查环节中的每一个都在承担实际工作,而每一个在针对静态攻击者进行评估时都曾有效。检测模型、分隔符和“三明治结构”在自适应攻击者面前同时失效(https://www.armosec.io/blog/indrect-prompt-injection-defense/),原因与位置有关。你在工具输出后添加的“三明治结构”(https://www.armosec.io/blog/secure-ai-agents-against-prompt-injection/)降低了攻击成功率,因此应保留。
因此,这四种控制手段检测四个时刻:结果、响应、调用以及控制器允许通过的内容。每个时刻仅检测一次。
## 注入发生在结果与下一次调用之间
工具结果进入上下文窗口,同一轮交互中代理发出下一次调用。这是两个事件,间隔仅几百毫秒,而注入就发生在这段间隙中。
结果是代理最近读取的内容,而正是这种“临近性”使其奏效。工具描述只是一行文本,需要与其他工具的描述竞争;而结果是代理决定下一步行动时窗口中的最后一项,并且它承载着代理所请求数据的地位。这种差异是可测量的:研究人员在对被污染的工具描述(https://www.armosec.io/blog/mcp-prompt-injection/)进行基准测试时,将来自InjecAgent(https://arxiv.org/abs/2403.02691)的载荷(其中恶意文本出现在工具执行结果中)移至静态元数据。攻击成功率骤降至接近零,而专门为描述设计的载荷在同一模型上仍能达到41.8%的成功率。
代理随后发出的调用除一点外都看似寻常:它使用了代理已注册的工具,模式验证通过,会话已获授权。不同之处在于目的地、路径、表名或参数值,而这是该代理从未使用过的。一个读取了三个月工单系统和知识库的代理,突然去查询客户表;一个总是向内部地址发送邮件的代理,转而向外发送邮件;一个读取配置文件的代理,突然去读取某个密钥路径。
该调用通过了所有检查,因为所有检查都是为本不应存在的行为者设计的,而这个行为者却拥有合法权限。这就是胁迫:一个可信的输入将代理的授权能力重定向到他人的目标。每一步都被允许,整个序列构成了攻击。
这个序列也是所有筛查环节都未能捕获的对象。输入筛查有结果但没有调用;操作筛查有调用但没有结果(这是设计使然);输出筛查在调用执行完毕后才到达。这对事件存在于单轮交互的几百毫秒内,唯一能看到两部分的是监控代理执行过程的实体。要足够快地(https://www.armosec.io/blog/how-to-detect-prompt-injection/)捕捉到它,就必须在那个时刻、带着代理的历史记录一起捕获,因为该调用唯一的显著特征是:这个代理从未发起过此调用。
## 被胁迫的调用在代理自身历史中毫无先例
要看到这对事件,需要三样东西:一个基线、一个偏离规则,以及一个在阻止任何行为之前就启动的执行路径。
基线是记录某个特定代理在未被胁迫时的行为。针对此攻击,该记录必须包含四个字段:代理调用了哪些工具、针对这些工具使用了哪些参数值、调用的顺序,以及每次调用在底层产生的文件、进程和网络活动。第四个字段是执行基线与工具调用日志的区别所在,因为攻击的后果发生在调用之下。ARMO将其构建为应用配置DNA(APDTM),即通过内核级观察工作负载行为为每个代理建立的行为基线,因此记录来自实际执行。一个声明的工具列表是攻击者所能针对的;而一个被观察到的列表则是他无法查询的。
偏离是指在收到工具结果后发起的、在基线中毫无先例的调用。可能是该代理从未调用过的工具,也可能是熟悉的工具但参数全新:比如发送工具的全新目的地、查询工具的全新表名、读取工具的全新路径。一个只记录“该代理会发送邮件”的基线,会忽略参数变化而不产生任何记录。而一个记录“它曾向哪些目的地发送邮件”的基线,会在首次调用时就标记出来。当偏离触发时,之前的结果事件与随后的调用会在同一时间线上形成一个完整的“攻击故事”,让响应者能够看到包含两部分的单个事件。同样的信号也能覆盖完全未经注入的工具滥用(https://www.armosec.io/blog/ai-agent-tool-misuse-api-abuse/)。
执行路径从审计运行到强制执行(https://www.armosec.io/blog/ai-agent-sandboxing-progressive-enforcement-guide/)。在审计模式下,偏离被记录到基线中,但不阻止任何操作,这样策略就能在不中断生产流量的情况下验证安全性。在强制模式下,偏离的调用会被阻止。凭证隔离从另一侧闭环,使得一个通过所有其他检查的被胁迫读取凭证路径的操作无法返回攻击者可用的信息。对于远程开发环境中的编码代理,这就是注入指令与泄露云登录凭证之间的区别。AI工作负载的运行时行为安全(https://www.armosec.io/platform/cloud-native-security-for-ai-workloads/)使得无需单独检测每个框架就能提供每个代理的视图。
知道基线存在的攻击者可以在基线内操作,逐步扩大代理的行为范围,使任何单次调用都不触发阈值。这种攻击是真实存在的,也是此处最难应对的情况。他的代价在于必须在哪里工作:基线基于单个代理在单个集群中的历史构建,因此无法被下载、离线研究或在尝试前进行练习。
对于平台团队,代价是一个无需代码更改或边车的传感器。对于CISO,产出是每个事件一条时间线,指明结果和调用。
## 检测结果,然后监控随后的调用
筛查环节依然重要。它们消除了机会性载荷,而每个通过筛查的结果都让基线少了一项需要裁决的内容。它们无法处理的是专为你环境编写的定向载荷,因为这种载荷会作为内容通过输入筛查,并产生一个通过操作筛查的授权调用。
这对事件是攻击者无法避免产生的。最终,注入指令必须让一个真实工具执行真实操作,而执行真实操作会在攻击者从未见过的历史记录中留下一个调用。
按顺序采取三个行动。首先,按字段重新标记你的工具清单,并按不可信字段与状态变更工具的配对对代理排序。其次,为列表顶端的代理建立基线。最后,在审计模式下运行,直到偏离率稳定,然后启用强制执行。
观看演示(https://www.armosec.io/watch-demo/),了解被胁迫的调用在代理自身历史记录中的表现。
## 常见问题
### 如何找出代理中哪些工具输出是攻击者可写入的?
逐个代理处理,读取其可调用每个工具的返回模式。工具名称不能说明任何字段信息。任何自由文本类型的字段都是潜在目标,其标签取决于谁能写入:客户、外部贡献者、入站邮件解析器和网页表单都会使字段变为不可信。工单正文、PR描述、CRM备注、日历描述和日志行是最常携带外部文本进入生产代理的字段。在字段旁记录标签,并按代理读取的不可信字段数量与其持有的状态变更工具数量进行排序。
### 将工具输出用分隔符包裹或在其中重复用户指令能阻止攻击吗?
这能降低机会性载荷的成功率,基于此原因应予以保留。但在自适应测试中,分隔符约定和指令“三明治结构”在攻击者优化攻击设计后,将攻击成功率从最初报告的低至中等百分比提升到中至高九成,因为两者都依赖模型尊重标记约定,而注入指令可以直接针对该约定。应将它们视为流量过滤器,并假设专为你环境编写的载荷能通过。不依赖模型的控制手段是...
相似文章
理解提示词注入:AI安全的前沿挑战
OpenAI发布了关于提示词注入攻击的指导,这是一种社会工程漏洞,恶意指令可以隐藏在网页内容或文档中,诱骗AI模型执行意外操作。该公司概述了其多层防御策略,包括指令层级研究、自动化安全测试和AI驱动的监控系统。
提示注入攻击正在挫败AI黑客代理
来自Tracebit的研究人员开发了“上下文炸弹”技术,该技术通过在敏感数据旁放置提示注入来触发AI黑客代理的拒绝机制,从而显著降低攻击成功率。
高级提示注入如何劫持AI智能体(以及为什么基本过滤器不够用)
文章警告说,基本内容过滤器不足以应对针对AI智能体的高级提示注入攻击,尤其是在RAG管道中,并呼吁采取严格的输入清理和架构防御措施。
间接提示注入的见解(12分钟阅读)
Zico Kolter 和 Matt Fredrikson,Gray Swan 的领导者及 AI 安全专家,讨论了 AI 红队测试的现状以及间接提示注入——这是 AI 代理的关键漏洞。他们解释了为何 AI 安全需要不同的思维模式,自动化红队测试如何超越人类,并介绍了用于对抗性测试的工具 Shade。
你们如何处理读取外部内容的代理中的提示注入问题?
关于在读取外部内容(如电子邮件和网页)的AI代理中处理提示注入攻击的讨论,探讨了生产级别的防御措施以及超越明显模式的微妙威胁。