最近在做一些安全攻击的调研及演示,发现了一些公司业务存在ip伪造漏洞。导致该漏洞的主要原因是,使用X-Forwarded-For字段获取用户ip地址。
我们来看一下X-Forwarded-For的定义。
X-Forwarded-For简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。它不是RFC中定义的标准请求头信息,在squid缓存代理服务器开发文档中可以找到该项的详细介绍。标准格式如下:X-Forwarded-For: client1, proxy1, proxy2。
重点看这句话“它不是RFC中定义的标准请求头信息”,也就是说,这个字段并不是官方定义的用来获取客户端真实IP。
在一次直接的网络请求中,是没有X-Forwarded-For这个字段的,只有代理、负载均衡时,才会添加该字段。大概示意图如下:
从图中可以看出,代理机(也可以是负载均衡)会在请求中转时,添加X-Forwarded-For这个参数,确保服务器知道最初来源客户端。如果中间有多个网络跳转,即先是代理机A,然后代理机B,再次代理机C,最终到达服务器,具体流程如下:
1. 客户端访问代理机A,代理机A得到用户真实IP。
2. 代理机A将请求发给代理机B,此时请求header中X-Forwarded-For字段为:客户端IP。
3. 代理机B得到代理机A真实IP,将此追加到X-Forwarded-For中。
4. 代理机B将请求发给代理机C,此时请求header中X-Forwarded-For字段为:客户端IP,代理机A IP。
5. 代理机C得到代理机B真实IP,将此追加到X-Forwarded-For中。
6. 代理机C将请求发给服务器,此时请求header中X-Forwarded-For字段为:客户端IP,代理机A IP,代理机B IP。
7. 经过代理机C后,请求的去向不确定,不过最终会到达服务器,服务器获取到的X-Forwarded-For字段就是:客户端 IP,代理机A IP,代理机B IP,代理机C IP。
X-Forwarded-For伪造IP攻击,攻击者发起请求时,客户端请求中添加X-Forwarded-For字段充当代理机,恶意伪造最初来源ip,进而达到攻击目的。
鉴于伪造这一字段非常容易,应该谨慎使用X-Forwarded-For字段。
那么什么才是正确的获取真实IP方式呢?其实每个语言都有提供获取真实IP的方法,比如php通过获取REMOTE_ADDR即可知道真实IP。但是这个IP是发起请求方的ip,如果客户端调用代理,代理再调用服务器,服务器得到的只能是代理ip。
不难理解,很多企业用X-Forwarded-For字段获取用户ip,是因为服务器前面架设了一层负载均衡,服务器不能直接获取客户端IP地址,REMOTE_ADDR字段返回的是负载均衡的ip。
REMOTE_ADDR字段是绝对可靠的,不可修改的,因为服务器返回数据,会返回给REMOTE_ADDR这个ip。一旦这个ip被客户端伪造,服务器是无法返回给这个客户端的,所以保证了绝对的安全。我们在开发中,也要使用REMOTE_ADDR来获取真实IP,及时服务器做了负载,我们可以先让负载机得到真实ip,再通过其它手段将此值传给服务器。
最后回归正题,我们在测试网站的时候,怎么模拟header伪造X-Forwarded-For发起请求呢?
以前的做法是,架设一台代理机,代理机写代码,实现这个伪造。浏览器只要连接到这个代理机,发送的所有http请求,请求中的header都会被脚本修改。
今天发现了一个工具,很是好用,再也不用维护一个代理脚本了。是在chrome上面找到的,插件名字叫做modheader。
可以实时添加修改header,不仅可以修改request,也可以修改response。
Leave a Reply