模式 1:X-forward-For
这是最具认知性的IP 伪造方法,早年的 CTF 话题也经常涉及。不过,现在知道的人太多了,CTF 也懒得提这样的话题。X-Forwarded-For 诞生的原因比较简单粗暴。对于一个非常简单的网络模型,一个网络请求通常只有两方,即请求方和被请求方,如下所示。在这种网络模型下,Web 服务器可以获得用户的真实 IP 地址,即使它可能获得路由器的地址。
User --> Web Server
但是在网站的规模上,它的网络模型不会这么简单,它可能看起来是这样的:
User --> CDN --> Web Server
在这种场景下,CDN 仍然可以获取用户的真实 IP 地址,但是 Web 服务器无法直接获取。为了解决这个问题,有人提出了 X-Forwarded-For,作为 HTTP 头传递给后端 Web 服务器,其格式如下:
X-Forwarded-For: <client>, <proxy1>, <proxy2>
假设用户的真实 IP 地址是 1.0.0.1,CDN 节点的 IP 地址是 2.0.0.2,CDN 会在 HTTP 请求报头中附加以下报头,告知 Web 服务器用户的真实 IP 地址。Web 服务器根据这个头解析用户的 IP。
X-Forwarded-For: 1.0.0.1, 2.0.0.2
你可以直接把 1.0.0.1 改成任何 IP 地址,然后直接把请求发送到 Web 服务器?是的,这是一个非常简单的 X-Forwarded-For IP 伪造攻击。这类问题的解决方法一般是检查 4 层协议的源 IP,确定是否是可信 IP,比如 CDN 的 IP。如果可信,它将尝试解析 x-forwarded-for 标头。
模式 2:代理协议
X-Forwarded-For 只支持HTTP 协议,那么 TCP 或者其他四层协议呢?这时,代理协议就应运而生了。2010 年首次提出,首次应用于 HAProxy。由于代理协议解决了实际应用中的痛点,越来越多的开源软件(如 NGINX)和 CDN 厂商(如 Cloudflare 和 Cloudfront)已经支持代理协议。
目前代理协议有两个版本,分别是 v1 和 v2。
代理协议 v1 协议非常简单易懂。因为这篇文章只是一个介绍,所以我不会写太多的技术细节,尽量用最简单的文字让读者了解它是如何工作的。假设网络模型如下:
User --> Load Balancer --> TCP Server
V1 的原理也很简单。当用户与负载均衡器(可能是 TCP 或 UDP)建立四层链路时,负载均衡器就知道了用户的真实 IP。与 TCP 服务器建立四层链接后,负载均衡器不会直接发送用户的请求,而是提前发送一个代理协议 V1 的报头。这个标题看起来像这样
PROXY TCP4 1.0.0.1 2.0.0.2 1001 2002\r\n
其中包括:
TCP4 表示用户使用 TCP v4 与负载平衡器建立 4 层链接。
1.0.0.1 是用户的 IP,2.0.0.2 是目标 IP。
1001 是用户端口,2002 是目标端口。
当 V1 报头被发送到 TCP 服务器时,负载平衡器将开始透明地传输 TCP 请求。但是 TCP Server 需要做一些调整,解析头部后,会启动业务逻辑。幸运的是,许多服务器,包括 NGINX,已经支持解析 V1 报头,所以只需改变配置。
同样,代理协议也存在 IP 伪造的问题。攻击者可以直接构造一个 V1 头并发送给 TCP 服务器,这样会造成 TCP 源 IP 地址伪造的问题。
代理协议的 V2 版本实际上是 V1 版本的升级优化。V1 版本是一个纯文本协议,它最大的缺点是报头占用了太多的字节,比如上例中的 38 字节。但是,表头是给机器看的,不是给人看的。有那么好读有用吗?因此,V2 实际上将 V1 升级为二进制版本。它的结构相对不太直观。以 IPv4 版本为例,其格式如下:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| Proxy Protocol v2 Signature |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|Command| AF | Proto.| Address Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IPv4 Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IPv4 Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
在 IPv4 版本中,V2 报头只占 28 个字节,比 v1 版本少了 10 个字节左右(这里注意“大约”,V1 版本更长)。
代理协议 V2 本质上只是改变了报头的编码方式,仍然存在 IP 地址伪造的问题。
模式 3: TOA (TCP 选项地址)
与前两个协议相比,TOA 的受欢迎程度并没有那么高。TOA 的原理是使用 TCP 协议中一个未使用的字段。在讲述原理之前,先回顾一下 TCP 报头的格式:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
可以看到,TCP 报头中有一个名为 Options 的段。TOA 正在使用此选项。负载均衡器收到用户请求后,会将用户的 IP 信息插入 Options,其格式如下:
struct toa_data { __u8 opcode; __u8 opsize; __u16 port; __u32 ip;};
TOA 最大的好处是没有改变协议,不会有兼容性问题。比如 TCP 服务器不支持 TOA 协议,仍然可以正常工作,但是无法获取真实的用户 IP 信息。
TOA 或代理协议,它们的本质是负载均衡器主动向 TCP 服务器传输用户 IP 信息。所以 TOA 协议也存在 IP 伪造的问题。在与 TCP 服务器建立连接的阶段,可以在选项中插入伪造的 IP 地址。
结语:
在现实世界中,伪造源 IP 的技术肯定更多,而这种 IP 伪造问题的根源也是类似的,即后端服务无条件信任他人传输的 IP 信息。解决方法说起来也简单,就是判断最后一个 IP 是否可信,如果不在可信列表中,就停止解析这些 IP 信息。详情请阅读 Gin 框架的代码。
转载请注明:汇站网 » IP 伪造思路(网络技术)