跳转到内容

PHP 编程/配置:Register Globals

来自维基教科书,开放世界中的开放书籍

什么是 Register Globals?

[编辑 | 编辑源代码]

PHP 中常见的安全问题是 PHP 配置文件 (php.ini) 中的 register_globals 设置。此设置(可以是 **开启** 或 **关闭**)指示是否将 EGPCS(环境、GET、POST、Cookie、服务器)变量的内容注册为全局变量。例如,如果 register_globals 为 **开启**,则 URL http://www.example.com/test.php?id=3 将声明 $id 为一个 全局变量,无需任何代码。类似地,$DOCUMENT_ROOT 也将被定义,因为它属于 $_SERVER '超级全局' 数组的一部分。这两个例子等同于在脚本开头放置以下代码

$id = $_GET['id'];
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];

此功能是一个巨大的安全风险,您应该确保所有脚本的 register_globals 设置为 **关闭**(从 PHP 4.2.0 开始,这是默认设置,从 5.4.0 开始,此设置已完全删除)。建议通过 PHP 预定义变量进行操作,例如超级全局的 $_REQUEST。更安全的方式是使用 $_ENV、$_GET、$_POST、$_COOKIE 或 $_SERVER 来指定,而不是使用更通用的超级全局 $_REQUEST。

假设这段 PHP 代码位于接收表单的末端。用户刚刚输入了错误的密码。$_POST 数组变量处理它。代码将描述如果密码正确(例如,"correct password" 为 "12345"),变量 $admin 将被设置为 TRUE。网站的配置说如果 $admin 设置为 TRUE,该用户将拥有管理员权限。此代码与 PHP5 兼容。

if (isset($_POST['password']) && $_POST['password'] == "12345") {
    $admin = TRUE;
}

register_globals 不会区分 $_POST 变量和 $_GET 变量。因此,假设用户输入了表单,它将用户带到了上述页面。用户可能会认为自己应该拥有管理员权限,即使他们不知道密码。因此,该用户可以在该页面的 URL 后附加 ?admin=1。如果 register_globals 为 **开启**,这样做会强制创建变量 $admin 并自动将值设置为 1,使其等效于 TRUE。因此,register_globals **开启** 允许用户将变量和值**注入**到程序中!在此,无论用户是否输入了正确的密码,用户只需使用 URL 就能获得管理员权限。

如您所见,这种状况可能会在任何时候发生,只要有人想出如何编写页面代码。它可能会在许多其他情况下发生。

另一个例子是会话。当 register_globals = 开启 时,我们也可以在下面的例子中使用 $username,但同样要注意,$username 也可以来自其他方式,例如 GET(通过 URL)。

 // We wouldn't know where $username came from but do know $_SESSION is
 // for session data
 if (isset($_SESSION['username'])) {
     echo "Hello <b>{$_SESSION['username']}</b>";
 } else {
     echo "Hello <b>Guest</b><br />";
     echo "Would you like to login?";
 }

最佳实践

[编辑 | 编辑源代码]

避免此问题的最佳方法是确保您的 php.ini 中的 register_globals 设置为 **关闭**。但作为一般的编码建议,始终初始化您的变量。以下代码对之前的代码示例进行了一些小的添加,但首先将 $admin 设置为 FALSE,因此用户只能通过条件语句获得管理员权限

 $admin = FALSE;
 if (isset($_POST["password"]) && $_POST["password"] == "12345") {
     $admin = TRUE;
 }

filter_input()

[编辑 | 编辑源代码]

由于超级全局数组访问容易受到 代码注入[1] 的影响,出于安全原因,最好使用带有 filter_input()[2] 的语法

<?php
echo filter_input(INPUT_GET, 'password'); // good
echo $_GET['password'];                   // not good
?>

参考资料

[编辑 | 编辑源代码]

更多信息

[编辑 | 编辑源代码]


华夏公益教科书