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 的请求和正常的请求,会因为缓存键不同而被区别对待,无法污染公共缓存。

相关推荐
枷锁—sha17 分钟前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全
郝学胜-神的一滴24 分钟前
深入解析C/S模型下的TCP通信流程:从握手到挥手的技术之旅
linux·服务器·c语言·网络·网络协议·tcp/ip
池央29 分钟前
CANN 算子诊断与故障定位:oam-tools 在异构计算错误解析中的作用
网络
“αβ”32 分钟前
数据链路层协议 -- 以太网协议与ARP协议
服务器·网络·网络协议·以太网·数据链路层·arp·mac地址
释怀不想释怀38 分钟前
Linux网络基础(ip,域名)
linux·网络·tcp/ip
开开心心就好1 小时前
AI人声伴奏分离工具,离线提取伴奏K歌用
java·linux·开发语言·网络·人工智能·电脑·blender
啦啦啦_99991 小时前
Redis-2-queryFormat()方法
数据库·redis·缓存
子榆.1 小时前
CANN 性能分析与调优实战:使用 msprof 定位瓶颈,榨干硬件每一分算力
大数据·网络·人工智能
驱动探索者1 小时前
U盘发展史
网络·cpu·u盘
青春给了代码1 小时前
基于WebSocket实现在线语音(实时+保存)+文字双向传输完整实现
网络·websocket·网络协议