2011-02-03 5 views
8

J'ai hérité d'un serveur web rempli de code qui nécessite register_globals pour être activé. La plupart d'entre elles est un code personnalisé écrit par des personnes au hasard qui sont venues et reparties au fil des ans. J'ai réparé la majorité dans des scripts que je connais, mais mon problème est de trouver ceux que je ne connais pas.Trouver des scripts PHP qui nécessitent register_globals

Je considère écrire une application pour balayer chaque répertoire sur le serveur Web pour identifier les manuscrits de PHP qui exigent register_globals. Y a-t-il une bonne stratégie pour le faire?

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

Y at-il de meilleures méthodes que vous pouvez penser?

+3

+1 pour ne pas utiliser simplement 'extract()' pour obtenir le code de travail merdique mais en fait fixer – ThiefMaster

Répondre

6

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

Il s'agit probablement de la variante la plus simple et indolore. Sinon, vous pouvez évidemment écrire votre propre script en utilisant le Tokenizer et identifier tous les T_VARIABLE, qui ne sont pas initialisés à l'aide d'une construction T_VARIABLE'='expr. Mais ce sera plus enclin à l'erreur. L'utilisation de l'IDE vous donnera probablement de meilleurs résultats avec moins d'effort.

+0

Merci, je ne connaissais pas PHPStorm. Je vais essayer ça plus tard aujourd'hui. Je pourrais aussi jeter un oeil à Tokenizer. Cette route serait probablement exagérée pour moi seulement, mais peut-être que je vais construire quelque chose avec elle, et la libérer pour que d'autres puissent l'utiliser. – Brad

+0

@Brad: Et, avez-vous utilisé PHPStorm? Ou avez-vous écrit quelque chose vous-même? – NikiC

+0

J'attends sur PHPStorm pour me revenir sur ma licence éducative gratuite. Ils ont un processus d'approbation manuelle, il semble. En regardant par-dessus cependant, je crois que cela fera l'affaire, ou au moins aider de manière significative. – Brad

3

En supposant des fichiers individuels utilisent toujours register_globals ou désactiver, vous pouvez créer une liste de tous les noms d'éléments de forme qui sont soumis à un script, puis vérifiez ce script s'il utilise $fieldname sans contenir $_REQUEST['fieldname'] (ou $_POST, $_GET tableaux). Votre méthode de «vérification des notifications» serait acceptable si vous pouvez garantir une couverture de code très élevée pendant ces vérifications (pour vous assurer de ne rien manquer - les parties non couvertes doivent ensuite être vérifiées manuellement).

+0

Le problème est, je n'ai aucun moyen de savoir ce qui est soumis à un script.Je ne parle pas de quelques pages ici et là, ou même d'applications contenues ... mais plus de 200 000 pages web et scripts PHP. Un grand nombre de ces scripts font référence à d'autres scripts, et certains scripts gèrent des messages provenant d'autres serveurs/sites. Bon point sur les chemins de code possibles. Je supposais que PHP générait un 'E_NOTICE' pour cela n'importe où dans le code, mais je me suis rendu compte que cela ne serait pas possible avant d'avoir exécuté le code en utilisant la référence. – Brad

2

Lors de l'examen de vos journaux pour les symptômes de scripts écrits en attente de vars globales peut être utile, la lecture du code est la seule façon de vraiment le faire. Si vous vouliez automatiser cela, vous auriez besoin de construire ou de compter sur un interpréteur PHP; sinon vous êtes destiné à rater des choses imbriquées dans des conditions, des évaluations potentielles, etc.

+0

Merci pour vos commentaires. J'espérais trouver un moyen de faire confiance à PHP.exe, mais comme vous l'avez souligné, il suffit de l'exécuter pour manquer des éléments dans les instructions conditionnelles. Cela ressemble à la méthode manuelle peut être la voie à suivre, si certains IDE PHP ne peuvent pas m'aider à les identifier. – Brad

1

Il existe un moyen de localiser les utilisations de globales de registre qui sont des chaînes dans le code en cours d'exécution. Vous pouvez créer le script suivant et utiliser les options ini PHP auto_prepend_file pour l'ajouter à votre code existant.

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

Pour les entiers, etc. vous devrez patcher votre PHP: https://gist.github.com/ircmaxell/1966809

1

je suis tombé sur moi-même problème dans une énorme base de code avec des milliers de fichiers. Inspiré par la solution postée par @sschueller, j'ai testé ce code auto_prepend_file qui enregistre les occurrences à investiguer. Cette méthode doit également être utilisée conjointement avec l'analyse/tokenizing pour capturer toutes les 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"); 
    } 
} 
Questions connexes