伪造X-Forwarded-For绕过服务器IP地址过滤

admin 2024年9月23日01:47:48评论90 views字数 2581阅读8分36秒阅读模式

在正常的TCP/IP 通信中,是可以伪造数据包来源 IP 的,但这会让发送出去的数据包返回到伪造的IP上,无法实现正常的通信。

实现TCP/IP层级别的伪造很难,因为很难实现正常的TCP连接;但是在应用层协议HTTP上的实现较容易,通过伪造IP,能欺骗多数服务器应用程序实现通信。对于绕过服务器的IP地址过滤或者伪造来源IP特别有用,导致的后果就是非授权IP能访问服务器,甚至能钻服务器的漏洞。

这其中的关键就是伪造X-Forwarded-For。

一、X-Forwarded-For介绍

我们知道 HTTP 连接基于 TCP 连接,HTTP 协议中没有 IP 的概念,只能通过X-Forwarded-For来实现。

X-Forwarded-For位于HTTP协议的请求头, 是一个 HTTP 扩展头部。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入RFC 7239(Forwarded HTTP Extension)标准之中。

X-Forwarded-For 请求头格式非常简单:

X-Forwarded-For: client, proxy1, proxy2

可以看到,XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP。

如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0,那么按照 XFF 标准,服务端最终会收到以下信息:

X-Forwarded-For: IP0, IP1, IP2

Proxy3 直连服务器,它会给 XFF 追加 IP2,表示它是在帮 Proxy2 转发请求。列表中并没有 IP3,IP3 可以在服务端通过 Remote Address 字段获得。Remote Address来自 TCP 连接,表示与服务端建立 TCP 连接的设备 IP,在这个例子里就是 IP3。

Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求。不同语言获取Remote Address的方式不一样,例如Node.js 是req.connection.remoteAddress,原理都一样。

一般的客户端(例如:浏览器)在发送HTTP请求时,并不会设置X-Forwarded-For头,当请求在到达第一个代理服务器时,代理服务器会在请求字段中加上X-Forwarded-For这个字段,并将其值设置为客户端的IP地址,后面如果还有更多的代理服务器,会依次将Ip地址追加到X-Forwarded-For这个字段中,最终当请求到达了Web应用服务器,应用会通过获取X-Forwarded-For头取出最左边的IP地址,即为客户端的真实IP地址。

如果客户端在发起请求时,请求头上带上一个伪造的X-Forwarded-For,由于后续每层代理只会追加而不会覆盖,那么最终到达应用服务器时,最左边的IP地址就是客户端伪造的IP地址

这个利用方法可以绕过一些针对IP地址进行限制的应用,例如:投票等应用

一般在nginx中会进行如下的配置

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for

这种如果没有X-Forwarded-For消息头会添加消息头,如果存在该消息头则会在后面追加一个IP。

二、X-Forwarded-For伪造

下面就是一种常见的获取客户端真实IP的方式

public String getClientIp(HttpServletRequest request) {    String xff = request.getHeader("X-Forwarded-For");    if (xff == null) {        return request.getRemoteAddr();    } else {        return xff.contains(",") ? xff.split(",")[0] : xff;    }}

可以通过抓包的方式伪造X-Forwarded-For头,如下

伪造X-Forwarded-For绕过服务器IP地址过滤

三、修复方式

目前很多Web 应用(例如获取用户所在地区,基于 IP 做访问频率控制,禁止某些IP访问等等),为了获取用户真正的 IP,从 HTTP 请求头中获取 IP地址。这些情况下,必须确保获取到的IP地址是真实可靠的。

经过前面的分析和测试,

1.对于直接使用的 Web 应用,必须使用从TCP连接中得到的 Remote Address,才是用户真实的IP;

2.对于使用 nginx 反向代理服务器的Web应用,nginx必须使用Remote Address正确配置set Headers,后端服务器则使用nginx传过来的相应IP地址作为用户真实IP。

正确配置nginx的方式,就是在最外层的代理服务器强制设定X-Forwarded-For的值为REMOTE ADDRESS。配置如下

proxy_set_header X-Forwarded-For $remote_addr

在最外层Nginx(即直接对外提供服务的Nginx)使用$remote_addr代替上面的$proxy_add_x_forwarded_for,可以防止伪造X-Forwarded-For。$proxy_add_x_forwarded_for会在原有X-Forwarded-For上追加IP,这就相当于给了伪造X-Forwarded-For的机会。而$remote_addr是获取的是直接TCP连接的客户端IP,这个是无法伪造的,即使客户端伪造也会被覆盖掉,而不是追加。

其它一下相似的消息头,也可以尝试使用这些消息头进行绕过

X-Originating-IP: 127.0.0.1X-Remote-IP: 127.0.0.1X-Client-IP: 127.0.0.1X-Forwarded-For: 127.0.0.1X-Forwared-Host: 127.0.0.1X-Host: 127.0.0.1X-Custom-IP-Authorization: 127.0.0.1

原文始发于微信公众号(信安路漫漫):伪造X-Forwarded-For绕过服务器IP地址过滤

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月23日01:47:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   伪造X-Forwarded-For绕过服务器IP地址过滤https://cn-sec.com/archives/3131635.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息