【发布时间】:2011-07-02 19:54:39
【问题描述】:
是否可以伪造或劫持$_SERVER['REMOTE_ADDR']变量的内容?
我想伪造一个请求:
$_SERVER['REMOTE_ADDR']='127.0.0.1';
我怎么能用 PHP 做到这一点? CURL 能以某种方式做到这一点吗?
【问题讨论】:
是否可以伪造或劫持$_SERVER['REMOTE_ADDR']变量的内容?
我想伪造一个请求:
$_SERVER['REMOTE_ADDR']='127.0.0.1';
我怎么能用 PHP 做到这一点? CURL 能以某种方式做到这一点吗?
【问题讨论】:
REMOTE_ADDR
用户查看当前页面的 IP 地址。
您可以使用代理等请求脚本来更改 IP 地址,但您不能在那里设置任何您想要的文本。
【讨论】:
远程地址不是出于礼貌而添加的,它在IP协议中用于路由包,所以如果你send a package with a fake address,你将不会收到响应,因为你在谈论一个HTTP请求,它通过 TCP 连接传递,需要设置几个 IP 数据包(和匹配的响应):
不,这是不可能的(当然除了通过环回接口从同一主机实际发送请求)。
【讨论】:
这是由 apache 或您使用的任何服务器设置的变量。你不能欺骗它。
你可以在脚本的开头运行$_SERVER['REMOTE_ADDR']='127.0.0.1';,但我怀疑这就是你想要做的
【讨论】:
您可以在您的服务器中覆盖$_SERVER 数组中的任何项目,包括您提到的项目;当然,不是在别人的。
但是,它不会更改您计算机的 IP 地址。
【讨论】:
如果您通过代理浏览,$_SERVER['REMOTE_ADDR'] 可能会设置为代理的 IP 地址,而不是最终用户的。
在这种情况下,您可以使用其他标题:此页面提供了一个功能,可检查所有可能性并提供最有可能是最终用户的地址:
http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html
但是,如果用户使用配置不当的代理、恶意代理或旨在匿名最终用户的代理进行代理,那么您将无法保证除REMOTE_ADDR 之外的任何标头(这将只带你到代理)。
如果您的最终用户通过 HTTPS 浏览,那么REMOTE_ADDR 将始终是他的 IP 地址;您不能通过 HTTPS 使用代理转发。因此,绝对确定他的地址的一种方法是让他使用 HTTPS 打开您的网站。
【讨论】:
我假设您的意思是远程伪造它。简短的回答是可以。关于它有多容易的长答案取决于你想如何伪造它。
如果您不关心接收响应,这就像打开一个原始套接字到目标并伪造源 IP 地址一样简单。我不确定在 PHP 中是否真的很容易做到,因为所有 PHP 的套接字实现都处于或高于 TCP 级别。但我确信这是可能的。现在,由于您无法控制网络,因此响应不会返回给您。所以这意味着你不能(无论如何可靠地)通过一个普通的伪造 TCP 标头创建 TCP 连接(因为 syn-ack 确实通过需要双向通信来防止这种情况发生)。
但是,如果您可以破坏 IP 所在的网关,您可以为所欲为。因此,如果您破坏了计算机所连接的 wifi 路由器,您可以假装是那台计算机,而服务器不会分辨出区别。如果您破坏了 ISP 的出站路由器,您可以(至少在理论上)假装自己是计算机,而服务器不会分辨出区别。
有关更多信息,请参阅以下链接:
但是,如果您确实破坏了本地机器/服务器,您将只能在 TCP 下伪造127.0.0.1 环回地址。到那时真的很重要吗?
如果您使用框架来访问此信息,请绝对确定它不会检查 X-HTTP-FORWARDED-FOR 标头!否则,伪造IP地址是微不足道的。例如,如果您使用Zend Framework's Zend_Controller_Request_Http::getClientIp 方法,请绝对确保您将false 作为参数传递!否则有人只需要发送一个 HTTP 标头:X-Http-Forwarded-For: 127.0.0.1,它们现在似乎是本地的!这是一种在不了解后端如何工作的情况下使用框架真的很糟糕的情况......
我最近写了一篇关于我如何偶然发现 StackOverflow 应用程序中的漏洞的博客文章。这在这里非常相关,因为它利用了与这个问题正在寻找的非常相似的机制(尽管它周围的情况有些狭窄):
【讨论】:
Apache 从它用来与浏览器通信的 TCP 套接字填充 $_SERVER['REMOTE_ADDR']。由于three-way-handshake,因此不可能在开放的 Internet 上影响此变量。如果客户端和服务器在广播网络上,比如wifi,那么你可以嗅探电线并完成握手。
【讨论】: