猫窝私语 — Makumo's Blog

玛酷猫的温馨小窝,记录生活点点滴滴。

@玛酷猫15 年前

12/6
01:46
他山之石 建站日志

HTTP_X_FORWARDED_FOR、IP、安全性

(由于本人也是PHP的初学者,对于一些安全问题了解的也不是很多。可能是空间商“将程序隐藏在Apache的Proxy模块后面”,除了使用HTTP_X_FORWARDED_FOR,其他方法获取的IP地址都是127.0.0.1。@gowers在之前所写的《解决wordpress留言评论者IP都是127.0.0.1》提到了关于HTTP_X_FORWARDED_FOR安全性的问题,我在网上查找了些资料,安全性的漏洞可以使用格式检查和SQL语句不安全字符过滤方法来封堵,不过对于伪造IP就没什么办法了。引用下kingthy的一篇文章《使用HTTP_X_FORWARDED_FOR获取客户端IP的严重后果》)

在WEB开发中.我们可能都习惯使用下面的代码来获取客户端的IP地址:

//优先取得代理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地址!!

下面是测试代码:

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”文件代码:

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地址).呵.现实就是这样,某种东西都有有得必有失…

HTTP_X_FORWARDED_FOR、IP、安全性