2

我很难理解这个功能。我知道 register_globals 是什么以及它从 PHP 中贬值了多长时间,但我正在查看这段代码,我想,里面有什么?...

<?php
    //Undo register_globals
    function unregister_globals() {
        if (ini_get(register_globals)) {
            $array = array('_REQUEST', '_SESSION', '_SERVER', '_ENV', '_FILES');
            foreach ($array as $value) {
                foreach ($GLOBALS[$value] as $key => $var) {
                    if ($var === $GLOBALS[$key]) {
                        unset($GLOBALS[$key]);
                    }
                }
            }
        }
    }
?>

我不明白的部分是这个......

foreach ($array as $value) {
    foreach ($GLOBALS[$value] as $key => $var) {
        if ($var === $GLOBALS[$key]) {
            unset($GLOBALS[$key]);
         }
     }
 }

这个 foreach 循环循环遍历我们定义的 $array 中的每个值,然后内部 foreach 循环从 GLOBALS 中获取一个超级全局数组,无论它是 _REQUEST、_SESSION、_SERVER、_ENV、_FILES 等......检查 $var 是否等于 GLOBAL 变量或不等于。如果是这样,那么我们将取消设置。

但是我仍然很难解决这个问题......

更新 这是我正在试验和调试的代码片段。如果 register_globals 处于打开状态,并且黑客来了,将 ?auth=1 插入到查询字符串中,会发生什么?auth 会从 GLOBALS 中删除还是会被回显?

if( true ) {
    $globals = array(
        '_COOKIE',
        '_GET',
        '_POST',
        '_REQUEST',
        '_SERVE',
        '_SESSION'
    );

    foreach($globals as $global) {
        foreach($GLOBALS[$global] as $k => $v) {
            /* $GLOBALS['_GET'] on the first loop; */
            /* IF WE SAY, $GLOBALS['app_dir'], WE GET THE VALUE */

            if( $v == $GLOBALS[$k] ) {
                echo "K=> " . $k . "<br />";
                echo "V => " . $v . "<br />";
                echo "GLOB => " . $GLOBALS[$k] . "<br />";
            }
        }
    }

            echo $authorized; // a intentional non-defined variable

    //print_r($GLOBALS);
}

谢谢你的时间。

4

3 回答 3

1

是的,这段代码看起来很奇怪:

foreach ($GLOBALS[$value] as $key => $var) {
        if ($var === $GLOBALS[$key]) {//<- ?
            unset($GLOBALS[$key]);
         }
     }

您可以使用一个简单的数组来模仿正在发生的事情,并确保这if绝对没用:

<?php
$data = array(1,2,3);

foreach ($data as $key => $var) {
    var_dump($var);
    var_dump($data[$key]);
    if ($var === $data[$key]) {
        unset($data[$key]);
    }
}

输出:

int(1)
int(1)
int(2)
int(2)
int(3)
int(3)

如您所见,每次的值都是相等的,最后 $data 将为空。

更新

这是脚本,您可以在您的机器上重现:

<?php
extract($_REQUEST);

var_dump($auth);
$array = array('_REQUEST', '_SESSION', '_SERVER', '_ENV', '_FILES');
foreach ($array as $value) {
    if(isset($GLOBALS[$value]))
    {
        foreach ($GLOBALS[$value] as $key => $var) {
            unset($GLOBALS[$key]);
        }
    }
}
var_dump($auth);

虽然这样称呼它:http://site/script.php?auth=1

它为我提供了以下输出:

string(1) "1"
<br />
<b>Notice</b>:  Undefined variable: auth on line 14
NULL

因此,似乎该 auth 变量已被破坏。但是 $GLOBALS 数组仍然包含大量数据。

更新 2

我想,我们的错误在这里:

unset($GLOBALS[$key]);

为什么我们要取消设置外部数组的键。如果你这样做:

$array = array('_REQUEST', '_SESSION', '_SERVER', '_ENV', '_FILES');
foreach ($array as $value) {
    if(isset($GLOBALS[$value]))
    {
        foreach ($GLOBALS[$value] as $key => $var) {
            unset($GLOBALS[$value][$key]);
        }
    }
}

它将清空 $_REQUEST、$_SESSION 和所有其他必要的数组。

于 2013-12-06T20:21:29.330 回答
0

全局变量(尤其是 $_GET, $_POST, $_COOKIE, $_ENV, ... 和这个 Superglobals 的 $GLOBALS-Entries )最初由 PHP 填充,并且不应该被任何应用程序(覆盖)或删除。

对 Superglobal-Values 的任何操作都会降低当前请求的真实性,并且会违背 PHP 的故意行为。

嵌套的 foreach 意味着给定的 Array 将被迭代(外部 foreach)并且每个条目也将被迭代。Array-Key 用作 $key,array-value 用作 $var

于 2013-12-06T20:29:40.603 回答
0

既然我能够看到它实际上是如何工作的,我就可以绕着它转。本质上,如果用户使用的是 PHP 5.3.0 或更低版本并且启用了“register_globals”,黑客可以查询常用变量名称,例如“授权”、“用户名”等,如果该变量已经由开发人员定义,则可以输入自己的值.

例子:

if( is_authorized() ) {
    $auth = 1;
}

if( $auth ) {
    // do authorization code here!!!
} else {
    show_login();
}

你可以看到 $auth 是有条件地定义的。如果黑客出现并尝试类似 index.php?auth=1 或 index.php?auth=true 那么 PHP 会将其注册为全局值,它将在条件中进行检查,我们的黑客将有权访问到应用程序。

我找到...

foreach ($array as $value) {
    foreach ($GLOBALS[$value] as $key => $var) {
        if ($var === $GLOBALS[$key]) {
            unset($GLOBALS[$key]);
        }
    }
}

...实际上取消设置这些值并且黑客将无权访问,但是,正如我之前认为的那样,还有一个错误。我的框架中有两个全局变量 $app_dir 和 $sys_dir 指向两个重要目录。如果黑客出现并说出类似 index.php?app_dir=application&sys_dir=system 的内容,那么它实际上会从 $GLOBALS 中取消设置这些全局变量。这要求任何在 PHP 5.3.0 或更低版本上使用它的人在我的框架内部存在潜在危险。

基本上它的工作原理是条件检查以查看 $var (我们的值,'system')是否等于 $GLOBAL['sys_dir'] 中的值。有人知道怎么修这个东西吗?

于 2013-12-08T11:10:49.300 回答