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

相关推荐
sdszoe49223 小时前
华为无线网络技术基础
网络·智能路由器·wlan·无线局域网
情深不寿3173 小时前
传输层————TCP
linux·网络·c++·tcp/ip
christine-rr3 小时前
【25软考网工】第五章(10) Internet应用
linux·网络·经验分享·笔记·软考
Sunhen_Qiletian4 小时前
从传统CNN到ResNet:深度学习中的深层网络革命
网络·深度学习·cnn
宇宙超超级无敌暴龙战士8 小时前
红队渗透实战
网络·渗透
weixin_4196583110 小时前
HTTP协议介绍
网络·网络协议·http
Suckerbin10 小时前
Clover: 1靶场渗透
笔记·安全·web安全·网络安全
沉迷技术逻辑10 小时前
Redis-实现分布式锁
数据库·redis·缓存
盟接之桥10 小时前
盟接之桥EDI软件:中国制造全球化进程中的连接挑战与路径探索
大数据·网络·人工智能·安全·制造