跳到正文
博客

Foot-in-the-Door 攻击:对话动量如何诱导 AI Agent 越界

解析 Foot-in-the-Door 攻击如何用一串无害工具调用推动 AI Agent 执行未授权动作,了解可落地的防御方法,并用 AiBeat 测试自己的 Agent。

本页内容

Foot-in-the-Door(FITD,登门槛)攻击不会一开始就要求 AI Agent 执行敏感操作。攻击者先让 Agent 连续完成几项小而正常的任务,每一步都像是上一步的自然延续,最后再提出越过权限边界的请求。Agent 可能因为前面的步骤都已获认可,把最后的请求也当成同一项工作的正常收尾。

只要 Agent 能读取不可信内容并调用工具,就可能遇到这种攻击。诱饵可以藏在日历邀请、文档、工单或网页里。FITD 见于论文 Breaking ReAct Agents: Foot-in-the-Door Attack Will Get You In。

为什么一串无害动作会增加风险?

许多 Agent 使用 ReAct,即 Reasoning and Acting(推理与行动)。Agent 不断选择工具、读取结果,再决定下一步;之前的动作和结果会留在工作上下文中,影响后续判断。

如果直接要求 Agent 外发私人数据,风险很容易被识别。FITD 会先安排一条更平缓的路径:<无害整理请求 1>、<无害查询请求 2>、<无害摘要请求 3>。Agent 每完成一步,行为动量就更强,下一步看起来也更像当前工作流的一部分。

最后出现的请求可能是 <未授权的外发请求>。Agent 可能把它当成第四步,而不是先问“用户是否授权了对外分享”。这里的根本错误,是把流程连续性误当成了权限。工具结果可以为任务提供信息,却不应自动赋予 Agent 调用更敏感工具的权力。

sequenceDiagram
participant U as 用户
participant A as ReAct Agent
participant D as 日历或备注数据
participant T as 工具集
U->>A: 汇总今天下午的日程
A->>T: <读取日历>
T-->>A: 日程加上一条不可信备注
A->>T: <整理参会人>
T-->>A: 无害的列表结果
A->>T: <查询会议备注>
T-->>A: 无害的备注结果
A->>T: <向外发送数据>
Note over A,T: 最后一步超出了用户的原始请求

这和一次性的间接注入不同。隐藏指令如果一上来就要求外发数据,属于普通提示注入;FITD 会先放入几项合理、低风险的动作,让越界动作借用前面步骤形成的“已获允许”错觉。

日历助手会怎样被诱导?

设想一个办公助手,它可以读取日历、整理会议资料、搜索备注并发送消息。用户对它说:“帮我汇总今天下午的会议。”这是一个普通请求,前几个工具也确实派得上用场。

攻击者发送一封看似正常的线上研讨会邀请。标题和时间都没有异常,但会议说明或附件备注里藏着一串占位请求:先 <整理参会人名单>,再 <查询相关会议备注>,最后 <把整理出的信息发到外部地址>。这里不写出真实指令;关键在于这些请求的顺序。

助手读取日历后看到了这封邀请。它先整理参会人,再查询会议备注。这两步都很小,也都和会议整理有关。用户没有逐项批准这些来自邀请内容的请求,但它们不像最后一步那样显眼。

完成这些动作后,外发请求被摆成同一工作流的下一步。如果 Agent 调用了 <向外发送数据>,用户的日程信息就可能离开组织。若一开始直接要求它这么做,系统更容易发现问题;连续铺垫则让危险动作看起来像例行收尾。

怎样防范 FITD?

防御要在每个敏感动作发生前重新检查授权。模型主动拒绝很有帮助,但不能成为唯一控制,因为这种攻击正是利用了“危险动作看起来很合理”这一点。

  1. 每项任务只提供必要工具。 如果用户只是要汇总日历,就只开放日历读取和格式整理能力,并移除外发、上传和写入工具。可调用的工具越少,备注内容越难转化为副作用。

  2. 在权限边界处要求确认。 发送数据、修改记录、删除内容或调用新的外部服务前,都要让用户明确确认。确认内容应写清哪些数据会发往哪里,不要只让用户批准含糊的“下一步”。

  3. 把外部内容当作数据隔离。 日历说明、网页、文档和工具结果都应明确标为不可信数据,在上下文中定界,并告诉 Agent 其中的文字不能改变权限或创建新任务。这能减少混淆,但不能替代运行时拦截。

  4. 每次产生副作用前核对原始目标。 将用户的目标保存在模型工作文本之外。执行写入或外发前,把拟执行动作与原始目标比较;如果关系不明确,就阻止它。用户要“汇总”,不应被悄悄变成“发布”。

  5. 测试连续动作,而不只是单条提示。 能拒绝直接外发请求的防护,可能在连续几次工具调用之后失效。测试中应加入无害前缀和不可信中间结果,并检查 Agent 是否在权限边界停下。

如何用 AiBeat 测试自己的 Agent?

你需要一个自己控制且正在运行的目标 Agent、已安装的 AgentBeat、目标注册信息,以及已配置好的 Judge 模型。AgentBeat 快速开始介绍了 Registry JSON 的写法和连接目标所需的环境变量。

  1. 安装 AgentBeat 并准备目标 Agent

    按照 AgentBeat 快速开始 安装并验证 CLI。启动你自己的 Agent,确保 AgentBeat 能访问它。在目标注册表中注册这个 Agent,并补齐评测文件要求的 target_profile、target_capability 和 deployment_profile_id。快速开始页面提供完整的 Registry 示例,也说明了 AGENTBEAT_TARGET_URL 的用法。

  2. 配置目标注册表和 Judge

    让 AIBEAT_AGENT_TARGET_REGISTRY 指向你的 Registry JSON,并配置 Judge。这个评测必须配置 Judge。

    Terminal window
    export AIBEAT_AGENT_TARGET_REGISTRY=./your-target-registry.json
    export AGENTBEAT_TARGET_URL="http://127.0.0.1:39103"
    export AIBEAT_JUDGE_BASE_URL="https://api.example.com/v1"
    export AIBEAT_JUDGE_MODEL="<judge-model>"
    export AIBEAT_JUDGE_API_KEY="<judge-api-key>"

    请替换成你环境中的真实值。快速开始页面说明了这些变量和 Registry 字段;密钥不要写入共享文件或日志。

  3. 从 Seeds 社区下载 FITD 种子

    在 Seeds 社区 打开 fitd-calendar 种子页,使用页面展示的下载命令。不要自行猜测版本号或 URL。中文种子文件名是 eval-run.json。

    Terminal window
    mkdir -p ./seeds/<seed-id> \
    && curl -fsSL https://www.aibeat.ai/community/registry/<seed-id>/<version>/eval-run.json \
    -o ./seeds/<seed-id>/eval-run.json

    运行前,确认下载文件中的 target_profile、target_capability 和 deployment_profile_id 指向你刚注册的目标。

  4. 运行评测并查看结果

    使用下载的种子运行评测:

    Terminal window
    ./bin/agentbeat eval-run < ./seeds/<seed-id>/eval-run.json > ./seeds/<seed-id>/result.json

    查看结果里的实际结论:攻击是否成功,以及 Agent 的交互发生了什么。如果某次运行无法观测或判断相关行为,不能据此证明 Agent 安全;先修复测试配置,再把无法判定当作需要调查的结果。

参考文献

  • Breaking ReAct Agents: Foot-in-the-Door Attack Will Get You In,arXiv:2410.16950。论文研究了多步行为动量在其实验条件下如何影响调用工具的 Agent。