PHP: sessioni e sicurezza
This entry was posted on January 28th, 2009 and is filed under php, sicurezza.
Questo articolo nasce da una recente discussione avuta con un mio lettore, Massimo, che ringrazio per la lunga chiacchierata!
Lo scopo di questo articolo non è insegnare ad usare le sessioni con il PHP, bensì quello di spiegare cosa non fare quando si lavora con le sessioni!
Molto probabilmente seguiranno altri articoli che tratterano di SQL Injections e le altre tecniche da cui bisogna salvaguardare i nostri progetti onde evitare spiacevoli sorprese; nel frattempo tratterò semplicemente alcuni consigli da seguire quando si ha a che fare con le sessioni.
Una pratica assolutamente sbagliata nella gestione delle sessioni è quella di utilizzare funzioni come session_register(), session_unregister() e session_is_registered().
Tali funzioni vanno ad operare sulle variabili di sessione inserite in un’ambiente globale, e ciò è molto pericoloso in quanto tale utilizzo può essere sfruttato da un aggressore per guadagnare diritti di accesso in maniera illecita, vediamo come.
L’utilizzo di quelle funzioni può portare a scrivere codice del genere:
<?php
session_start();
session_register("ok");
....
if(autenticazione_user())
$ok=1;
else
$ok=0;
?>
<?php
global $ok;
....
if($ok) {
....
// sezione privata
....
}
?>
questo codice basa l’autenticazione sulla variabile $ok, provate ad immaginare cosa può succedere se l’aggressore richiama da browser file2.php nel seguente modo:
http://www.sito.it/file2.php?ok=1
Inevitabilmente l’autenticazione sarebbe compromessa.
Purtroppo quando si parla di sicurezza non si può sperare che le cose vadano per il verso giusto, sperando magari che nessuno riesca mai ad indovinare (o a conoscere) il nome della variabile utilizzata per ricordare lo stato di connessione dell’utente.
Infatti è abitudine di tutti i programmatori associare sempre ai nomi di variabili un significato, in modo da rendere il codice leggibile e facilmente modificabile, pertanto, una variabile del genere avrò nomi tipo:
logged_in, logged, loggato, ok, ammesso, entrato e così via…
Ciò sta a significare che il rischio c’è sempre e che non può essere tralasciato.
Per risolverlo basta utilizzare l’array globale $_SESSION e utilizzare anche per gli altri metodi di passaggio informazione i vari array globali illustrati. Questo perché $ok è diverso da $_SESSION['ok'].
A ciò si può aggiungere la possibilità di disabilitare l’ambiente globale delle variabili andando a modificare la variabile register_globals contenuta nel file di configurazione del PHP (php.ini) assegnandole il valore Off come riportato di seguito:
register_globals = Off
Questo può essere fatto soltanto dal gestore del server web, pertanto se siete clienti di un servizio di hosting potete verificare il settaggio della variabile utilizzando una pagina php con il seguente codice:
<?php phpinfo(); ?>
Attualmente tale variabile è settata ad on sulla maggior parte dei server, questo perché molti script PHP passati utilizzano l’ambiente globale.
La retrocompatibilità però non ci deve portare a commettere gli errori del passato, pertanto ogni nuovo script deve essere scritto pensando alla sicurezza, e quindi utilizzando gli array globali ($_SESSION, $_GET, $_POST e $_COOKIE).
Nel caso si voglia utilizzare il codice di qualcun altro, consiglio sempre di verificare la modalità del trattamento dei dati delle sessioni.
Questo frammento di articolo è tratto da: Guida alle sessioni in PHP di Davide Coppola.
L’ho postato in quanto è secondo me la base di partenza per realizzare uno script sicuro. Purtroppo la sicurezza assoluta non credo si avrà mai dato che i modi per rubare i dati di accesso o comunque far danni ne sono davvero tanti; questo però non deve di certo portarci a trascurare l’utilizzo di tutte le tecniche che abbiamo a disposizione per rendere difficile la vita ai malintenzionati.
Un altro errore che spesso viene compiuto è quello di lasciare le password in chiaro nel database. Per molti sembrerà una cosa scontata criptare le password ma fidatevi, sono ancora in molti che lasciano la password in chiaro nel db. Anche utilizzare un sistema di criptaggio come MD5 ormai non garantisce una alta sicurezza in quanto cresce sempre di più il numero di siti che “aiutano” nel decriptaggio di quest’ultime. Per questo che come primo consiglio che dò è non lasciare la password in chiaro nel database ma affidarsi a sistemi di criptaggio come SHA1 o MD5. Il secondo consiglio che dò è quello di rendere ancora più difficile la vita dei malintenzionati combinando tra di loro questi sistemi in modo da complicare e di molto la possibilitàdi utilizzare tecniche di brute-force. Un esempio potrebbe essere quello di utilizzare un criptaggio MD5 due volte sulla password come nel seguente codice:
<?php $password = md5( md5( "prova" ) ); ?>
Cosi facendo la stringa password non contiene l’hash di “prova”, bensi (permettetemi il giro di parole) l’hash dell’hash di “prova”. Banale trucchetto ma molto più sicuro di una singola “passata”. Ultimo consiglio sulle password ma non ultimo per importanza: non usare password brevi o semplici. Una password per essere sicura deve essere di ALMENO 8 caratteri e contenere al suo interno:
- caratteri alfabetici minuscoli e maiuscoli
- caratteri numerici
- caratteri alfanumerici
Un esempio di password sicura è: Df_32*dwrW
Sfido chiunque con il brute-force a scoprire una password del genere senza metterci qualche millennio!
Per terminare questo articolo parliamo dell punto più delicato di tutto l’argomento: i file di sessione. Le sessioni PHP vengono propagate tramite il SID, stringa “univoca” che identifica una data sessione, puntando il file di sessione sul server Web. La sicurezza dei file di sessione diviene a questo punto un problema sistemistico: è necessario configurare il server in modo che nessuno possa accedere da remoto a tali file e che nessuna applicazione “estranea” possa aprirli in lettura e/o scrittura. Le relative problematiche vanno (ben) al di là della presente guida.
Tuttavia, pur dando per scontato quanto sopra, la situazione non è rosea: se infatti l’applicazione PHP risiede su spazio Web in hosting (e solo in questo caso può nascere il problema), è verosimile che tutti i file di sessione di tutte le applicazioni vengano salvati assieme: di qui a che un’applicazione PHP bacata o appositamente studiata possa visualizzare il contenuto di ogni file il passo è breve. Di default, i file di sessione sono appunto salvati nella medesima cartella, col risultato che se uno script legge un suo file di sessione, allora quello stesso file viene letto da un qualsiasi altro script di una qualsiasi altra applicazione che giri sullo stesso Web server (quindi coi medesimi permessi).
Le soluzioni sono di impostare, via script, tramite la direttiva ini_set (da usare prima del session_start() e per ogni pagina dello script), i parametri relativi alle sessioni (session.save_path in primis), differenziando la cartella temporanea relativa al proprio programma dalle altre cartelle temporanee, oppure di salvare le sessioni su database.
La seguente riga di codice imposta quale directory di salvataggio dei file di sessione il path percorsomydir (che diventa percorso/mydir/ su sistemi Linux o Unix like):
<?php
ini_set("session.save_path","percorso/mydir/");
?>
Spero che con questa piccola raccolta di consigli sull’argomento abbia soddisfatto la curiosità di molti che si avvicinano da poco all’argomento e, per qualunque precisazione, consiglio o critica potete tranquillamente contattarmi!









