Question

J'ai hérité d'un serveur Web rempli de code qui nécessite que register_globals soit activé.La plupart sont du code personnalisé écrit par des personnes aléatoires qui sont allées et venues au fil des ans.J'en ai corrigé la majorité dans des scripts que je connais, mais mon problème est de trouver ceux que je ne connais pas.

J'envisage d'écrire une application pour parcourir tous les répertoires du serveur Web afin d'identifier les scripts PHP qui nécessitent register_globals.Existe-t-il une bonne stratégie pour y parvenir?

Une méthode que j'ai envisagée consiste à forcer PHP à signaler toutes les erreurs, à exécuter des scripts et à vérifier les notifications de variables non définies.Je pourrais créer une application qui lit le flux STDERR pour cela.

Y a-t-il de meilleures méthodes auxquelles vous pouvez penser?

Était-ce utile?

La solution

La plupart des IDE vous montreront des variables non définies, comme PHPStorm par exemple.Vous pouvez le laisser analyser tous vos fichiers source et vous serez averti des variables non définies dans tout votre code, le blanc l'exécutant réellement.

C'est probablement la variante la plus simple et la plus indolore.Sinon, vous pouvez évidemment écrire votre propre script en utilisant le Tokenizer et identifier tous les T_VARIABLEs, qui n'ont pas été initialisés auparavant à l'aide d'un T_VARIABLE '='construction expr.Mais ce sera plus sujet aux erreurs.L'utilisation de l'EDI vous donnera probablement de meilleurs résultats avec moins d'effort.

Autres conseils

Assuming single files are always using register_globals being on or off, you could create a list of all form element names which are submitted to a script and then check this script if it's using $fieldname without containing $_REQUEST['fieldname'] (or the $_POST, $_GET arrays).

Your "check for notices" method would be ok if you can guarantee a very high code coverage while doing those checks (to ensure you didn't miss anything - the uncovered parts then have to be checked manually).

While examining your logs for symptoms of scripts written expecting global vars can be helpful, reading through the code is the only way to really do this. If you wanted to automate this, you would need to build or rely on a PHP interpreter; otherwise you're destined to miss stuff nested inside of conditions, potential evals, etc.

There is a way to locate usages of register globals that are strings in running code. You can create the following script and use the PHP auto_prepend_file ini options to prepend it to your existing code.

<?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...
}

For integers etc. you would need to patch your PHP: https://gist.github.com/ircmaxell/1966809

I ran into this problem myself in an enormous codebase with thousands of files. Inspired by the solution posted by @sschueller I have tested this auto_prepend_file code which logs occurrences for investigation. This method should also be used in conjunction with parsing/tokenizing to catch all occurrences.

<?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");
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top