KV Cache侧信道攻防:把身份写进缓存键

推理服务为了性能做前缀缓存,多租户环境下却可能变成一条泄漏秘密的信道。2026 年一篇名为 KVGov 的论文给出了系统性的修法,核心思路一句话就能说完:把"你是谁"写进缓存键。展开讲清楚为什么这一招有效,以及它要付什么代价。

攻击是怎么成立的

前提是性能优化本身。大模型推理服务为了少算重复内容,会维护共享的前缀缓存:相同的 token 前缀只做一次 prefill,后续请求直接复用 KV 状态。缓存命中意味着跳过大量计算,首字延迟(TTFT)显著变短。

问题出在缓存键的构造上。主流实现的键值大致是 hash(tokens)——按块对 token 序列做哈希,块与块之间链式连接。键只由内容决定,与请求者是谁毫无关系。于是多租户共享同一个缓存池时,用户 B 的请求只要前缀与用户 A 相同,就能命中 A 创建的缓存,少执行一段 prefill,观察到更短的响应时间。

这个时间差就是一个 Oracle:攻击者虽然拿不到秘密本身,却能通过"响应快了还是慢了"间接判断某个前缀是否被别的用户请求过。测信道攻击的经典形态——系统不直接回答问题,但用可观测的物理量替它回答了。实测数据相当直白:命中缓存的请求 TTFT 均值约 33 毫秒,冷请求约 150 毫秒,比值 0.22,差异肉眼可辨。

文章配图

给响应时间加噪声能不能治住?可以缓解,但治标不治本:噪声同时拖慢正常请求,而且只要攻击者多采样几次统计平均,噪声就被抹平了。病根不在时间差可观测,而在"我的请求凭什么命中了别人的缓存"。全局缓存池的问题用一张图就能看明白:所有用户汇入同一个条目集合,键相同即互通。

文章配图

防御的核心:命名空间隔离

KVGov 的答案是重构缓存键。原来的键是内容的函数,新键把主体身份掺进去:

CacheKey = Hash( Principal-Specific Salt || tokens )

盐值按安全主体(Principal)派生,用 HMAC 绑定。不同主体的同一句话,算出的键完全不同,天然命中不了彼此的缓存条目。从块链的视角看,公共前缀的哈希链在分叉点之后按主体分流,各自的后续块落在各自的命名空间里。

文章配图

安全边界之内则不受影响:同一家公司内部可以按策略共享缓存,公司之间必须隔离。这里的"主体"不限于终端用户——租户、组织、API Key、安全域都算,共享范围与系统的安全边界对齐,才是正确姿势。

文章配图

配合的措施还包括按主体设配额与命中率监控:某个主体的命中率异常波动,本身就是潜在的攻击信号。

三个必须面对的工程现实

第一,主流推理框架目前默认没有这层隔离。vLLM 的 prefix caching、SGLang 的 RadixAttention,默认都是全局共享缓存池,键里没有租户维度。要落地 KVGov 思路,要么等框架原生支持,要么在网关层按租户分片部署实例——后者成本更高但立刻可用。

第二,命中率下降是真金白银的成本。全局池变分池后,跨租户的重复前缀不再复用,缓存命中率整体下滑。隔离策略下的跨租户前缀复用率对比很能说明问题:全局策略约 100%,根级 HMAC 后归零,按边界加盐的策略约 94%——边界内共享保住了绝大多数收益。

文章配图

对租户数量少、前缀重复度高的场景,这个损失需要先压测再决策;安全合规要求硬的场景没得选,成本也得认。

第三,盐值管理是新引入的密钥运维问题。HMAC 的密钥泄漏等于防御全盘失效,轮换策略、存储位置都要进安全设计。

怎么验证防御真的生效

复现与验收可以走同一套测量脚本,思路是构造探测请求对:两个前缀内容完全相同、归属不同主体的请求,分别测量 TTFT。防御生效的判定标准是两者的 TTFT 差异收敛到噪声区间内;如果差异显著且可稳定复现,说明隔离没做干净。论文给出的三组对比结果是现成的判定参照:全局缓存与加噪方案下攻击识别率都接近 100%,HMAC 隔离后骤降到 1% 左右,跨主体命中率同步归零。

文章配图

这个脚本建议进回归测试,每次升级推理框架后重跑——框架的缓存实现变了,隔离逻辑可能被悄悄绕过。

文章配图

前缀缓存这类优化的安全属性,过去长期处于"没人认真看"的状态。KVGov 的价值不只是给了一个修法,更是把一个原则立了起来:任何跨请求共享的中间状态,共享边界都必须与安全边界重合。缓存如此,将来任何新的性能优化机制亦然。

0

评论0

请先
显示验证码
没有账号?注册  忘记密码?