使用HTTP_X_FORWARDED_FOR获取客户端IP的严重后果

在WEB开发中.我们可能都习惯使用下面的代码来获取客户端的IP地址:
 -----------------C#代码----------------------------------------------------------------------
//优先取得代理IP 
string IP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; 
if (string.IsNullOrEmpty(IP)) {
 
//没有代理IP则直接取连接客户端IP 
 IP = Request.ServerVariables["REMOTE_ADDR"]; 
}
 

-----------------------------------------------------------------------------------------------

上面代码看来起是正常的.可惜这里却隐藏了一个隐患!!因为"HTTP_X_FORWARDED_FOR"这个值是通过获取HTTP头的"X_FORWARDED_FOR"属性取得.所以这里就提供给恶意破坏者一个办法:可以伪造IP地址!!

下面是测试代码:
--------------C#代码---------------------------------------------------------------------------
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://localhost/ip.aspx"); 
request.Headers.Add(
"X_FORWARDED_FOR""0.0.0.0"); 
HttpWebResponse response 
= (HttpWebResponse)request.GetResponse(); 
StreamReader stream 
= new StreamReader(response.GetResponseStream()); 
string IP = stream.ReadToEnd(); 
stream.Close(); 
response.Close(); 
request 
= null

-----------------------------------------------------------------------------------------------
"ip.aspx"文件代码:
------------C#代码-----------------------------------------------------------------------------
Response.Clear(); 
//优先取得代理IP 
string IP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; 
if (string.IsNullOrEmpty(IP))

  
//没有代理IP则直接取客户端IP 
  IP = Request.ServerVariables["REMOTE_ADDR"]; 
}
 
Response.Write(IP); 
Response.End(); 

------------------------------------------------------------------------------------------------
这样.当测试代码中去访问ip.aspx文件时."string IP = stream.ReadToEnd();"这段代码取到的IP数据就是"0.0.0.0"!!!!(呵.在真实情况下.这样的IP地址肯定不是我们想要的结果.而在有些投票系统中限制一个IP只能投1次票时,如果也是用类似的代码取得对方IP然后再判断的话.呵呵.限制就失效咯)...

或者如果你用上面代码获取IP地址后后面又不再进行数据判断的话也许还能更进一步进行数据破坏!!
比如你用类似上面的代码中获取IP地址就直接有这样的SQL语句:
 string sql = "INSERT INTO (IP) VALUE ('" + IP + "')";
那么也许破坏者还可以进行SQL注入进行数据破坏!!

这样看来利用"HTTP_X_FORWARDED_FOR"这个属性获取客户端IP的方法就不再可取了.-_-# 但如果不用这种方法.那么那些真正使用了代理服务器的人.我们又不能再获取到他们的真实IP地址(因为某些代理服务器会在"X_FORWARDED_FOR"这个HTTP头里加上访问用户真正的IP地址).呵.现实就是这样,某种东西都有有得必有失...

最后,我的建议是不要再使用上面的方法去获取客户端IP.即是不要再理会代理情况.你的建议又是怎样呢???
posted @ 2007-11-24 11:06 Kingthy 阅读(13407) 评论(29) 编辑 收藏

 回复 引用 查看   
#1楼[楼主] 2007-11-24 11:07 Kingthy      
我的天..编辑器不见了.就成了这样的排版..汗...
 回复 引用   
#2楼 2007-11-24 11:11 匿名[未注册用户]
有道理。。。
 回复 引用 查看   
#3楼 2007-11-24 11:14 dudu      
麻烦重新调整一下排版。
 回复 引用 查看   
#4楼[楼主] 2007-11-24 11:18 Kingthy      
现在好了.换了一个编辑就可以了..
"TextBox"这个编辑怎么用不了了??

 回复 引用   
#5楼 2007-11-24 11:24 A1[未注册用户]
呵呵,我用这个骗了不少论坛,搞了不少恶作剧,网上搜一下白宫有哪些IP,然后以此就利用工具(也可以只是浏览器插件FF下比IE容易实现)伪装成从白宫访问,哈哈哈。。。。

回到正题,个人认为还是只支持REMOTE_ADDR比较好。
至于你说的利用伪造HTTP_X_FORWARDED_FOR来实现sql注入,这个貌似02年就被爆出,某个著名的php论坛程序有此漏洞。现在多数论坛程序在处理ip地址的时候都有格式检查,即便没有,在拼接sql语句的时候肯定会过滤不安全字符的(这是最应该做的了)。

 回复 引用 查看   
#6楼[楼主] 2007-11-24 11:31 Kingthy      
@A1
嗯.认同.但现在其时还有很多WEB程序都不会处理这个IP数据的(因为在部分程序员的头脑里IP地址就是XXX.XXX.XXX.XXX.所以认为是数据安全的). :0

 回复 引用 查看   
#7楼 2007-11-24 12:02 阿不      
还是拼接SQL的错误。
 回复 引用   
#8楼 2007-11-24 13:01 banroo[未注册用户]
老漏洞了。

做好过滤是应该的。

 回复 引用 查看   
#9楼 2007-11-24 13:44 曲滨*銘龘鶽      
Http Header 本来就是方便传输一些数据的
根本就没有加密

这一点作Web的人应该心知肚明。

 回复 引用 查看   
#10楼 2007-11-24 17:15 Enzo      
@A1
恩,现在都要过滤输入字符!

 回复 引用 查看   
