2011-02-03 41 views
8

我继承了一个充满代码的Web服务器,需要register_globals才能打开。其中大部分是由随机人员编写的自定义代码,这些人随着时间的流逝而变化。我已经将它的大部分内容解决了我所知道的脚本,但是我的问题是找到我不知道的脚本。查找需要register_globals的PHP脚本

我正在考虑编写一个应用程序来扫描Web服务器上的每个目录,以识别需要register_globals的PHP脚本。有这样做的好策略吗?

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

有没有更好的方法可以想到?

+3

+1不是简单地使用`提取物()`让蹩脚的代码的工作,但实际上将其固定 – ThiefMaster 2011-02-03 18:41:07

回答

6

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

这可能是最简单和无痛的变体。或者,您可以明显使用Tokenizer编写自己的脚本,并确定所有T_VARIABLE,这些文件以前未使用T_VARIABLEexpr构造来初始化。但这会更容易出错。使用IDE可能会以更少的努力为您提供更好的结果。

+0

谢谢,我不了解PHPStorm。今天晚些时候我会试一试。我也可以看看Tokenizer。那条路线对我来说可能是过火,但也许我会用它来构建一些东西,然后发布给其他人使用。 – Brad 2011-02-03 20:05:10

3

假设单个文件总是使用register_globals为打开或关闭,您可以创建它们提交给脚本,然后如果它使用$fieldname不含$_REQUEST['fieldname'](或$_POST检查该脚本中的所有表单元素名称的列表,$_GET阵列)。

如果您在执行这些检查时可以保证非常高的代码覆盖率(以确保您不会错过任何东西 - 那么必须手动检查未覆盖的部分),您可以“检查通知”方法。

+0

麻烦的是,我不知道什么被提交到脚本的方式。我不是在讨论几个页面,甚至包含应用程序......但是有200,000多个网页和PHP脚本。很多这些脚本引用其他脚本,并且一些脚本处理来自其他服务器/站点的帖子。关于可能的代码路径的好处。我假定PHP为代码中的任何位置生成了一个`E_NOTICE`,但是直到它使用引用执行代码时才意识到这是不可能的。 – Brad 2011-02-03 19:59:44

2

虽然检查您的日志以了解写入期望全局变量的脚本的症状可能会有所帮助,但通过代码阅读是真正做到这一点的唯一方法。如果你想自动化这个,你需要建立或依靠一个PHP解释器;否则你注定会错过嵌套条件内的东西,潜在的evals等。

+0

感谢您的意见。我希望找到一种方法来依赖于PHP.exe,但正如您已经指出的那样,仅仅执行它就会错过条件语句中的项目。看起来像手动方法可能是一条路,如果某些PHP IDE无法帮助我识别它们。 – Brad 2011-02-03 20:04:15

1

有一种方法可以找到使用注册全局变量,它们是运行代码中的字符串。您可以创建以下脚本,并使用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

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"); 
    } 
}