HTTP学习之路:代理中的缓存投毒

代理转发请求过程中有个很常用的头,叫做X-Forward-Host,会让攻击者恶意利用进行缓存投毒。

一.问题背景

在一个典型的Web架构中,用户访问公网域名 www.example.com,流量首先到达部署在公网的负载均衡器。负载均衡器负责将请求分发到内网多台应用服务器(如 192.168.1.20 )中的某一台,以实现高可用和扩展性。

核心矛盾点:

  1. 虚拟主机依赖: 一台内网应用服务器通常通过虚拟主机技术托管数十个网站,它完全依赖HTTP请求头中的 Host 字段来判断用户想访问哪个具体网站。

  2. 内外网寻址差异: 公网域名 www.example.com 在内部网络可能无法解析或解析到错误地址,导致负载均衡器的转发请求失败。

二、 核心挑战

如果负载均衡器将原始请求(Host: www.example.com)直接转发给内网服务器 192.168.1.20(app-server-1.internal),会导致两个问题:

  1. 路由错误: 请求发往 www.example.com 而非目标服务器的内网IP,可能在内网中路由失败。

  2. 网站识别错误: 应用服务器 192.168.1.20 收到 Host: www.example.com 的请求后,会试图寻找自身配置中名为 www.example.com 的站点。如果找不到,将返回错误或默认页面,而非用户想要的网站。

三、 解决方案

负载均衡器在转发请求时,执行以下两个关键操作:

  1. (1)修改目标地址与Host头(用于正确路由)

  2. 将请求的目标地址改为应用服务器的内网IP或内部域名(如 app-server-1.internal)。

  3. 目的:确保请求能在内网环境中被准确路由到目标机器,并被其接受。

  4. (2)添加X-Forwarded-Host头(用于保留原始信息)

  5. 在修改Host头之前,将原始的 Host 值(www.example.com)存入一个名为 X-Forwarded-Host 的自定义HTTP头中。

  6. 目的:无损地传递用户的原始访问意图,供后端应用服务器识别。

转发前后的请求头变化:

  • 用户 -> 负载均衡器的请求头:

  • 负载均衡器 -> 应用服务器 的请求头:

四、 后端应用服务器的配合

应用服务器(如Nginx、Apache)必须被配置为能够识别和处理 X-Forwarded-Host 头。

五、 安全风险

上述方案引入了一个关键的安全依赖:后端服务器必须无条件信任由负载均衡器设置的 X-Forwarded-Host 等头。如果配置不当,攻击者可以伪造这些头信息,进行缓存投毒攻击。


攻击过程如下:

第1步:攻击者发送恶意请求

攻击者直接向负载均衡器发送一个精心构造 HTTP请求。他手动添加了 X-Forwarded-Host 头,试图覆盖其值。

攻击者 -> 负载均衡器:

请注意: 攻击者完全可以在自己的客户端(如Burp Suite)中轻松地设置任何HTTP头。

第2步:负载均衡器处理并转发请求

负载均衡器收到此请求,按照既定规则进行处理:

  1. 它看到 Host: www.example.com,将其改写为 Host: 192.168.1.20

  2. 它看到请求中已经有一个 X-Forwarded-Host 头。负载均衡器的常见行为是:要么追加一个值,要么直接覆盖它。在很多默认配置下,它可能会信任并保留客户端传来的这个头,或者在其后追加自己的值(如 X-Forwarded-Host: evil.com, www.example.com),这取决于具体配置。最危险的情况就是它直接原样转发。

我们假设一个不安全的配置,负载均衡器简单地转发了客户端提供的头:

负载均衡器 -> 后端服务器 (192.168.1.20):

第3步:后端服务器生成恶意响应

后端服务器 192.168.1.20 收到请求。它的应用逻辑运行:

  1. 它发现了 HTTP_X_FORWARDED_HOST 存在,其值为 evil.com

  2. 它完全信任这个值,并用它来生成页面内容。

后端服务器 -> 负载均衡器: 返回包含了指向攻击者控制域名 evil.com 的脚本。

第4步:缓存服务器存储恶意响应(投毒)

负载均衡器/缓存服务器收到后端返回的这个响应。

  1. 生成缓存键 :它的缓存键规则是 Host + URL。它看的是最初收到的请求中的 Host 头,即 www.example.com,加上路径 /index.html。所以缓存键是www.example.com/index.html

  2. 决定缓存 :它看到响应头中有 Cache-Control: public, max-age=3600,于是决定缓存此响应。

  3. 执行存储 :它将这个恶意响应,存储到了 www.example.com/index.html 这个缓存键下。

第5步:无辜用户访问中毒的缓存

此后一小时内,任何普通用户访问 https://www.example.com/index.html

  1. 他们的请求 GET /index.html HTTP/1.1 Host: www.example.com 到达负载均衡器。

  2. 负载均衡器生成缓存键 www.example.com/index.html,立即命中第4步中存储的恶意缓存。

  3. 负载均衡器不再向后端请求,直接将该恶意响应返回给用户。

  4. 用户的浏览器解析HTML,向 evil.com 请求并执行那个恶意的 app.js 脚本。攻击者成功窃取用户cookie或其他敏感信息。

解决办法:

防御策略1:严格校验与过滤HTTP头

漏洞代码示例(javascript):

防御策略2:谨慎设置缓存响应头

对包含用户动态内容的页面,正确设置 Cache-Control头,避免其被公共缓存。

防御策略3:配置缓存键(Cache Key)

默认的缓存键可能只包含 req.urlreq.http.Host。我们需要修改它,将可能影响响应内容的头(如 X-Forwarded-Host)加入缓存键。这样配置后,一个带有 X-Forwarded-Host: evil.com 的请求和正常的请求,会因为缓存键不同而被区别对待,无法污染公共缓存。

相关推荐
清@尘3 分钟前
威联通NAS双网卡双倍速度聚合+SMB多通道设置的方法
网络·nas·威联通
init_236119 分钟前
Option B(MP-EBGP跨AS VRF)设备配置及ASBR标签转发原理
运维·服务器·网络
CJH(本人账号)34 分钟前
从快手“12·22”直播攻击事件看:一次教科书式的业务层饱和攻击
网络·安全
Xの哲學35 分钟前
Linux IPsec 深度解析: 架构, 原理与实战指南
linux·服务器·网络·算法·边缘计算
老王熬夜敲代码37 分钟前
TCP相关问题的解决
linux·网络·笔记·网络协议
工程师华哥40 分钟前
【网工技术实验】华为S5700交换机堆叠配置实验案例
服务器·网络·华为
记得记得就1511 小时前
Docker核心功能全解析:网络、资源控制、数据卷
网络·docker·容器
wheeldown1 小时前
【Linux网络编程】网络基础之MAC地址与IP地址的区别
linux·运维·网络·macos
辉视广播对讲1 小时前
SIP广播对讲系统:引领未来IP广播的主流方向
网络·网络协议·tcp/ip
松涛和鸣1 小时前
DAY37 Getting Started with UDP Network Programming
linux·c语言·网络·单片机·网络协议·udp