动态页面加上 .css 就被 CDN 缓存?排查 Web Cache Deception 与路径规则错配
本内容发表于:2026-11-04 09:32:43
浏览量
1049

私人资料卡片伪装成静态文件接近 CDN 缓存,入口盾牌阻止其进入共享缓存。

个人资料页面本来不该进入共享缓存,但当地址后面多出一段看似静态文件的路径时,源站仍返回同一份登录态内容,CDN 却把它当成可缓存资源。这是 Web Cache Deception(Web 缓存欺骗)需要关注的典型条件:两层对路径用途的判断不同,最终让私人响应被错误存入共享缓存。[1]

本文面向维护自有网站的开发与运维人员。以下检查只应在授权的预发布环境、测试账号和虚构数据上进行,未在你的生产环境实测。不要邀请真实用户打开可疑链接,也不要读取或复制其他账号的信息来证明风险。

它与普通缓存配置错误有什么不同

普通缓存错误可能直接把登录后的 /account 页面缓存。缓存欺骗则利用一条看起来符合静态资源规则、实际上仍被动态路由处理的地址,让原本没有进入缓存的私人响应获得缓存资格。

例如,应用把附加路径忽略,仍按账户页返回内容;边缘却仅凭末尾扩展名判断为样式资源。目录映射、路径分隔符以及规范化规则的差异,也可能造成类似错配。[1] 不是给任何地址加上 .css 都会成功,需要同时检查源站路由、边缘规则与缓存键。

不要把它和 Web Cache Poisoning 混为一谈。后者通常关注把攻击者可控的响应内容放进缓存,缓存欺骗则关注诱使私人响应进入不该共享的缓存。两者可能共享某些薄弱配置,但排查目标不同。

先检查源站对异常路径的实际处理

在预发布环境中建立只包含固定测试标记的账户页面。比较规范路径和不应存在的附加路径:是否都返回 200、是否出现相同的账号标记、是否有重定向,以及是否经过同一个动态处理器。

后端框架、反向代理和 SPA 回退规则可能对未知路径采取不同策略。不能因为前端页面看起来相同,就断言响应来自相同路由;应结合应用日志确认实际匹配结果。

对账号、账单、订单等端点,意外路径不应悄悄继承私人页面的响应语义。可根据业务返回明确的未找到或规范化跳转,但要评估既有链接、语言路径和客户端路由兼容性。不要为修复这一问题直接关闭整站前端路由。

找出是谁授予了缓存资格

导出当前 CDN 缓存规则,检查扩展名匹配、路径前缀、全站缓存、边缘脚本和源站 Cache-Control 覆盖设置。确认它们的执行顺序,而不是只看管理界面中某一条“绕过缓存”规则。

仅凭 .css、.js 或图片后缀授予缓存资格,对混合动态路由站点风险较大。使用只承载静态文件的独立目录或域名,配合明确的路由边界,通常更容易审计;但域名独立本身不保证内容安全,仍需检查 Cookie 作用域、源站映射与响应策略。

缓存键是否包含 Cookie,与响应是否允许共享,是两个问题。把全部 Cookie 放进缓存键可能造成大量变体,也不能代替禁止存储敏感响应。攻击者能否在无认证状态取得相同缓存对象,取决于具体键设计与授权流程,不能凭一次命中推断全部用户都受影响。

私人响应需要明确的缓存策略

按 HTTP 缓存规范,private 限制共享缓存存储,no-store 要求缓存不存储该响应;no-cache 并不等于不保存,而是要求复用前进行验证。[3] 对确实不应保存的私人数据,可采用经过业务验证的策略,例如:

Cache-Control: private, no-store

这个示例不是要求所有动态响应一律关闭缓存。公开且与用户无关的数据可以有单独的缓存策略,关键是先完成数据分类,再决定是否允许共享。

还要确认边缘产品是否被配置为忽略或覆盖源站指令。应用加了 no-store,不代表一条强制缓存规则不会改变实际行为。Set-Cookie 的存在也不能被当作跨产品通用的“不缓存保证”;应查当前服务的具体规则。

Vary: Cookie 不是敏感数据的通用补丁。它可以表达响应随 Cookie 变化,但支持情况、变体数量和边缘配置都需要核对。错误的共享缓存不应靠不断增加变体来维持。

在授权测试中验证是否真的发生跨会话复用

使用两个彼此隔离的测试会话。会话 A 登录测试账号,请求一个由自己控制、不会与正常流量共用的预发布路径;会话 B 不携带 A 的 Cookie 或 Authorization 请求同一路径。只使用虚构标记,不放真实姓名、账单或令牌。

观察响应内容、状态、缓存相关响应头及边缘日志,判断 B 是否取得 A 的标记。单独看到 Age 或供应商的命中头不能证明私人信息已泄露,也不能保证响应一定安全:多层代理可能添加或覆盖这些字段。

反过来,带 Cookie 的 curl 请求与浏览器行为也不一定相同。务必确认测试工具没有自动共享会话、自动跟随到另一个页面,或把同一个本地响应误当成新的边缘响应。

不要盲目加一个随机查询参数就认为测试已隔离。某些缓存键忽略查询参数;应先确认测试路径和缓存键的实际映射,并在测试结束后定向清理。HAR、请求日志和响应体按敏感诊断材料管理,限制访问并在不需要时删除。

路径规范化要沿链路统一检查

CDN、WAF、负载均衡和应用可能在不同阶段解码或规范化路径。应核对原始请求目标、边缘匹配时使用的路径和源站实际收到的路径。日志中的路径也可能已经处理过,不能拿它当作原始字节的完整证据。

不要用一条全局解码或重写规则仓促“统一”所有路径。重复解码、错误合并分隔符或修改编码形式,可能影响签名校验、路由与访问控制。先在受控样本上比较行为,再按特定端点最小范围修复。

安全产品提供的缓存欺骗防护可以增加一道检查。例如 Cloudflare Cache Deception Armor 会检查扩展名与响应 Content-Type 等是否符合其缓存安全判断。[2] 具体例外和覆盖范围以文档为准,它不能代替正确路由和私人响应策略;也不能把其他 CDN 的相似名称功能当作完全等价。

已经缓存的内容不会因改规则自动消失

出现疑似泄露时,先阻止受影响私人端点继续进入共享缓存,并按响应流程保留必要的脱敏证据。修改源站缓存头或路由后,还需要确认已有边缘对象的处理方式。

根据实际缓存键、路径变体和分发范围进行定向失效。若无法确定泄露对象范围,应由事件负责人评估扩大清理范围的必要性以及回源压力,不要为了避免全站刷新而遗漏敏感对象。

缓存清理不能收回已经被下载的信息。如果响应里包含有效会话令牌或其他凭据,应评估撤销、轮换与用户通知;若只有个人数据,也应按实际事件范围执行隐私与安全处置,不能因为缓存已删就宣布没有影响。

修复验收要同时覆盖私人页面与正常静态资源

至少验证规范私人路径、异常附加路径、登录与未登录会话,以及正常的样式、脚本和图片。私人响应不应跨用户复用,合法静态资源也不应因为过宽绕过规则全部回源。

备份原规则、记录变更顺序,先在预发布和小范围流量中观察缓存命中率、源站负载、路由错误及敏感端点的存储行为。回滚不能简单恢复已知会泄露的规则;若新规则影响可用性,可先保持私人路径禁止缓存,再调整公开资源规则。

最终需要确认三个具体事实:源站如何解释路径、CDN 为什么认为可以缓存、另一会话是否可能复用私人响应。把这三处证据对齐,才能区分真正的缓存欺骗、普通配置错误和测试会话串用。

参考资料

资料核验日期:2026 年 11 月 4 日。供应商功能和规则优先级以当前文档及实际配置为准。

  1. PortSwigger:Web cache deception

  2. Cloudflare:Cache Deception Armor

  3. RFC 9111:HTTP Caching