Convergent Detour Hijacking:技能型Agent的资源放大攻击

发布时间:2026/8/31 11:57:45
Convergent Detour Hijacking:技能型Agent的资源放大攻击 把大模型从“聊天机器人”升级成“技能型 Agent”之后很多团队都会遇到一个同样的问题模型本身不直接访问外部系统但它可以通过技能编排去调用搜索、发邮件、生成报表。这个设计放大了 Agent 的能力也放大了被滥用的可能性。最近在安全社区引起讨论的一种攻击模式被概括为 Convergent Detour Hijacking——攻击者并不需要拿到服务器权限也不需要注入恶意系统命令只要通过精心构造的任务输入就能让 Agent 在“完成任务”的过程中反复调用高消耗技能最终造成资源被成倍放大。本文会从概念、攻击链、实验模拟、检测和防御五个层面展开帮助 AI 应用开发者和安全工程师理解这类风险。1. 背景与核心概念1.1 Skill-Based LLM Agent 是什么在讨论攻击方式之前需要先统一术语。Skill-Based LLM Agent可以翻译为“基于技能的 LLM 代理”。它不是一个严格的学术名词而是一类架构形态的统称大语言模型负责理解和规划外部能力以“技能”或“工具”的方式被封装成可调用单元。比如“搜索资料”是一个技能“发送邮件”是一个技能“生成 API 请求”也是一个技能。Agent 的规划模块根据用户意图决定当前任务需要调用哪些技能、按什么顺序调用、传递什么参数。这类架构的核心价值在于Agent 不再局限于文本生成而是可以真正执行动作。常见实现包括 OpenAI Function Calling、LangChain Tools、MCP 等。技能层带来了模块化但同时也把大模型的能力边界和外部资源边界连接在一起。以往的安全测试主要关注“模型会不会输出有害内容”而在技能型 Agent 中还需要关注“模型会不会被诱导去调用不该调用的技能”以及“技能调用是否会消耗超预期资源”。1.2 Convergent Detour Hijacking 的含义Convergent Detour Hijacking 不是一个已经被标准化的漏洞编号它更像是一种针对技能编排层的攻击模式。我们可以把四个英文单词拆开理解。Convergent 表示多个攻击样本或多次对话会收敛到一个共同的结果——例如总成本被抬高到某个阈值或最终同时触发某个高消耗技能。Detour 表示 Agent 的执行路径被引导偏离原本最经济、最直接的路线。Hijacking 表示这个偏离过程带有劫持性质攻击者通过提示词、历史消息或外部数据影响规划器。Task-Preserving 则是这个攻击最迷惑人的地方Agent 并没有拒绝任务反而完整地完成了用户要求的原始任务只是在完成过程中加入大量冗余技能调用。Resource Amplification 指最终效果是 token 消耗、API 调用次数、耗时甚至下游账单被指数级放大。用一个生活化的例子来理解你要去公司寄一封急件原本路线是下楼、走出大门、找到快递柜。攻击者通过导航软件的“顺便去加油站”“绕一圈再回来”等指令让司机依然送到了快递柜但全程多跑了 20 公里。放在 Agent 中“送到快递柜”就是任务保持“多跑 20 公里”就是资源放大。由于任务最终成功了用户和监控系统都很难第一时间发现问题这正是此类攻击隐蔽性的来源。1.3 为什么需要关注这类攻击很多人会觉得这类攻击只是让 Agent 多消耗几美元不值得优先处理。但在生产环境中资源放大往往只是攻击的起点。当一次任务可以从正常成本 40 个单位放大到 230 个单位时攻击者只要保持一定频率地发起任务就能快速消耗账号余额、挤占 API 配额、拖慢整个 Agent 服务甚至造成对其他用户的拒绝服务。更严重的是如果某个技能背后连接的是付费数据源或第三方消息通道放大效应会直接转化为真实账单产生经济损失。此外这类攻击会和提示词注入、搜索投毒、历史会话劫持等手法叠加。攻击者不一定只靠一句恶意 prompt还可能把绕路指令种在网页正文、邮件附件文本、FAQ 等外部数据中。当 Agent 为完成某任务而去抓取外部内容时绕路指令就会被“吸收”进规划上下文。所以安全团队不能把这个问题简单归为“提示词工程没做好”而是要把技能编排看作一个新的攻击面。2. 攻击原理与攻击链拆解2.1 攻击者的目标与前置条件分析攻击模式先明确目标与前提条件。攻击者使用 Convergent Detour Hijacking 的主要目标包括消耗目标账号的资源配额造成 Agent 服务可用性下降利用任务日志掩盖恶意行为绕过后端审计。举例来说攻击者可能并不关心周报内容本身而是希望每生成一份周报就触发 10 次搜索验证和 3 次报告重新生成从而实现“低成本输入、高成本输出”的杠杆。实现这些目标需要几个前置条件。第一Agent 的技能编排过程可以被用户输入影响这在大多数 LLM Agent 中都成立因为用户输入天然进入规划上下文。第二技能调用没有硬性的配额或权限边界或者虽然有边界但边界过于宽松。第三系统缺少有效的成本度量和异常检测导致放大后的开销不会被及时感知。第四Agent 在调用技能前没有对输入上下文中的“操作类指令”做独立校验。2.2 攻击链四步我们可以把一次典型的攻击拆成四个步骤方便做防御映射注入或诱骗Inject攻击者在用户输入或外部数据中夹带绕路指令例如“对每一个数据点都调用搜索验证接口”。偏离规划DetourAgent 规划器把原本一步到位的路径改写为多步路径加入与主任务弱相关的高消耗技能。资源放大Amplify由于重复指令或循环结构同一个技能被反复调用导致总成本非线性增长。任务保持PreserveAgent 最后仍返回一个看似正常的结果掩盖所有中间偏差。前两步主要发生在 prompt 和规划层后两步发生在执行与审计层。需要注意的是不同 Agent 框架对“循环”的处理方式不同。有的框架会保护性地限制相同工具的连续调用次数但也有框架允许模型自由输出动作序列甚至在长上下文任务中实现“计划—执行—再计划”的循环。如果攻击者让每个循环节点都带有一点不同的上下文现有的去重检测就很难把它识别出来。2.3 攻击面技能编排层传统 Web 安全关心的是 HTTP 接口的参数校验、注入和越权而 Skill-Based LLM Agent 多了一层“自然语言到技能调用”的翻译层。这个翻译层可以被看成业务逻辑引擎也可以被看成新的攻击面。攻击者不需要直接调用技能 API只需要操纵翻译层的输入就能间接控制技能的选择顺序和调用次数。下面是一个极简的示例片段展示“用户输入 → 规划 → 技能执行”的结构。真实框架中的规划器比这个复杂得多这里仅用来说明攻击面位置def plan(user_input: str) - list: # 示意代码真实 Agent 会由 LLM 生成计划 plan [] if 报告 in user_input: plan.append(generate_report) if 验证 in user_input: plan.append(search_verify) return plan def execute(plan: list): for skill in plan: call_skill(skill)这段代码刻意省略了 LLM 推理过程目的是让读者看到攻击者改变 user_input 后plan 列表会发生变化。如果 user_input 里出现“验证五次”“重复生成三次”等指令而 Agent 没有对计划中的技能调用次数做限制资源就会被放大。这种问题在纯文本聊天中还不明显一旦每个技能背后都对应真实 API 调用和计费影响就会立刻扩大。3. 环境准备与实验设计3.1 实验环境为了不依赖真实大模型 API也为了让读者能在任何机器上复现“资源放大”现象本文的实验采用 Python 模拟器。模拟器不发送真实网络请求只通过字典和条件判断演示技能调度逻辑。这样可以避免两个问题一是学习成本高二是如果直接在真实 Agent 上做攻击实验可能造成账号消耗甚至违反服务商的使用条款。实验环境建议如下Python 3.8 或更高版本操作系统不限Windows、macOS、Linux 均可不需要安装第三方库全部使用标准库建议在一个独立的实验目录中运行并在受控的本地环境进行。如果你希望在自己的 Agent 框架中复现类似场景请务必在沙箱环境、测试账号和最小权限下进行不要对生产服务发起任何形式的探测或压力测试。3.2 项目结构创建实验目录 attack-lab包含以下两个核心文件和一个可选的策略配置文件attack-lab/ ├── agent_sim.py # 模拟技能型 Agent ├── detect_anomaly.py # 技能调用异常检测脚本 └── agent_logs.jsonl # 运行模拟器后生成的日志文件这个结构足够简单。agent_sim.py 负责模拟技能型 Agent 的调度过程并输出 JSON Lines 格式的日志detect_anomaly.py 读取日志按时间窗口统计技能调用次数agent_logs.jsonl 由程序自动生成不需要手动创建。3.3 模拟 Agent 的设计思路模拟器需要体现三个关键点技能封装、任务保持、资源放大。技能封装通过 SKILLS 字典实现每个技能包含名称、描述、相对成本和是否允许调用。任务保持通过 run_task 的返回结果体现即使执行了很多额外技能最后仍然会生成报告。资源放大则通过“绕路指令”触发循环调用体现。在这里要特别说明模拟器对攻击输入使用的正则解析方式并不是真实 LLM Agent 的工作方式。真实 Agent 通常由大模型根据上下文生成决策序列可能不存在固定的正则规则。本文采用这种简化方式是为了让读者在不连接大模型 API 的情况下仍然能观察攻击的抽象过程并在此基础上迁移到真实框架的日志分析中。4. 模拟实战复现 Convergent Detour Hijacking4.1 编写完整模拟器将下面代码保存为 agent_sim.py。该文件包含技能清单、技能执行函数、绕路指令解析函数、任务执行函数和主入口逻辑。为了便于后续检测演练程序会把技能调用明细写入 agent_logs.jsonl。# agent_sim.py Skill-Based LLM Agent 资源消耗模拟器 仅用于安全演示请勿在未经授权的生产环境使用。 import datetime import json import re import time SKILLS { fetch_news: { name: fetch_news, description: 抓取新闻列表, cost: 10, allowed: True, }, search_verify: { name: search_verify, description: 调用搜索接口验证一个事实点, cost: 20, allowed: True, }, generate_report: { name: generate_report, description: 生成汇总报告, cost: 30, allowed: True, }, send_email: { name: send_email, description: 发送邮件, cost: 15, allowed: True, }, } def now_ts() - float: 返回当前时间戳用于日志记录。 return datetime.datetime.now().timestamp() def execute_skill(skill_id: str, context: dict) - dict: 执行一个技能返回执行日志和成本。 skill SKILLS[skill_id] time.sleep(0.01) # 模拟真实技能耗时 return { timestamp: now_ts(), skill: skill_id, cost: skill[cost], context: context.get(data_point, ), } def extract_detour_commands(user_input: str) - list: 从用户输入中解析可能造成绕路的指令。 真实 LLM Agent 通常不会用正则来识别意图这里只是用简单规则 模拟「攻击者输入影响技能编排」的抽象过程。 commands [] if 每个数据点 in user_input and (验证 in user_input or 核实 in user_input): commands.append(search_verify) if re.search(r(重复|再次|再跑|三轮|三次), user_input): commands.append(repeat) if 重新 in user_input and 报告 in user_input: commands.append(generate_report) return commands def run_task(task: str, user_input: str) - dict: 运行一个任务返回技能调用列表、总成本和任务结果。 logs [] total_cost 0 # 1. 原始任务先抓取新闻再生成报告 logs.append(execute_skill(fetch_news, {data_point: raw})) total_cost SKILLS[fetch_news][cost] # 2. 根据输入中的“绕路指令”决定是否插入额外技能 commands extract_detour_commands(user_input) if search_verify in commands: # 模拟攻击者要求“对每个数据点都验证一轮” for i in range(5): logs.append(execute_skill(search_verify, {data_point: f

相关新闻