2011-02-03 12 views
8

Ho ereditato un server Web pieno di codice che richiede register_globals di essere attivo. La maggior parte è un codice personalizzato scritto da persone casuali che sono andate e venute nel corso degli anni. Ne ho fissato la maggior parte in script che conosco, ma il mio problema è trovare quelli che non conosco.Ricerca di script PHP che richiedono register_globals

Sto pensando di scrivere un'applicazione per eseguire la scansione di ogni directory sul server Web per identificare gli script PHP che richiedono register_globals. C'è una buona strategia per farlo?

Un metodo che ho preso in considerazione implica in qualche modo forzare PHP a segnalare tutti gli errori, a eseguire script ea controllare le notifiche di variabili non definite. Potrei creare un'applicazione che legge il flusso STDERR per questo.

Ci sono metodi migliori a cui puoi pensare?

+3

+1 per non semplicemente usando 'estratto()' per ottenere il codice di merda di lavoro, ma in realtà il fissaggio – ThiefMaster

risposta

6

La maggior parte degli IDE mostra le variabili non definite, ad esempio PHPStorm. Puoi lasciarlo scansionare tutti i tuoi file sorgente e sarai informato delle variabili non definite in tutto il tuo codice, whiteout effettivamente in esecuzione.

Questa è probabilmente la variante più semplice e indolore. In alternativa si potrebbe, ovviamente, scrivere il proprio script utilizzando la Tokenizer e identificare tutti i T_VARIABLE s, che non sono precedentemente inizializzata con un costrutto T_VARIABLE'='expr. Ma questo sarà più incline agli errori. Usando l'IDE probabilmente otterrai risultati migliori con meno sforzo.

+0

Grazie, non sapevo di PHPStorm. Darò questa prova più tardi oggi. Potrei anche dare un'occhiata a Tokenizer. Quella strada probabilmente sarebbe eccessiva solo per me, ma forse costruirò qualcosa con essa e la renderò disponibile ad altri. – Brad

+0

@Brad: E hai usato PHPStorm? O hai scritto qualcosa da te? – NikiC

+0

Sto aspettando che PHPStorm torni dalla mia licenza educativa gratuita. Hanno un processo di approvazione manuale a quanto pare. Guardandoci sopra, credo che svolgerà il lavoro, o almeno aiuterà in modo significativo. – Brad

3

Supponendo che i singoli file sono sempre utilizzando register_globals essere acceso o spento, è possibile creare un elenco di tutti i nomi degli elementi forma che vengono sottoposti ad uno script e quindi controllare questo script se sta usando $fieldname senza contenere $_REQUEST['fieldname'] (o il $_POST, $_GET array).

Il metodo di "verifica delle notifiche" sarebbe ok se si può garantire una copertura del codice molto elevata durante questi controlli (per assicurarsi di non aver perso nulla: le parti scoperte devono essere controllate manualmente).

+0

Il problema è che non ho modo di sapere ciò che viene sottoposto ad uno script.Non sto parlando di poche pagine qua e là, o anche contenute applicazioni ... ma oltre 200.000 pagine Web e script PHP. Molti di questi script fanno riferimento ad altri script e alcuni script gestiscono i post di altri server/siti. Buon punto su possibili percorsi di codice. Supponevo che PHP generasse un 'E_NOTICE' per questo in qualsiasi parte del codice, ma ho realizzato che non sarebbe stato possibile fino a quando non ha eseguito il codice usando il riferimento. – Brad

2

Mentre esaminare i log per i sintomi degli script scritti in attesa di vars globali può essere utile, leggere il codice è l'unico modo per farlo davvero. Se si desidera automatizzare questo, è necessario creare o fare affidamento su un interprete PHP; altrimenti sei destinato a perdere roba annidata all'interno di condizioni, potenziali evasioni, ecc.

+0

Grazie per i vostri commenti. Speravo di trovare un modo per fare affidamento su PHP.exe, ma come hai fatto notare, semplicemente eseguendolo mancheranno gli elementi nelle dichiarazioni condizionali. Sembra che il metodo manuale sia la strada da percorrere, se alcuni IDE PHP non possono aiutarmi a identificarli. – Brad

1

C'è un modo per individuare gli utilizzi di Globale di registro che sono stringhe nel codice di esecuzione. È possibile creare il seguente script e utilizzare le opzioni PHP auto_prepend_file per anteporlo al codice esistente.

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

Per gli interi, ecc si avrebbe bisogno di patch per il PHP: https://gist.github.com/ircmaxell/1966809

1

mi sono imbattuto in questo problema me stesso in una enorme base di codice con migliaia di file. Ispirato alla soluzione pubblicata da @sschueller ho testato questo codice auto_prepend_file che registra le occorrenze per l'investigazione. Questo metodo dovrebbe anche essere usato insieme a parsing/tokenizing per catturare tutte le occorrenze.

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