CDN缓存投毒是什么?缓存键与Host头防护
本内容发表于:2026-08-10 14:51:04
浏览量
1005

微信图片_2026-08-10_144935_788.png

CDN 缓存投毒是指攻击者利用“响应会受到某个请求输入影响,但该输入没有正确进入缓存键或没有经过安全处理”的差异,让异常响应被 CDN 缓存,随后分发给其他正常用户。风险不只来自查询参数,也可能来自 Host 相关请求头、转发头、Cookie、协议判断、路径规范化或源站自动生成绝对 URL 的逻辑。

防护的核心原则很简单:凡是能够改变响应内容、状态码或关键响应头的请求输入,都必须被纳入缓存键、在进入应用前规范化或拒绝,或者让对应响应不被共享缓存。只增加更多缓存键字段并不总是正确,因为字段过多会降低命中率并扩大缓存变体数量;真正需要的是让缓存策略与源站实际变化逻辑一致。

本文配置与资料核查日期为 2026 年 8 月 10 日。示例用于防御性检查,不包含可直接用于攻击生产网站的载荷。CloudFront、AWS WAF 与其他服务能力可能调整,实际配置以当前官方文档和控制台为准。

CDN 缓存投毒需要哪些条件?

一次可持续影响其他用户的缓存投毒,通常同时满足以下条件:

  1. 请求中存在攻击者能够控制的输入。

  2. 源站或边缘代码使用该输入改变了响应。

  3. 该输入没有进入缓存键,或在不同组件中被不一致地规范化。

  4. 响应满足 CDN 的缓存条件。

  5. 后续正常请求命中了同一个缓存对象。

如果输入被安全忽略,风险不会成立;如果响应从不进入共享缓存,影响通常只限于单次请求;如果输入完整进入缓存键,攻击者更可能只创建自己的缓存变体,而不是覆盖普通用户使用的对象。因此,排查重点是源站的响应变化维度与 CDN 的缓存区分维度是否一致

缓存键到底包含什么?

缓存键是 CDN 用来判断两个请求能否共用同一份缓存响应的标识。按照 HTTP 缓存规范,主要缓存键至少由请求方法和目标 URI 组成;CDN 还可以根据配置加入查询参数、请求头和 Cookie。

CloudFront 的缓存策略用于控制哪些查询字符串、请求头和 Cookie 进入缓存键,同时也决定其中哪些值会转发到源站。Origin request policy 可以额外向源站转发某些值,但不把它们加入缓存键。这个能力很有用,却也是配置不一致的高风险位置:

高风险组合:某个请求头、Cookie 或查询参数被转发到源站,并会改变源站响应,但没有进入缓存键。此时不同输入可能共用同一缓存对象。
输入是否影响源站响应推荐处理
纯跟踪参数不影响页面内容从缓存键和回源请求中移除,或在边缘统一删除
语言、设备或格式参数确实返回不同内容纳入缓存键,并限制允许值
登录态或用户 Cookie返回私人内容通常不使用共享缓存,或采用经过验证的私有缓存设计
未经信任的转发头可能改变跳转、脚本或绝对 URL删除、覆盖或严格校验,不直接信任
仅供源站记录的诊断头不改变响应可以只转发,但需要持续验证该假设

Host 头为什么是重点风险?

应用经常根据 Host 或类似的转发主机头生成规范链接、密码重置链接、跳转地址、静态资源 URL 和安全策略。如果应用接受任意主机名,并把它反射到可缓存响应中,就可能让异常域名进入缓存页面或响应头。

多层代理还会带来更多“主机来源”:原始 HostX-Forwarded-Host、CDN 注入的主机信息以及源站框架自己识别的外部 URL。不同层若选择了不同字段,安全团队看到的配置与应用实际使用的值可能并不一致。

Host 相关防护建议

  1. 建立主机名允许列表:在最靠近入口的位置只接受已经绑定并验证的业务域名,未知 Host 直接拒绝。

  2. 不要从用户输入生成安全敏感链接:规范域名、重置链接和回调地址优先使用服务器端固定配置。

  3. 清理转发主机头:如果业务不需要 X-Forwarded-Host 等字段,就不要转发;需要时由受信任代理覆盖,而不是保留访问者提交值。

  4. 隔离不同信任边界:后台、客户自定义域名和公共站点若逻辑差异明显,应使用独立行为、源站甚至独立分配。

  5. 检查错误页和跳转:异常 Host 不应被写入可缓存的 3xx、4xx 页面或 Location 响应头。

不要把“把 Host 加入缓存键”当作唯一补救。它可能让攻击输入生成大量缓存变体,而且无法解决恶意链接被返回给单个用户的问题。优先方案仍是拒绝未知主机并使用可信的规范域名。

查询参数应该全部缓存、全部忽略,还是使用允许列表?

查询参数是最常见的缓存策略分歧来源。三种做法各有边界:

策略适用场景主要风险
全部忽略所有参数都不改变响应源站若实际使用某个参数生成内容,多个版本会错误共用缓存
全部加入缓存键参数集合受控且每项都确实产生变体参数顺序、垃圾参数和高基数值会降低命中率并放大缓存
允许列表只有少数已知参数影响内容新增业务参数后忘记同步缓存策略

