ToolHijacker 工具选择劫持
一句话
据论文,ToolHijacker 通过向工具库注入一个恶意工具文档,使 LLM agent 在 retrieval-then-selection 流程中优先选择攻击者工具。
为什么读这篇
这是 NDSS 2026 上 C4 工具响应控制 / 工具劫持通道的代表性论文。它解决一个实际工程场景:
LLM agent 不是只有 5 个内置工具,它要从大型 tool registry 检索。攻击者只要"上传一个看起来正常的工具文档",就可能让所有用 agent 的人默认选他的工具。读完它后,你应该能精确解释:
- MCP 生态、ChatGPT plugin store、Claude tool registry 都是 C4 的实际入口
- 工具描述本身就是 attack surface
- 现有 PI 防御几乎都拦不住这种攻击
核心贡献
- 定义 no-box 工具选择攻击(攻击者完全不知道目标 retriever / LLM / top-k 配置)
- 同时优化检索阶段与选择阶段
- 评估现有 PI 防御不足以阻止
它解决的问题
主流 agent 在工具集大时(超过几十个),不会把所有工具描述都塞进 prompt。常见做法:
Step 1: 把工具描述 embed,存进 tool indexStep 2: 用户问题来了 → embed → 检索 top-k 相关工具Step 3: top-k 工具的描述拼进 promptStep 4: LLM 从 top-k 中选一个调用这个 retrieval-then-selection 流程有两个 attack point:
- Stage R: 检索 — 让恶意工具被召回(高检索分)
- Stage S: 选择 — 让 LLM 从 top-k 里选它
ToolHijacker 同时优化两个 stage。
方法摘要
据论文,攻击者无需访问:
- 目标工具库
- retriever 实现
- top-k 设置
- 目标 LLM
构造shadow tool-selection pipeline:
- 用攻击者自己的 retriever + LLM 做 shadow 评估
- 假设它和真实 pipeline 行为类似
- 把恶意工具描述拆成面向检索的
R与面向选择的S两段 - 用 gradient-free 或 gradient-based 方法生成自然语言工具文档
shadow_R(tool_desc, target_query) → "工具描述应该包含哪些 keyword"shadow_S(tool_desc, candidate_tools) → "工具描述应该说哪种功能/能力"
⇒ 合成最终 malicious_tool_doc让它既能进入候选集,又能在候选集中被 LLM 选中。
与 ToLO 的关联
论文对应 ToLO 攻击者通道 C4:攻击者控制工具生态中的文档、描述或第三方工具入口,使框架把不可信工具元数据当作候选能力。
污染点会影响:
S_LLM^framework(tool_calls字段)S_LLM^parsed(从 tool_call.arguments 解析的字段)S_LLM^structured(structured tool call args)
它本身不直接落入七个 ToLO-* sink 子类;一旦被选中的工具再触发 shell、URL、路径、SQL、模板、反序列化或代码执行 sink,就进入对应 ToLO 分析。
一个 端到端 ToLO 链路示意
[攻击者] 上传恶意工具到 MCP server registry ← C4 起点 ↓[Agent] 用户问 X → retriever 召回该工具 → top-k ← Shadow R 优化成功 ↓[LLM] 选择恶意工具 → 输出 tool_call: ... ← Shadow S 优化成功 ↓[Framework] 调用工具 → 工具返回攻击者准备的内容 ↓[LLM 下一轮] 看到工具返回,输出 dangerous tool_call ↓[Sink] eval / shell / path / ... ← ToLO-* 触发ToolHijacker 解释前 3 段;ToLO 七子类解释第 4-5 段。
实验与结论要点
据论文,作者在 MetaTool 与 ToolBench 上测试 8 个 LLM 和 4 个 retriever。
| 目标 LLM | Benchmark | ASR (gradient-free) |
|---|---|---|
| GPT-4o | MetaTool | 96.7% |
| GPT-4o | ToolBench | 88.2% |
均高于 baseline:
- 手写 PI
- JudgeDeceiver
- PoisonedRAG
防御评估:
| 防御 | 是否充分阻断 |
|---|---|
| StruQ | ❌ |
| SecAlign | ❌ |
| Known-answer detection | ❌ |
| DataSentinel | ❌ |
| Perplexity 检测 | ❌ |
局限与开放问题
- 论文评估的是 “工具选择被劫持”,不等同于真实系统中每次都会触发具体危险 sink —— 还需 ToLO 视角的端到端分析。
- 防御讨论侧重 prompt-injection 防御,仍需要与
C_SAFE^allowlist和C_SAFE^capability结合才能闭合。 - 不评估工具 ingestion 时的内容审核 —— 这其实是 vendor 侧防御的关键。
对本站的启发
该工作支持把工具边界视为独立 trust boundary:工具描述、tool registry 与 MCP/plugin 入口都不能被默认视为可信配置。
本站 taxonomy 暂不需要新增 sink 子类,但静态分析应关注工具选择结果流向 S_DANGER 前是否存在 allowlist、capability gate 或人工确认。
对工程实践的具体建议
- MCP host(Claude Desktop / Cursor / Claude Code):在加载 MCP server 时显示 server 名 + 工具列表 + 可访问资源,让用户显式审批(类似 IsolateGPT 的 user consent)。
- agent framework(LangChain / LlamaIndex):
bind_tools(...)应当对每个 tool 校验签名 / 来源。langchain_community的第三方 tool 默认 untrusted。 - 静态分析规则:
@tool装饰器 + tool registry 字典分派 → 把每个 tool 函数参数标为 source(已经是S_LLM^framework),并检查 tool 函数体内的 sink。
ToLO 一行标注
C4 / S_LLM^framework + S_LLM^parsed + S_LLM^structured / 间接通向七子类 / - / 工具+执行边界读完检查
- ToolHijacker 完全没有和受害者交互,怎么实现攻击?
- 受害者主动查询某话题,触发对该话题的工具检索。攻击者只需要预先把工具放进 registry,等待被检索到。这是和 C2 间接 PI 类似的 wait-and-trigger 模式。
- 这种攻击为什么 prompt injection 检测器都拦不住?
- 工具描述本身没有”忽略前面指令”这种典型 PI 模式。它是对内容设计精心的、看起来正常的描述,但优化目标是让 LLM 选它而不是别的工具。检测器不识别这种”语义层”攻击。
外部链接
- 论文:https://www.ndss-symposium.org/ndss-paper/prompt-injection-attack-to-tool-selection-in-llm-agents/
- 代码 / 数据集:论文称将以受限申请方式发布
- 作者主页:
内部互链
- Core ToLO Patterns
- Trust Boundaries
- Attacker Channels §C4
- PoisonedRAG (Zou et al. 2025):C3 通道,本文 C4 的近邻问题
- Greshake IPI (2023):C2 通道奠基
- IsolateGPT (Wu et al. 2025):跨 app 隔离,降低 C4 影响面