Поиск PHP-скриптов, требующих register_globals

Я унаследовал веб-сервер, заполненный кодом, который требует, чтобы register_globals был включен. По большей части это пользовательский код, написанный случайными людьми, которые приходили и уходили на протяжении многих лет. Я исправил большую часть этого в скриптах, о которых я знаю, но моя проблема заключается в том, чтобы найти те, о которых я не знаю.

Я рассматриваю возможность написания приложения для сканирования каждого каталога на веб-сервере, чтобы идентифицировать PHP-скрипты, требующие register_globals. Есть ли хорошая стратегия для этого?

Один метод, который я рассматривал, заключается в том, чтобы каким-то образом заставить PHP сообщать обо всех ошибках, выполнять сценарии и проверять уведомления о неопределенных переменных. Для этого я мог бы создать приложение, которое читает поток STDERR.

Есть ли какие-нибудь лучшие методы, которые вы можете придумать?


person Brad    schedule 03.02.2011    source источник
comment
+1 за то, что не просто использовал extract() для того, чтобы заставить дрянной код работать, но и фактически исправил его.   -  person ThiefMaster    schedule 03.02.2011


Ответы (5)


Большинство IDE показывают вам неопределенные переменные, например PHPStorm. Вы можете позволить ему сканировать все ваши исходные файлы, и вы будете уведомлены о неопределенных переменных во всем вашем коде, фактически выполняя его.

Это, наверное, самый простой и безболезненный вариант. В качестве альтернативы вы можете написать свой собственный скрипт, используя Tokenizer, и идентифицировать все T_VARIABLE, которые ранее не были инициализированы с помощью T_VARIABLE '='. expr конструкция. Но это будет более подвержено ошибкам. Использование IDE, вероятно, даст вам лучшие результаты с меньшими усилиями.

person NikiC    schedule 03.02.2011
comment
Спасибо, я не знал о PHPStorm. Я попробую это позже сегодня. Я мог бы также взглянуть на Tokenizer. Этот маршрут, вероятно, будет излишним только для меня, но, возможно, я создам что-нибудь с ним и выпущу его для использования другими. - person Brad; 03.02.2011
comment
@Brad: А вы использовали PHPStorm? Или вы сами что-то написали? - person NikiC; 04.02.2011
comment
Я жду ответа от PHPStorm по поводу моей бесплатной образовательной лицензии. Кажется, у них есть процесс утверждения вручную. Однако, глядя на это, я верю, что это сделает работу или, по крайней мере, значительно поможет. - person Brad; 04.02.2011
comment
@Brad: У них есть демо-версия, которую вы можете использовать в течение 45 дней, я думаю;) - person NikiC; 04.02.2011

Предполагая, что отдельные файлы всегда используют включенный или выключенный параметр register_globals, вы можете создать список всех имен элементов формы, которые отправляются в скрипт, а затем проверить этот скрипт, использует ли он $fieldname без содержания $_REQUEST['fieldname'] (или массивов $_POST, $_GET).

Ваш метод "проверки на наличие уведомлений" будет приемлемым, если вы можете гарантировать очень высокий охват кода при выполнении этих проверок (чтобы убедиться, что вы ничего не пропустили - непокрытые части затем должны быть проверены вручную).

person ThiefMaster    schedule 03.02.2011
comment
Проблема в том, что у меня нет возможности узнать, что передается сценарию. Я говорю не о нескольких страницах здесь и там, или даже о приложениях... но о более чем 200 000 веб-страниц и PHP-скриптов. Многие из этих скриптов ссылаются на другие скрипты, а некоторые скрипты обрабатывают сообщения с других серверов/сайтов. Хороший вопрос о возможных путях кода. Я предполагал, что PHP генерирует E_NOTICE для этого в любом месте кода, но просто понял, что это будет невозможно, пока он не выполнит код, используя ссылку. - person Brad; 03.02.2011

Хотя изучение ваших журналов на наличие признаков сценариев, написанных с ожиданием глобальных переменных, может быть полезным, чтение кода — единственный способ сделать это. Если вы хотите автоматизировать это, вам нужно будет создать или положиться на интерпретатор PHP; в противном случае вам суждено пропустить вещи, вложенные в условия, потенциальные оценки и т. д.

person coreyward    schedule 03.02.2011
comment
Спасибо за ваши комментарии. Я надеялся найти способ полагаться на PHP.exe, но, как вы указали, простое его выполнение пропустит элементы в условных операторах. Похоже, что ручной метод может быть подходящим, если какая-то PHP IDE не может помочь мне их идентифицировать. - person Brad; 03.02.2011

Существует способ найти использование глобальных переменных регистрации, которые являются строками в работающем коде. Вы можете создать следующий скрипт и использовать 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

person sschueller    schedule 27.07.2015

Я сам столкнулся с этой проблемой в огромной кодовой базе с тысячами файлов. Вдохновленный решением, опубликованным @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");
    }
}
person roktechie    schedule 06.09.2017