Vulnerabilità
La direttiva register_globals del php.ini, se abilitata, permette allo script PHP di creare variabili globali secondo quanto ricevuto via query string, form, cookies o sessione.
Consideriamo il seguente URL: test.php?documento=4&pagina=2. Nel caso la direttiva fosse attivata, per esso verranno create due variabili (globali) con i nomi e valori indicati dalle stringhe. Questo metodo di trattamento dati, inizialmente creato per semplicità di notazione (le scritture $_GET['documento'] o $documento sono in questo caso equivalenti), successivamente ha suscitato l'attenzione degli sviluppatori in quanto possibile veicolo di exploit su codice mal congegnato.
Poniamo infatti che la direttiva register_globals sia abilitata e l'applicazione Web PHP abbia al suo interno una funzione simile alla seguente:
<?
function autenticazione()
{
if (procedura_complicatissima) return true;
else return false;
}
// main
if (autenticazione()) $utente_autorizzato = true;
if ($utente_autorizzato)
{
echo "Benvenuto utente autorizzato.";
il_resto_dello_script();
}
?>
La funzione autenticazione() autentica l'utente, in base a qualsiasi metodo il programmatore ritenga opportuno, ed il risultato di tale procedura è memorizzato nella variabile $utente_autorizzato.
Tuttavia, non è assolutamente necessario che un cracker (che conosca comunque il codice del programma) superi la procedura di autenticazione per accedere al sistema: è sufficiente richiamare lo script come in figura, in quanto $utente_autorizzato è ugualmente valorizzato dalla variabile in GET.
Poiché il cracker deve conoscere i dettagli del codice, va da sé che tali vulnerabilità riguardano essenzialmente gli applicativi open source.
Per nostra fortuna, infine, la direttiva in questione generalmente è oramai sempre disabilitata: stiamo solo attenti a non aprire vulnerabilità ormai in pensione modificandone il valore.
Soluzioni
La direttiva register_globals deve essere impostata ad OFF, l'abbiamo già capito.
In ogni modo, che si intenda impostare register_globals ad OFF o no, l'esempio sopra riportato mostra l'importanza di definire ed inizializzare tutte le variabili usate nello script, all'inizio dello stesso. Mentre altri linguaggi obbligano a farlo, PHP si dimostra decisamente più permissivo al riguardo. Aggiungendo infatti l'inizializzazione della variabile $utente_autorizzato ad inizio script, l'exploit non funziona nemmeno con register_globals impostato ad ON:
// main
$utente_autorizzato = false;
Durante lo sviluppo del programma è inoltre consigliabile impostare, sempre nel file php.ini, la direttiva error_reporting ad E_ALL. Con questa impostazione, PHP evidenzia in fase di runtime ogni variabile non inizializzata:
Notice: Undefined variable: variabile in percorsocartellascript.php on line xx
Non dimentichiamo, una volta terminata la fase di produzione, di impostare error_reporting in modo che ogni tipo di errore non venga più visualizzato, in quanto ogni output di questo tipo rivela la struttura interna del programma, intesa come nome e percorso degli script e via discorrendo. E il cracker non aspetta altro.
Come qui:
FPDF error: Unable to create output file:
../manuali/15022-MANUALI-MGCI--2006391/man/lista_manutenzioni.pdf
PHP Warning: stat failed for
../manuali/15022-MANUALI-MGCI--2006391/fscommand/manuali.list.xml
(errno=2 - No such file or directory) in E:xxxmanual_maker_mm_funct.php on line 208
Distinguere quindi tra direttive del php.ini in- e post-produzione.