8

我继承了一个 Web 服务器,里面装满了需要register_globals开启的代码。其中大部分是由多年来来来往往的随机人员编写的自定义代码。我已经在我知道的脚本中修复了大部分问题,但我的问题是找到我不知道的脚本。

我正在考虑编写一个应用程序来扫描 Web 服务器上的每个目录,以识别需要register_globals. 有没有一个好的策略来做到这一点?

我考虑过的一种方法是强制 PHP 报告所有错误、执行脚本和检查未定义的变量通知。我可以为此构建一个读取STDERR流的应用程序。

你能想到什么更好的方法吗?

4

5 回答 5

7

大多数 IDE 会显示未定义的变量,例如PHPStorm。您可以让它扫描您的所有源文件,并且您将收到有关所有代码中未定义变量的通知,而实际执行它的白化。

这可能是最简单和无痛的变体。或者,您显然可以使用Tokenizer编写自己的脚本并识别所有T_VARIABLE之前未使用T_VARIABLE '=' expr构造初始化的 s。但这将更容易出错。使用 IDE 可能会以更少的努力为您带来更好的结果。

于 2011-02-03T18:44:55.077 回答
3

假设单个文件始终使用打开或关闭的 register_globals,您可以创建提交给脚本的所有表单元素名称的列表,然后检查该脚本是否在$fieldname不包含$_REQUEST['fieldname'](或$_POST,$_GET数组)的情况下使用。

如果您在进行这些检查时可以保证非常高的代码覆盖率(以确保您没有遗漏任何内容 - 然后必须手动检查未覆盖的部分),那么您的“检查通知”方法就可以了。

于 2011-02-03T18:40:20.333 回答
2

虽然检查您的日志以了解编写期望全局变量的脚本的症状可能会有所帮助,但通读代码是真正做到这一点的唯一方法。如果您想自动执行此操作,则需要构建或依赖 PHP 解释器;否则你注定会错过嵌套在条件、潜在评估等中的东西。

于 2011-02-03T18:42:44.653 回答
1

有一种方法可以定位在运行代码中作为字符串的寄存器全局变量的用法。您可以创建以下脚本并使用 PHP auto_prepend_file ini 选项将其添加到现有代码中。

<?php

class revealGlobalsUsage {

    public $globalName;
    public $globalVal;

    public function __construct($name, $val)
    {
        $this->globalName = $name;
        $this->globalVal = $val;
    }

    public function __toString()
    {
        $backtrace = debug_backtrace();

        // log backtrace here...

        return $this->globalVal;
    }
}

// overwrite globals that have been set from GET and POST requests
foreach ($_REQUEST as $name => $val) {
    // Strings that are cast to integers will fail as there 
    // is no __toString equivalent for integers/bool/float etc.
    if (is_string($val) && !is_numeric($val)) {
        $GLOBALS[$name] = new revealGlobalsUsage($name, $val);
    }

    // You can log all GET/POST requests here...
}

对于整数等,您需要修补您的 PHP:https ://gist.github.com/ircmaxell/1966809

于 2015-07-27T07:00:55.257 回答
1

我自己在包含数千个文件的庞大代码库中遇到了这个问题。受@sschueller 发布的解决方案的启发,我测试了这个 auto_prepend_file 代码,该代码记录事件以供调查。此方法还应与解析/标记化结合使用以捕获所有事件。

<?php

$vars = get_defined_vars();

foreach ($vars as $var => $value) {
    if (in_array($var, array('$_SERVER', '$_REQUEST', '$_GET', '$_POST', '$_COOKIE', '$_SESSION', '$_FILES', '$_ENV'))) {
        // only examine the local symbols, not superglobals
        continue;
    }

    if (array_key_exists($var, $_REQUEST) && $value == $_REQUEST[$var]) {
        error_log(sprintf("register_globals reliance detected in %s for variable %s=%s", $_SERVER['SCRIPT_FILENAME'], $var, $value), 3, "/var/tmp/register_globals.log");
    }
}
于 2017-09-06T02:56:52.400 回答