PHP $_SERVER['HTTP_HOST'] 与 $_SERVER['SERVER_NAME'],我是否正确理解手册页?
我进行了大量搜索,还阅读了 PHP $_SERVER 文档。我是否有权决定在我的 PHP 脚本中使用哪些脚本来定义整个站点中使用的简单链接?
$_SERVER['SERVER_NAME']
基于您的 Web 服务器的配置文件(在我的例子中是 Apache2),并根据以下几个指令而变化:(1) VirtualHost、(2) ServerName、(3) UseCanonicalName等。
$_SERVER['HTTP_HOST']
是根据客户端的请求来的。
因此,在我看来,为了使我的脚本尽可能兼容,最合适使用的是 $_SERVER['HTTP_HOST']
。这个假设正确吗?
后续评论:
我想在读完这篇文章并注意到有些人说“他们不会信任任何 $_SERVER
vars”后我有点偏执:
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(评论:Vladimir Kornea 2009 年 3 月 14 日 01:06)
显然讨论主要是关于 $_SERVER['PHP_SELF']
以及为什么你不应该在表单action属性中使用它而不进行适当的转义以防止XSS攻击。
我对上述原始问题的结论是,对网站上的所有链接使用 $_SERVER['HTTP_HOST']
是“安全”的,无需担心 XSS 攻击,即使在表单中使用也是如此。
如果我错了,请纠正我。
I did a lot of searching and also read the PHP $_SERVER docs. Do I have this right regarding which to use for my PHP scripts for simple link definitions used throughout my site?
$_SERVER['SERVER_NAME']
is based on your web server's config file (Apache2 in my case), and varies depending on a few directives: (1) VirtualHost, (2) ServerName, (3) UseCanonicalName, etc.
$_SERVER['HTTP_HOST']
is based on the request from the client.
Therefore, it would seem to me that the proper one to use in order to make my scripts as compatible as possible would be $_SERVER['HTTP_HOST']
. Is this assumption correct?
Followup comments:
I guess I got a little paranoid after reading this article and noting that some folks said "they wouldn't trust any of the $_SERVER
vars":
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 (comment: Vladimir Kornea 14-Mar-2009 01:06)
Apparently the discussion is mainly about $_SERVER['PHP_SELF']
and why you shouldn't use it in the form action attribute without proper escaping to prevent XSS attacks.
My conclusion about my original question above is that it is "safe" to use $_SERVER['HTTP_HOST']
for all links on a site without having to worry about XSS attacks, even when used in forms.
Please correct me if I'm wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这想必是每个人的第一想法。但这有点困难。请参阅 Chris Shiflett 的文章
SERVER_NAME
与HTTP_HOST
相比。似乎没有灵丹妙药。仅当您强制 Apache 使用规范名称时,您将始终使用
SERVER_NAME
获取正确的服务器名称。因此,您要么接受它,要么根据白名单检查主机名:
That’s probably everyone’s first thought. But it’s a little bit more difficult. See Chris Shiflett’s article
SERVER_NAME
VersusHTTP_HOST
.It seems that there is no silver bullet. Only when you force Apache to use the canonical name you will always get the right server name with
SERVER_NAME
.So you either go with that or you check the host name against a white list:
附加说明 - 如果服务器在 80 以外的端口上运行(这在开发/内联网计算机上可能很常见),则
HTTP_HOST
包含该端口,而SERVER_NAME
则包含该端口不是。(至少这是我在基于 Apache 端口的虚拟主机中注意到的)
正如 Mike 在下面指出的,当在 HTTPS 上运行(除非您在非标准端口上运行,我尚未测试过)。
Just an additional note - if the server runs on a port other than 80 (as might be common on a development/intranet machine) then
HTTP_HOST
contains the port, whileSERVER_NAME
does not.(At least that's what I've noticed in Apache port-based virtualhosts)
As Mike has noted below,
HTTP_HOST
does not contain:443
when running on HTTPS (unless you're running on a non-standard port, which I haven't tested).使用任一。它们都同样(不)安全,因为在许多情况下 SERVER_NAME 无论如何都是从 HTTP_HOST 填充的。我通常选择 HTTP_HOST,以便用户停留在他们开始时使用的确切主机名上。例如,如果我在 .com 和 .org 域上有相同的网站,我不想将某人从 .org 发送到 .com,特别是如果他们可能在 .org 上拥有登录令牌,如果发送到这些令牌,他们就会丢失另一个域。
无论哪种方式,您只需要确保您的网络应用程序只会响应已知良好的域。这可以通过 (a) 通过像 Gumbo 这样的应用程序端检查来完成,或者 (b) 通过在您希望不响应请求的域名上使用虚拟主机来完成未知的主机标头。
这样做的原因是,如果您允许以任何旧名称访问您的站点,您就会面临 DNS 重新绑定攻击(其中另一个站点的主机名指向您的 IP,用户使用攻击者的主机名访问您的站点,然后使用该主机名)移动到攻击者的 IP,并带走您的 cookie/身份验证)和搜索引擎劫持(攻击者将自己的主机名指向您的站点,并尝试让搜索引擎将其视为“最佳”主要主机名)。
噗。好吧,如果不使用
htmlspecialchars($string, ENT_QUOTES)
进行转义,则不应在 any 属性中使用 anything,因此服务器变量没有什么特别之处。Use either. They are both equally (in)secure, as in many cases SERVER_NAME is just populated from HTTP_HOST anyway. I normally go for HTTP_HOST, so that the user stays on the exact host name they started on. For example if I have the same site on a .com and .org domain, I don't want to send someone from .org to .com, particularly if they might have login tokens on .org that they'd lose if sent to the other domain.
Either way, you just need to be sure that your webapp will only ever respond for known-good domains. This can be done either (a) with an application-side check like Gumbo's, or (b) by using a virtual host on the domain name(s) you want that does not respond to requests that give an unknown Host header.
The reason for this is that if you allow your site to be accessed under any old name, you lay yourself open to DNS rebinding attacks (where another site's hostname points to your IP, a user accesses your site with the attacker's hostname, then the hostname is moved to the attacker's IP, taking your cookies/auth with it) and search engine hijacking (where an attacker points their own hostname at your site and tries to make search engines see it as the ‘best’ primary hostname).
Pfft. Well you shouldn't use anything in any attribute without escaping with
htmlspecialchars($string, ENT_QUOTES)
, so there's nothing special about server variables there.这是 Symfony 用于获取主机名的详细翻译(请参阅第二个示例以获取更直译的翻译):
已过时:
是我对 Symfony 框架中使用的方法的裸 PHP 的翻译,该方法尝试按照最佳实践的顺序从各种可能的方式获取主机名:
This is a verbose translation of what Symfony uses to get the host name (see the second example for a more literal translation):
Outdated:
This is my translation to bare PHP of a method used in Symfony framework that tries to get the hostname from every way possible in order of best practice:
是的,使用
$_SERVER['HTTP_HOST'] 安全 code>(甚至是
$_GET
和$_POST
)只要您在接受之前验证它们即可。这就是我对安全生产服务器所做的事情:$_SERVER['HTTP_HOST']
的优点是它的行为比$_SERVER['SERVER_NAME']
定义更明确>。对比 ➫➫:和:
使用像
$_SERVER['HTTP_HOST']
这样定义更好的接口意味着更多的 SAPI 将使用可靠定义良好的行为来实现它。 (与另一个不同。)但是,它仍然完全依赖于SAPI ➫➫:要了解如何正确检索主机名,首先您需要了解仅包含代码的服务器无法知道(验证的先决条件)其自己的名称< /strong> 在网络上。它需要与为其提供自己名称的组件进行交互。这可以通过以下方式完成:
本地配置文件
本地数据库
硬编码源代码
外部请求(curl)
客户端/攻击者的
Host:
请求etc
通常是通过本地(SAPI)配置文件完成的。请注意,您已正确配置它,例如在 Apache ➫➫ 中:
Yes, it's safe to use
$_SERVER['HTTP_HOST']
, (and even$_GET
and$_POST
) as long as you verify them before accepting them. This is what I do for secure production servers:The advantage of
$_SERVER['HTTP_HOST']
is that its behavior is more well-defined than$_SERVER['SERVER_NAME']
. Contrast ➫➫:with:
Using a better defined interface like
$_SERVER['HTTP_HOST']
means that more SAPIs will implement it using reliable well-defined behavior. (Unlike the other.) However, it is still totally SAPI dependent ➫➫:To understand how to properly retrieve the host name, first and foremost you need to understand that a server which contains only code has no means of knowing (pre-requisite for verifying) its own name on the network. It needs to interface with a component that supplies it its own name. This can be done via:
local config file
local database
hardcoded source code
external request (curl)
client/attacker's
Host:
requestetc
Usually its done via the local (SAPI) config file. Note that you have configured it correctly, e.g. in Apache ➫➫:
两者之间的主要区别在于,
$_SERVER['SERVER_NAME']
是服务器控制的变量,而$_SERVER['HTTP_HOST']
是用户控制的值。经验法则是永远不要信任用户的值,因此
$_SERVER['SERVER_NAME']
是更好的选择。正如 Gumbo 指出的那样,如果您未设置
UseCanonicalName On
,Apache 将根据用户提供的值构造 SERVER_NAME。编辑:话虽如此,如果站点使用基于名称的虚拟主机,则 HTTP 主机标头是访问非默认站点的唯一方法。
The major difference between the two is that
$_SERVER['SERVER_NAME']
is a server controlled variable, while$_SERVER['HTTP_HOST']
is a user-controlled value.The rule of thumb is to never trust values from the user, so
$_SERVER['SERVER_NAME']
is the better choice.As Gumbo pointed out, Apache will construct SERVER_NAME from user-supplied values if you don't set
UseCanonicalName On
.Edit: Having said all that, if the site is using a name-based virtual host, the HTTP Host header is the only way to reach sites that aren't the default site.
我不确定也不太信任
$_SERVER['HTTP_HOST']
因为它依赖于来自客户端的标头。换句话说,如果客户请求的域不是我的域,他们将不会进入我的网站,因为 DNS 和 TCP/IP 协议将其指向正确的目的地。但是我不知道是否可以劫持 DNS、网络甚至 Apache 服务器。为了安全起见,我在环境中定义主机名并将其与$_SERVER['HTTP_HOST']
进行比较。在根目录下的 .htaccess 文件中添加
SetEnv MyHost domain.com
并在 Common.php 中添加此代码我在每个 php 页面中都包含此 Common.php 文件。该页面执行每个请求所需的任何操作,例如
session_start()
、修改会话 cookie 以及如果 post 方法来自不同域则拒绝。I am not sure and not really trust
$_SERVER['HTTP_HOST']
because it depend on header from client. In another way, if a domain requested by client is not mine one, they will not getting into my site because DNS and TCP/IP protocol point it to the correct destination. However I don't know if possible to hijack the DNS, network or even Apache server. To be safe, I define host name in environment and compare it with$_SERVER['HTTP_HOST']
.Add
SetEnv MyHost domain.com
in .htaccess file on root and add ths code in Common.phpI include this Common.php file in every php page. This page doing anything required for each request like
session_start()
, modify session cookie and reject if post method come from different domain.即使您使用
$_SERVER['HTTP_HOST']
、$_SERVER['SERVER_NAME']
或$,
XSS
也始终存在_SERVER['PHP_SELF']XSS
will always be there even if you use$_SERVER['HTTP_HOST']
,$_SERVER['SERVER_NAME']
OR$_SERVER['PHP_SELF']
首先,我要感谢您所有好的答案和解释。
这是我根据您获取基本网址的所有答案创建的方法。我只在非常罕见的情况下使用它。因此,安全问题(例如 XSS 攻击)并没有受到太多关注。也许有人需要它。
First I want to thank you for all the good answers and explanations.
This is the method I created based upon all your answer to get the base url. I only use it in very rare situations. So there is NOT a big focus on security issues, like XSS attacks. Maybe someone needs it.