Php 取消注册全局文件?

Php 取消注册全局文件?,php,session,foreach,superglobals,Php,Session,Foreach,Superglobals,我很难理解这个函数。我知道什么是register_globals,以及它从PHP中贬值了多长时间,但我在看这段代码时,我想,在什么 <?php //Undo register_globals function unregister_globals() { if (ini_get(register_globals)) { $array = array('_REQUEST', '_SESSION', '_SERVER', '_ENV',

我很难理解这个函数。我知道什么是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中的每个值,然后内部foreach循环从GLOBALS获取一个超级全局数组,无论它是_请求、_会话、_服务器、_环境、_文件等等。。。之后,条件似乎在检查$var是否等于一个全局变量。如果是这样的话,我们将取消它

但是我仍然很难把我的头绕在这个上面

更新 下面是我正在试验和调试的代码片段。如果register_globals处于打开状态,并且黑客蜂拥而至,在查询字符串中插入?auth=1,会发生什么情况?身份验证将从全局文件中删除,还是将被回显

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);
}
if(真){
$globals=数组(
"饼干",,
"你得到",,
"邮政",,
"请求",,
"发球",,
"会议"
);
foreach($globals作为$global){
foreach($GLOBALS[$global]作为$k=>$v){
/*$GLOBALS[''u GET']在第一个循环中*/
/*如果我们说$GLOBALS['app_dir'],我们就得到了值*/
如果($v==$GLOBALS[$k]){
回显“K=>”$K.
“; 回声“V=>”$V.
“; 回显“GLOB=>”$GLOBALS[$k]。“
”; } } } echo$authorized;//一个故意的未定义变量 //印刷(全球); }

谢谢您的时间。

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

foreach ($GLOBALS[$value] as $key => $var) {
        if ($var === $GLOBALS[$key]) {//<- ?
            unset($GLOBALS[$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);
所以,似乎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]);
        }
    }
}
它将清空$\u请求、$\u会话和所有其他必需的数组。

全局文件(尤其是$\u GET、$\u POST、$\u COOKIE、$\u ENV、…和此超全局文件的$Globals条目)最初由PHP填充,任何应用程序都不应(过度)写入或删除

对超全局值的任何操纵都会降低当前请求的真实性,并与PHP的故意行为背道而驰


嵌套的foreach意味着给定的数组将被迭代(outterforeach),并且每个条目也将被迭代。数组键被用作$Key,数组值被用作$var,现在我已经能够看到它是如何工作的了,我可以把我的头绕在它周围了。基本上,如果用户使用的是PHP5.3.0或更低版本,并且启用了“register_globals”,黑客可以查询常见变量名称,如“authorized”、“username”等,以便在开发人员已经定义变量的情况下输入自己的值

示例:

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]);
        }
    }
}
。。。实际上,取消设置这些值,黑客将无法访问,然而,正如我之前所想,还有一个bug。我的框架中有两个全局变量$app_dir和$sys_dir,它们指向两个重要的目录。如果黑客出现并说出index.php?app_dir=application&sys_dir=system之类的话,那么它实际上会从$GLOBALS中取消设置这些全局变量。这对任何在PHP5.3.0或更低版本上使用我的框架的人来说都是一个潜在的危险


基本上,这是通过条件检查来确定$var(我们的值,'system')是否等于$GLOBAL['sys_dir']中的值。有人知道如何解决这个问题吗?

它取消了所有全局变量的设置,太疯狂了,不要这样做。我检查了我的全局数组,在我的代码中运行它之后,所有变量仍然存在。@W3Geek var_dump($\u globals)在运行它之前,看看它包含什么,除非通过引用传递迭代器,否则不能更改foreach循环中的数组。所以看起来这应该删除所有全局变量,但除非您执行
foreach($globals[$value]as$key=>&$var)
@user4035我看到了所有全局信息,否则它不会工作?我应该在之后转储变量吗?是的,但是假设我有一个变量$authorized,我忘记在某处定义了。一个黑客可以随便走一走,加上?auth=1给自己一个godmode。这会从GLOBALS或GLOBALS取消$auth吗?这段代码很奇怪。@W3Geek正在尝试做一个实验。我会很快让你知道的。@W3Geek我想,我找到了原因。看看更新2,我得等回家再试试。我现在正在试验,但没有办法打开register_globals。它在我的开发服务器上被禁用。我只是想确保我明白这一点。它太复杂了,而且上面没有多少资源?@W3Geek register\u globals也在我的机器上关闭了。我使用了摘录($\u请求);模仿全球人的行为。如果我在URL中查询了?auth=1,并且在代码中已经有$auth变量,您是否会取消设置全局per?不,我不会,现有变量不会影响$\u GET-value。较旧的PHP版本允许一种称为“register globals”的影响安全的行为,这种行为几十年来一直被弃用。在PHP 5.5.x中,只有在提取超全局变量时才可能覆盖现有变量(这相当于旧的寄存器全局变量行为,是最糟糕的做法)。如果:
if($var====$globals[$key])
,则不需要这样做。这个代码不好。让我在没有它的情况下试试。那么,它不会让一切都不安吗?是的,我在回答的开头已经向您展示了,它正在检查sa
$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]);
        }
    }
}
if( is_authorized() ) {
    $auth = 1;
}

if( $auth ) {
    // do authorization code here!!!
} else {
    show_login();
}
foreach ($array as $value) {
    foreach ($GLOBALS[$value] as $key => $var) {
        if ($var === $GLOBALS[$key]) {
            unset($GLOBALS[$key]);
        }
    }
}