我知道注册全局变量不应该使用,但不能完全理解为什么?
这是我经常发现的代码,用于演示在将example.com?authorized=1
之类的东西传递给脚本时使用全局寄存器的安全风险:
if (authenticated_user())
{
$authorized = true;
}
if ($authorized)
{
include '/highly/sensitive/data.php';
}
我的问题是,如果用户必须在url中传递authorized=1
,他应该知道我在脚本中使用的变量名称,对吗?这怎么可能呢?
也不是像parse_str()
这样的函数,其行为有点类似于注册全局变量,也存在安全风险?
- 攻击者可能通过另一个安全漏洞或隐私泄露访问您的源代码。
- 攻击者可以猜测。构建一个bot来枚举所有可能的变量名,并在数千个php站点上进行尝试,这非常简单。(
?authorized=1
,?login=1
,?access=1
等)
编辑
对于parse_str
的响应,这取决于用例是什么,但通常可能。如果parse_str
被传递给任何用户提供的内容,那么是的,它绝对是不安全的。
可能有一些合法的用例,其中提供的输入不是用户提供的,但通常我会远离它。
我也想说同样的extract
: http://ca1.php.net/manual/en/function.extract.php
想想你为什么用authorized
来命名你的变量?是描述性的,对吧?黑客在url中使用字典词,如果register_globals
在
虽然黑客确实需要知道变量名,但在许多情况下,这些变量名很容易猜到,并且尝试暴力破解是一项微不足道的任务。
当你使用开源软件、插件或复制/粘贴流行的代码片段时,这一点变得更加真实。
首先register_globals
存在安全风险。
- 它是在PHP级别打开的,所以你不能说只引用一个脚本是安全的。
- 程序员(可能是任何程序员,而不仅仅是你)将不知道
$authorized
是如何设置的,并且可能无意中在代码中留下安全循环漏洞。 - 在
register_globals
中注册的变量是superglobals
,这意味着它们可以在PHP脚本的任何范围内使用。
接下来我们看看parse_str
。该函数只将变量解析到当前代码范围内(参考)。任何程序员都可以查看当前的作用域,并确定是否以及如何保护它。它仍然不是很安全,但不像register_globals
那样不安全。