用户访问的是账户页面,CDN看到的却像一张图片。两边对同一URL的理解不同,可能让本应只返回给当前用户的订单、邮箱甚至安全令牌进入公共缓存。这类问题被称为Web缓存欺骗(Web Cache Deception,WCD)。
WCD危险之处在于请求和响应都可能返回200,监控没有明显报错。漏洞往往藏在路径后缀、分号、编码字符和重写规则中。防御不能只添加一条“禁止缓存.php”的规则,而要统一CDN、代理、框架和应用对URL的解析。
漏洞是怎样形成的
假设应用把/account/profile/anything都路由到个人资料页面,而CDN按照扩展名缓存静态文件。攻击者诱导已登录用户访问/account/profile/photo.css,应用仍返回个人资料,CDN却可能因.css后缀把响应当作公共资源保存。随后攻击者访问相同URL,就可能命中缓存。
不同服务器对分号参数、双斜杠、点号段和URL编码的处理也可能不同。只要缓存键与应用最终资源身份不一致,就存在混淆空间。

WCD与缓存投毒有什么区别
WCD通常是诱导缓存保存受害者的私有响应,重点是隐私泄露;缓存投毒则是攻击者让恶意或错误响应进入缓存,影响后续用户,重点是内容完整性。二者都利用缓存规则和应用解析差异,但测试方法与影响评估不同。
实际事件可能同时包含两者。例如先用未纳入缓存键的请求头改变响应,再让该响应被公共缓存。审计时不要只按名称分类,应追踪“谁控制了响应、缓存为什么接受、哪些用户会命中”。
如何在不影响生产的前提下验证
优先在测试环境使用专门账号和无敏感数据页面。构造路径变体后,检查Cache-Control、Age、Vary、Set-Cookie和CDN命中标识;再次以无登录状态请求相同URL,确认是否返回了前一会话内容。不要在真实用户页面批量扫描。
生产环境可以先通过日志寻找信号:动态路由带静态后缀、账号路径出现高缓存命中、含Set-Cookie响应被缓存、同一缓存键对应不同用户。发现异常后先停止相关缓存,再做范围确认。

防御要从响应身份出发
对包含身份、订单、令牌或个性化内容的响应明确设置Cache-Control: private, no-store,并确保CDN不会覆盖。缓存规则应以明确允许列表为主,例如只缓存固定静态目录和确定的内容类型,而不是“凡是某后缀都缓存”。
应用和边缘应使用一致的路径规范化策略。鉴权应在缓存命中之前完成,或者把身份维度正确纳入私有缓存键。响应含Set-Cookie、Authorization相关请求和非GET方法默认不进入公共缓存。
修复后还需要做什么
先清除可能受影响的缓存对象,再检查访问日志和缓存日志,评估是否存在未授权命中。若响应中包含会话令牌或密钥,应按泄露处理并轮换。修复规则需要覆盖各节点和备用域名,不能只改主域。
最后把WCD用例加入发布测试。路由、框架或CDN配置升级后自动验证敏感页面不会缓存。缓存安全不是一次渗透测试,而是随着URL规则变化持续维护。

落地检查清单
- 敏感响应明确使用private或no-store
- 只对白名单目录和内容类型启用公共缓存
- 统一边缘与应用的URL规范化
- 检查Set-Cookie、Authorization与Vary处理
- 修复后清缓存并评估令牌轮换
结语
Web缓存欺骗没有神秘的利用魔法,本质是多个系统对资源身份判断不一致。让应用明确声明响应是否可缓存,让CDN按允许列表执行,并持续验证路径边界,才能真正关上这条隐秘的数据泄露通道。