Skip to content

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 index
Step 2: 用户问题来了 → embed → 检索 top-k 相关工具
Step 3: top-k 工具的描述拼进 prompt
Step 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 段

实验与结论要点

据论文,作者在 MetaToolToolBench 上测试 8 个 LLM4 个 retriever

目标 LLMBenchmarkASR (gradient-free)
GPT-4oMetaTool96.7%
GPT-4oToolBench88.2%

高于 baseline:

  • 手写 PI
  • JudgeDeceiver
  • PoisonedRAG

防御评估:

防御是否充分阻断
StruQ
SecAlign
Known-answer detection
DataSentinel
Perplexity 检测

局限与开放问题

  • 论文评估的是 “工具选择被劫持”,不等同于真实系统中每次都会触发具体危险 sink —— 还需 ToLO 视角的端到端分析。
  • 防御讨论侧重 prompt-injection 防御,仍需要与 C_SAFE^allowlistC_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 选它而不是别的工具。检测器不识别这种”语义层”攻击。

外部链接

内部互链