多数网站更适合使用允许列表:只把语言、图片格式、分页或其他明确影响内容的参数加入缓存键;广告跟踪参数应在边缘删除,或确保源站完全不使用它们生成响应。

参数顺序与重复参数也要测试

AWS 文档指出,CloudFront 会根据查询字符串的名称和值缓存对象,参数顺序不同可能形成不同缓存对象。源站框架对重复参数、大小写、空值和编码形式的解释也可能不同。应统一参数顺序和编码,限制参数名称和值,并避免让 CDN、WAF 与应用分别使用不一致的解析规则。

请求头应该怎样进入 CloudFront 缓存策略?

请求头不是越多越安全。把所有访问者请求头加入缓存键会显著降低缓存命中率,因为浏览器版本、追踪标识和临时头会产生大量变体。更稳妥的方式是按响应差异建立最小允许列表。

  • Accept-Encoding应使用 CloudFront 缓存策略提供的压缩支持,不要自行创建含义重叠的变体。

  • Origin如果跨域响应会按来源变化,应让缓存与 CORS 策略一致;若只允许固定来源,也应在边缘或源站校验。

  • 设备或语言头:只有在源站确实返回不同对象时才入键,并优先归一化为少量类别。

  • 转发与重写头:不要直接信任访问者提交的 X-Forwarded-* 值;由可信代理生成或覆盖。

  • 调试头:调试模式不应通过公开请求头改变可缓存页面,生产环境应关闭或要求强认证。

Vary 响应头可以表达响应根据哪些请求头变化,但在 CDN 场景中仍必须确认产品的缓存策略和实际行为。不能只在源站添加 Vary,就假设所有边缘缓存一定按预期区分对象。

路径规范化为什么也会造成缓存差异?

缓存键安全不仅涉及头和参数。CDN、负载均衡器、Web 服务器和应用框架可能以不同方式处理重复斜杠、点路径、大小写、百分号编码和尾部斜杠。如果 CDN 认为两个路径相同,而源站认为不同,或反过来,就会形成缓存混淆。

建议在一个明确层级完成路径规范化,并确保后续组件不再以不同规则二次解释。对不符合规范的路径,返回不可缓存的 4xx 往往比自动进行多次隐式重写更容易审计。

哪些响应不应该进入共享缓存?

  • 包含用户姓名、账户信息、订单或授权结果的页面。

  • 依赖登录 Cookie、Authorization 或会话状态生成的响应。

  • 密码重置、邮箱验证、支付回调等安全敏感流程。

  • 调试信息、堆栈错误和内部诊断页面。

  • 根据未经规范化输入生成的重定向或错误页面。

此类响应应通过正确的 Cache-Control、CloudFront 缓存行为和应用设计避免进入共享缓存。不要只依靠前端 JavaScript 隐藏敏感内容,因为 CDN 缓存的是实际 HTTP 响应。

CloudFront 配置的防护步骤

  1. 按路径盘点响应变化:记录每个 Cache Behavior 中哪些参数、请求头和 Cookie 会改变内容。

  2. 选择或创建 Cache Policy:只把必要输入加入缓存键,并为高基数值做归一化。

  3. 审查 Origin Request Policy:找出“转发但未入键”的输入,逐项确认它们绝不会改变响应。

  4. 固定可信 Host:只接受已绑定域名,并清理访问者可伪造的主机转发头。

  5. 限制可缓存状态与 TTL:错误页、跳转和动态页面使用符合风险的缓存时间。

  6. 在 AWS WAF 中建立输入约束:对不应出现的头、异常参数和非法主机名进行阻止或计数观察。

  7. 减少边缘代码差异:CloudFront Functions 或 Lambda@Edge 若修改 URI、头或响应,应与缓存键处理顺序一起审核。

  8. 记录配置版本:缓存策略、源请求策略、WAF 和边缘函数应纳入变更记录与回滚流程。

最实用的审查问题是:如果去掉某个缓存键字段,源站是否仍可能返回不同响应?如果答案是“可能”,就需要纳入缓存键、规范化输入或禁止共享缓存。

如何安全验证是否存在缓存投毒风险?

验证应在测试环境、预发布域名或获得明确授权的生产窗口中进行。不要在公共生产缓存中尝试危险输入。一个低风险验证流程是:

  1. 使用不会被其他用户访问的测试路径或随机对象名。

  2. 为测试请求加入无害、可识别的标记值。

  3. 分别改变一个查询参数、请求头或 Cookie,观察响应是否变化。

  4. 使用新的无标记请求检查是否收到前一次响应的标记。

  5. 检查 Age、缓存结果头、请求 ID 与访问日志,确认对象是否来自缓存。

  6. 在不同边缘位置重复验证,避免把单个节点结果误认为全局结果。

  7. 测试结束后清除测试对象,并恢复临时配置。

不能只凭一次 HIT 或响应中出现某个值就下结论。需要同时证明该值由可控输入产生、输入未被缓存键区分,并且无该输入的后续请求会命中受影响响应。

