Pregunta

He heredado un servidor web lleno de código que requiere register_globals para estar en. La mayor parte es un código personalizado escrito por personas aleatorias que han ido y venido a lo largo de los años. He solucionado la mayoría en los guiones que conozco, pero mi problema es encontrar los que no conozco.

Estoy considerando escribir una aplicación para escanear a través de cada directorio en el servidor web para identificar scripts de PHP que requieren register_globals. ¿Hay una buena estrategia para hacer esto?

Un método que he considerado implica de alguna manera obligar a PHP a informar todos los errores, ejecutar scripts y verificar los avisos variables indefinidos. Podría crear una aplicación que lea el STDERR transmitir para esto.

¿Hay algún método mejor que se te ocurra?

¿Fue útil?

Solución

La mayoría de los ides le mostrarán variables indefinidas, Tormenta php lo hace, por ejemplo. Puede dejar que escanee todos sus archivos de origen y se le notificará sobre variables indefinidas en todo su código, lo que realmente lo ejecuta.

Esta es probablemente la variante más simple e indolora. Alternativamente, obviamente podrías escribir tu propio script utilizando el Tokenizador e identificar todo T_VARIABLEs, que no se inicializan previamente usando un T_VARIABLE '=' expr construir. Pero esto será más propenso a errores. Usar el IDE probablemente le dará mejores resultados con menos esfuerzo.

Otros consejos

Suponiendo que los archivos únicos siempre están utilizando registro_globals que está encendido o desactivado, puede crear una lista de todos los nombres de elementos de formulario que se envían a un script y luego verifique este script si está usando $fieldname sin contener $_REQUEST['fieldname'] (o el $_POST, $_GET matrices).

Su método de "verificar los avisos" estaría bien si puede garantizar una cobertura de código muy alta mientras realiza esos cheques (para asegurarse de que no se pierda nada; las piezas descubiertas deben verificarse manualmente).

Si bien examinar sus registros para ver los síntomas de los scripts escritos que esperan Vars globales pueden ser útiles, leer el código es la única forma de hacerlo realmente. Si quisiera automatizar esto, necesitaría construir o confiar en un intérprete PHP; De lo contrario, está destinado a perderse cosas anidadas dentro de las condiciones, posibles evals, etc.

Hay una manera de localizar usos de registrar globals que son cadenas en la ejecución del código. Puede crear el siguiente script y usar el PHP auto_prepend_file Opciones de INI para prevenirlo con su código existente.

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

Para enteros, etc. Debería parchear su PHP: https://gist.github.com/ircmaxell/1966809

Me encontré con este problema en una enorme base de código con miles de archivos. Inspirada en la solución publicada por @SSChueller He probado este código Auto_Prepend_File que inicia sesión para la investigación. Este método también debe usarse junto con el análisis/tokenización para atrapar todos los ocurrencias.

<?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");
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top