#11楼 2007-11-24 20:05 zoti      
有道理,顶一个。
推荐阅读HTTP协议
 回复 引用 查看   
#13楼 2007-11-25 02:30 米开朗基罗      
http的头本来就是不可信的,要把它和用户从textbox里面输入的字符串作同等处理。

可以把HTTP_X_FORWARDED_FOR作为一个判断逻辑里面的参考,比较一下看里面是不是已经有了。
其实,限制一个ip只能投一票,它就影响了很多NAT方式共用一个ip的人的正常使用。影响小的是一个家里的人,比如大姐一台电脑,你的一台电脑。两个人,但你们只能投一票。影响大点就是有些垃圾isp,装网的时候就给你一个10.x.x.x,然后让你到它的内部网关路由出去,一堆人用一个ip。

 回复 引用 查看   
#14楼 2007-11-25 09:00 暗香浮动      
那ip如何获取才是可信的呢。
 回复 引用   
#15楼 2007-11-25 11:57 5555[未注册用户]
public static string GetRealIP()
{
string ip;
try
{
if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
{
ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString().Split(',')[0].Trim();
}
else
{
ip = HttpContext.Current.Request.UserHostAddress;
}
}
catch (Exception e)
{
throw e;
}
return ip;
}

用上面的函数获取IP

 回复 引用 查看   
#16楼 2007-11-25 13:42 米开朗基罗      
@5555
楼上的一行写太多代码了:
ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString().Split(',')[0].Trim();

 回复 引用 查看   
#17楼[楼主] 2007-11-25 21:05 Kingthy      
@米开朗基罗
HTTP头这肯定是不可信的.
@暗香浮动
只有"Request.UserHostAddress"才是可信的.但是这样的话却又获取不了那些已使用了代理服务器的用户真实IP地址(因为在这时Request.UserHostAddress获取到的就是这代理服务器的IP)..

 回复 引用   
#18楼 2007-11-25 22:16 helixapp[未注册用户]
这个看怎么选择了 一般的情况下 特别是使用IE 伪造这个头的可能比较小

假如不判断这个头,作弊者想要找一堆的代理 也不难啊

 回复 引用 查看   
#19楼 2007-11-26 00:47 米开朗基罗      
@Kingthy
在大众化的产品里面想identify一个用户就是和用户的隐私作搏斗,技术上有很多反追踪的办法的,所以不能完全做到你想要的效果,只可以尽量去堵漏洞,并消除带来的影响。

 回复 引用   
#20楼 2007-11-26 16:50 cozo[未注册用户]
有时候我的程序需要隐藏在自己的Apache的Proxy模块后面,这样如果不用这个方法,取到的IP全部是127.0.0.1。
 回复 引用 查看   
#21楼[楼主] 2007-11-28 22:48 Kingthy      
@cozo
因为你已经知道你的程序是要经过你自己的Proxy,所以基本就可以相信那些数据了..

对了,好像用ASP不行.试一下下面的代码
<%
userip = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If userip = "" Then userip = Request.ServerVariables("REMOTE_ADDR")
Response.write(userip)
%>
<table>
<% For Each sd In Request.ServerVariables %>
<TR><TD> <%= sd%> </TD>
<TD> <%= Request.ServerVariables(sd) %> </TD>
</TR>
<% Next %>
</table>

 回复 引用   
#23楼 2008-10-14 23:49 fearwall[未注册用户]
public long IPtoNum(string Ip)
{
string[] stringip = new string[4];
stringip = Ip.Split('.');
long ipnum = Convert.ToInt64((stringip[0])) * 16777216 + Convert.ToInt64(stringip[1]) * 65536 + Convert.ToInt64(stringip[2])*256 + Convert.ToInt64(stringip[3]);
return ipnum;
}

sadf
sfasdf

 回复 引用 查看   
#26楼 2009-11-08 08:15 rym1020      
如果是用了squid进行加速的网站那如何对待这个问题呢?如果不取代理IP,那全是服务器的IP了。如果取代理IP,那么又可以伪造。。。不知道腾讯、新浪等网站是如何处理的?
 回复 引用 查看   
#27楼 2011-02-19 15:24 betsell      
介绍说明:
相信很多做过“皇冠投注系统出租或安装”的技术人员来说,会有一个很头痛的技术问题:那就是客户要求经常要求更换服务器(至少更换IP)。
大部分情况都是直接把程序安装到新的服务器去,当然也包括导入和导出数据库等一系列工作。要是新服务器的配置环境遇到什么问题的话,恐怕需要花不长时间调试。

使用说明:
影射规则例子:源127.0.0.1,目标127.0.0.1:8080;则当浏览器访问127.0.0.1的时候会和直接访问127.0.0.1:8080的感觉一样;依照这样的方法也可以保留服务器本身的www服务,只需要把www服务的端口改成其他端口(如8080),接着按上边方法添加目标规则就可以了。也可以直接修改map.txt(这个是影射规则文件)的写字板文件。
免责申请:
由于本软件免费,所以不提供任何保证,也不包括所有因为本软件带来的法律风险,请使用者不要违反当地的法律法规。

PS:服务端程序可以调用http头里边的“X_FORWARDED_FOR”信息,这个是访问者的真实IP;
运行需求:.NET Framework 3.5


文章来源:<a href="http://www.betsell.net" target="_blank">betsell</a>

 回复 引用 查看   
#28楼 2011-12-18 15:00 杨印      
你们说的这些代码,我都试过了,全都获得不了我的真是IP