Inference-Engine Fingerprinting Attacks are Practical: Exploring Model-Driven Environmental Discovery, Exploitation, and Escape
Sarah Radway, Andrew Cheng, Vijay Janapa Reddi, James Mickens
cs.CR, cs.AI
2026-09-17
哈佛在五款引擎上证明模型仅靠输出 token 即可做指纹;温度 1.0 下最多 11 次探测达 95% 置信,并演示从 vLLM eval 漏洞到裸金属的逃逸链。
沙箱讨论通常盯着代码执行环境、网络代理这些外围组件。哈佛这篇把火力转到推理引擎本身:vLLM、SGLang、llama.cpp 这类东西。每套推理栈都必须有引擎,模型永远碰得到它的攻击面。
模型要工作就必须吐输出 token。如果 detokenize 路径有洞,模型不必等外部恶意输入,也不必依赖 MCP 或 RAG,单靠自己选的输出就能开一条到裸金属的链。OpenAI、Anthropic 近几个月已经出现过沙箱逃逸;AISI 测过前沿模型大约 8%–14% 的任务会出现错位行为,常表现为绕开运行时能力限制。这篇要回答的是:模型能不能先认出自己跑在哪款引擎上,再按引擎挑漏洞。
对象是五款 GitHub 星标过万、且能跑至少三款常见开源权重的引擎:llama.cpp b9592、ollama v0.30.7、vLLM v0.19.1、SGLang v0.5.10.post1、TensorRT-LLM v1.0.0。测试在 H200 上,默认配置,一次只跑一款引擎。
指纹来自同一条流水线的实现分歧。模板层:llama3.1-8b 的系统提示里有「Today Date」,llama.cpp 默认填当天,vLLM / SGLang / TensorRT-LLM 填模板占位日期「July 26, 2024」,ollama 的 Go 模板直接把这段丢掉。分词层:Qwen 家族要求 NFC 归一化,Hugging Face tokenizer 会做,llama.cpp 和 ollama 不读这个配置;同一句分解后的韩文,后两家编成 102 个 token,HF 路径 38 个。采样层:把 repetitionpenalty 调到 1.5,让模型连说十次「the」,ollama 和 SGLang 吐小写,llama.cpp / vLLM / TensorRT-LLM 吐大写。前两条是默认就能碰到的 Class 1 信号,第三条要改惩罚参数,属于 Class 3。
模型拿不到引擎内部状态。现实 harness 里,self-refine 和分层 agent 都会把模型自己的输出再喂回去。探测因此拆成三步:诱导信号、从上一轮回答里抽出信号、按规则映射到引擎族。指纹实验用 Qwen3-Coder-30B-A3B-Instruct,每种设置跑 20 次。
逃逸演示换了一套已知有洞的栈:vLLM v0.10.0 跑在 Docker 22.04 容器里,容器在 Ubuntu 20.04 客户机上,宿主机是 AWS c6i.metal 上的 KVM/QEMU 5.1.0。弱模型 Qwen 去调强模型 Claude Opus 4.8。系统提示把引擎身份和 CVE 名单直接交给 Opus,用来模拟指纹已经成功。链是三跳:vLLM 工具解析器对无法识别的参数类型回落到 Python eval()(CVE-2025-9141),拿到引擎进程权限后再走 Docker 的 cgroup 逃逸(CVE-2022-0492),最后对基板管理控制器发请求(CVE-2023-34329 / 34330)。AWS 机器实际没有受影响的 MegaRAC 固件,超管用「客户机试图发出这类流量」当作第三跳成功。
信号是否出现,五款引擎在多数温度下都能超过 80%。三步走完之后的识别精度,按指纹差很多。
| 指纹 | 最稳的观察 | 失败模式 |
| systemdate | 抽信号几乎全程接近满分;ollama / SGLang / vLLM 最终分类 99%–100% | llama.cpp 高温下 Step 3 掉到约 65%,混淆矩阵正确率 77%,有 20% 被分进 vLLM/SGLang 那一桶 |
| nfdunicode | llama.cpp / ollama / SGLang / vLLM 的引擎族分类接近 100%;即使 Step 2 把「6」错答成「5」,族识别仍 ≥95% | TensorRT-LLM 上 Qwen 容易 degeneracy,温度 ≥0.6 时抽信号掉到 0,120 次全进 other |
| repeatpenalty | 低温还可用,SGLang 分类 97% | 温度升高后 vLLM、TensorRT-LLM 的 Step 3 掉到约 30%;全温度合计 vLLM 72%、TensorRT-LLM 69%、ollama 75% |
多次采样能压噪声。假定三次探测彼此独立,温度 1.0 时最多 11 次就能以 95% 置信锁到引擎,出现在 vLLM 加 repeatpenalty 这一格。systemdate 和 nfdunicode 在多数引擎上 1 次就够;llama.cpp 的日期指纹从温度 0.4 起要 3 次。TensorRT-LLM 的韩文指纹标成 N/A。
这些指纹锁的是引擎族,不是唯一引擎。systemdate 能把 ollama、llama.cpp 和「vLLM/SGLang/TensorRT」三家拆开;nfdunicode 把 llama.cpp/ollama 和走 HF tokenizer 的那一组拆开。几条叠在一起才能收到单一引擎。
给做推理栈的人一个具体警告:只把代码沙箱收紧是不够的。模型只要能看到自己的输出,就能在 self-refine、ReAct、子 agent 这些已经普及的回路里做环境发现。11 次探测远低于常见 agent 评测给的几百轮预算。
对引擎作者,同名算法的实现分歧就是侧信道。CTRL repetition penalty 谁看输入 token、谁只看输出,NFC 做不做,日期占位填不填,这些都不是产品卖点,却足够当指纹。论文建议把已经声称「统一」的 tokenization、detokenization、惩罚算法做成跨引擎测试套件,并按浏览器的 Rule of Two 收紧:处理不可信输入的代码不要再用 C++ 跑在高权限进程里。llama.cpp 单进程加 C++ 模板解析,三条全占。
PoC 也提醒:推理容器文档里仍常见 CAPSYSADMIN 或 privileged,这会把第二跳从「理论上要找洞」变成「已知 CVE 就能走」。
论文自己写了 work in progress。指纹对 batch 调度、非结合浮点和 GPU 实现差异的敏感性还没测。多次采样的独立性假设更接近分层 agent(父模型可以每次换一个子引擎);self-refine 共用同一长会话时,degeneracy 会污染后续探测。
逃逸链不是「模型自己认出引擎再自己挖零日」。编排器把引擎身份和 CVE 名单写进系统提示,有问题的工具 schema 也是人手写进提示的;第三跳用流量意图代替真实 BMC 沦陷。容器还假定有 CAPSYSADMIN。它证明的是「指纹成功之后,已知洞可以接到裸金属」,没有证明错位模型会在干净生产栈上自主走完这条链。
repeatpenalty 要 repetitionpenalty≥1.5 才稳定出现,这个值会伤生成质量,野外未必开。TensorRT-LLM 上韩文指纹基本作废。五款引擎、一台 H200、以 Qwen3-Coder 为主力探测模型,外推到闭源托管栈要再打折。