我做了很多搜索,也读了PHP $_SERVER docs。我是否有权使用PHP脚本来定义整个站点中使用的简单链接?$_SERVER['SERVER_NAME']
基于Web服务器的配置文件(在我的例子中是Apache2),并根据以下几个指令而变化:(1)VirtualHost,(2)ServerName,(3)UseCanonicalName等。$_SERVER['HTTP_HOST']
基于客户端的请求。
因此,在我看来,为了使我的脚本尽可能兼容,应该使用的合适的脚本是$_SERVER['HTTP_HOST']
。这个假设是否正确?
跟进意见:
我想我阅读了这篇文章后有点偏执,并注意到有些人说“他们不会信任任何$_SERVER
变量”:
- http://markjaquith.wordpress.com/2009/09/21/php-server-vars-not-safe-in-forms-or-links/
- http://php.net/manual/en/reserved.variables.server.php#89567(评论:弗拉基米尔Kornea 2009年3月14日01:06)
显然,讨论主要是关于$_SERVER['PHP_SELF']
以及为什么不应该在没有适当转义的情况下在form action属性中使用它来防止XSS攻击。
我对上面最初问题的结论是,对网站上的所有链接使用$_SERVER['HTTP_HOST']
是“安全的”,而不必担心XSS攻击,即使在表单中使用也是如此。
如果我说错了请纠正我。
9条答案
按热度按时间cyvaqqii1#
这可能是每个人的第一个想法。但这有点困难。参见Chris Shiflett’s article
SERVER_NAME
VersusHTTP_HOST
。似乎没有银。只有当您强制Apache使用规范名称时,您才能始终获得正确的服务器名称
SERVER_NAME
。因此,您可以使用它,或者根据白色名单检查主机名:
kmbjn2e32#
只是一个额外的注意-如果服务器运行在一个端口不是80(在开发/内部网机器上可能很常见),那么
HTTP_HOST
包含端口,而SERVER_NAME
不包含。(At至少这是我在Apache基于端口的虚拟主机中注意到的)
正如Mike在下面提到的,
HTTP_HOST
在HTTPS上运行时不包含:443
(除非你在非标准端口上运行,我还没有测试过)。zqry0prt3#
两者都可以使用。它们都是同样安全的,因为在许多情况下,SERVER_NAME只是从HTTP_HOST填充的。我通常使用HTTP_HOST,这样用户就可以使用他们开始时使用的主机名。例如,如果我在.com和.org域上有相同的站点,我不想将某人从.org发送到.com,特别是如果他们可能在.org上有登录令牌,如果发送到另一个域,他们会丢失。
无论哪种方式,你只需要确保你的网络应用程序只会响应已知良好的域名。这可以通过(a)应用程序端检查(如Gumbo的)或(b)在您想要的域名上使用虚拟主机来完成,该域名不响应给予未知主机头的请求。
这样做的原因是,如果您允许您的网站访问任何旧的名称,你奠定自己开放的DNS重新绑定攻击(其中另一个站点的主机名指向您的IP,用户使用攻击者的主机名访问您的站点,然后主机名被移动到攻击者的IP,把你的cookies/auth与它)和搜索引擎劫持(攻击者将自己的主机名指向您的站点,并试图让搜索引擎将其视为“最佳”主主机名)。
显然,讨论主要是关于$_SERVER ['PHP_SELF']以及为什么不应该在没有适当转义的情况下在form action属性中使用它来防止XSS攻击。
你不应该在 any 属性中使用 anything 而不使用
htmlspecialchars($string, ENT_QUOTES)
进行转义,所以这里的服务器变量没有什么特别的。o4tp2gmn4#
这是Symfony用于获取主机名的详细翻译(* 请参阅第二个示例以获得更直接的翻译 *):
过期:
这是我对Symfony框架中使用的方法的纯PHP翻译,该方法试图以最佳实践的顺序从各种可能的方式获取主机名:
pgccezyw5#
对站点上的所有链接使用
$_SERVER['HTTP_HOST']
而不必担心XSS攻击(即使在表单中使用)是否“安全”?是的,使用
$_SERVER['HTTP_HOST']
(甚至$_GET
和$_POST
)是safe,只要您在接受它们之前进行验证。这是我为安全生产服务器所做的:$_SERVER['HTTP_HOST']
的优点是它的行为比$_SERVER['SERVER_NAME']
定义得更好。对比度:主持人内容:当前请求的头,如果有。
其中:
正在执行当前脚本的服务器主机的名称。
使用像
$_SERVER['HTTP_HOST']
这样定义更好的接口意味着更多的SAPIs将使用可靠定义良好的行为来实现它。(与the other不同。)但是,它仍然完全依赖于SAPI:不保证每个Web服务器都将提供任何这些[
$_SERVER
条目];服务器可以省略一些,或者提供这里未列出的其它。要理解如何正确检索主机名,首先您需要了解仅包含 * 代码 * 的服务器无法知道(验证的先决条件)网络上的自己的名称。它需要与一个提供自己名称的组件进行交互。这可以通过以下方式实现:
Host:
请求通常通过本地(SAPI)配置文件完成。请注意,您已正确配置了它,例如:在Apache中:
有几件事需要“伪造”,使动态虚拟主机看起来像一个正常的。
最重要的是Apache用来生成自引用URL等的服务器名称。它使用
ServerName
指令进行配置,CGI可以通过SERVER_NAME
环境变量使用它。运行时使用的实际值由UseCanonicalName设置控制。
UseCanonicalName Off
表示服务器名称来自请求中Host:
头的内容。对于UseCanonicalName DNS
,它来自虚拟主机IP地址的反向DNS查找。前者用于基于名称的动态虚拟主机,后者用于基于IP的主机。如果因为没有
Host:
头或者DNS查找失败而导致Apache无法计算出服务器名称*,则**使用ServerName
配置的值。jgovgodb6#
两者之间的主要区别在于
$_SERVER['SERVER_NAME']
是服务器控制的变量,而$_SERVER['HTTP_HOST']
是用户控制的值。经验法则是永远不要相信来自用户的值,因此
$_SERVER['SERVER_NAME']
是更好的选择。正如Gumbo指出的,如果不设置
UseCanonicalName On
,Apache将根据用户提供的值构造SERVER_NAME。编辑:说了这么多,如果站点使用基于名称的虚拟主机,HTTP主机头是访问非默认站点的唯一方法。
wz1wpwve7#
我不确定,也不真正信任
$_SERVER['HTTP_HOST']
,因为它依赖于来自客户端的头。换句话说,如果客户端请求的域不是我的,他们就不会进入我的网站,因为DNS和TCP/IP协议将其指向正确的目的地。然而,我不知道是否可能劫持DNS,网络甚至Apache服务器。为了安全起见,我在环境中定义了主机名,并将其与$_SERVER['HTTP_HOST']
进行比较。在根目录下的.htaccess文件中添加
SetEnv MyHost domain.com
并在Common.php中添加ths代码我在每个php页面中都包含了这个Common.php文件。此页面为每个请求做任何需要的事情,如
session_start()
,修改会话cookie并拒绝来自不同域的post方法。gblwokeq8#
XSS
将始终存在,即使您使用$_SERVER['HTTP_HOST']
、$_SERVER['SERVER_NAME']
或$_SERVER['PHP_SELF']
gstyhher9#
首先,我想感谢你所有的好答案和解释。这是我根据你的所有答案创建的方法来获取基本URL。我只在非常罕见的情况下使用它。因此,没有一个大的重点是安全问题,如XSS攻击。也许有人需要它。