应该监控哪些异常信号?

  • 同一路径突然出现大量不同查询参数或 Cookie 组合。

  • 未知 Host、转发主机头或异常协议头增加。

  • 缓存命中率突然下降,同时对象数量或回源请求增加。

  • 正常页面出现陌生域名、异常重定向或不一致的安全响应头。

  • 相同缓存键在不同时间返回明显不同的内容摘要。

  • 错误响应被长时间缓存,且影响多个地区。

  • WAF 计数规则与 CloudFront 日志中的异常输入同步上升。

日志中可能包含 Cookie、查询字符串和客户端信息,应执行最小化采集、访问控制与合理保留期限。为了安全分析而无限期保存所有原始请求,同样会带来隐私和合规风险。

发现疑似缓存投毒后怎么处理?

  1. 先阻断输入:在 CDN、WAF 或源站拒绝导致响应变化的异常输入。

  2. 暂停受影响路径缓存:在原因未修复前缩短 TTL 或暂时绕过共享缓存。

  3. 修复缓存键或应用逻辑:不要只清缓存,否则相同输入可能再次污染。

  4. 执行精准失效:修复生效后清除受影响路径;只有无法确定范围时才扩大失效范围。

  5. 检查多层缓存:浏览器、反向代理、CloudFront 和源站应用缓存可能各自保留对象。

  6. 复核传播范围:按边缘位置、时间窗口、Host 和路径分析日志。

  7. 更换受影响数据:若响应泄露令牌、链接或敏感内容,应按事件响应流程撤销和轮换。

顺序很重要:先修入口和逻辑,再清除缓存。如果先执行失效而攻击路径仍存在,新的异常响应可能马上重新进入缓存。

常见误区

把所有请求字段都加入缓存键

这会制造大量低命中缓存变体,并可能被滥用为缓存容量消耗。缓存键应保持最小但完整,而不是无限扩张。

认为使用 HTTPS 就不会发生缓存投毒

HTTPS 保护传输过程,不会自动修复 CDN 与源站对缓存键、请求头和响应变化理解不一致的问题。

只配置 WAF,不修复源站

WAF 可以减少已知异常输入,但无法覆盖所有业务语义。源站仍应拒绝未知 Host、避免反射不可信值,并正确标记私人响应。

发现问题后只执行全站清缓存

全站失效会降低命中率并增加源站压力,而且无法阻止再次污染。应先修复根因,再按已确认范围清理。

常见问题

CDN 缓存投毒和浏览器缓存投毒一样吗?

不完全一样。CDN 是共享缓存,一个异常对象可能影响大量用户;浏览器缓存通常只影响单个客户端。实际链路中两者也可能同时存在。

忽略所有查询参数最安全吗?

不是。如果源站会根据某个参数返回不同内容,而 CDN 忽略该参数,不同响应就可能错误共用缓存。应根据真实业务逻辑使用允许列表。

把所有查询参数加入缓存键能彻底解决问题吗?

不能。风险还可能来自请求头、Cookie、路径规范化和边缘代码,而且过多参数会导致缓存碎片和资源消耗。

CloudFront 的托管缓存策略可以直接使用吗?

可以作为起点,但仍要确认它是否匹配源站。关键不在于策略由谁创建,而在于所有会改变响应的输入是否得到一致处理。

需要缓存动态页面时怎么办?

先把页面划分为真正公共的变体,明确语言、设备或地区等有限维度;用户身份、授权和私人数据不应混入共享响应。无法清楚定义公共变体时,优先不缓存。

结论

CDN 缓存投毒的根源,是缓存层与源站对“哪些输入会改变响应”理解不一致。最可靠的防护不是机械增加规则,而是逐个 Cache Behavior 建立清晰契约:允许哪些 Host,哪些查询参数、请求头和 Cookie 会进入缓存键,哪些只允许回源,哪些响应绝不能共享缓存。

对 CloudFront,应重点审查 Cache Policy 与 Origin Request Policy 的组合,尤其是所有“转发到源站但未进入缓存键”的字段。再配合 Host 允许列表、参数归一化、WAF 约束、安全测试、日志监控和先修复后失效的应急流程,才能在保持缓存命中率的同时降低投毒风险。

CloudFlew 提供基于 CloudFront 的 CDN 服务。调整缓存策略前,可以先整理业务中实际影响响应的参数、请求头、Cookie 和域名,再以最小且完整的缓存键完成配置。

参考资料

  1. AWS CloudFront 开发者指南:Understand the cache key,核查日期:2026-08-10

  2. AWS CloudFront 开发者指南:Control the cache key with a policy,核查日期:2026-08-10

  3. AWS CloudFront 开发者指南:Cache content based on query string parameters,核查日期:2026-08-10

  4. AWS CloudFront 开发者指南:Cache content based on request headers,核查日期:2026-08-10

  5. AWS WAF 开发者指南:Request component options,核查日期:2026-08-10

  6. IETF RFC 9111:HTTP Caching,核查日期:2026-08-10

  7. PortSwigger Web Security Academy:Web cache poisoning,核查日期:2026-08-10