Sicurezza sessione PHP


125

Quali sono alcune linee guida per mantenere la sicurezza della sessione responsabile con PHP? Ci sono informazioni su tutto il Web ed è giunto il momento che tutto atterri in un unico posto!

Risposte:


88

Ci sono un paio di cose da fare per proteggere la sessione:

  1. Utilizzare SSL per autenticare gli utenti o eseguire operazioni sensibili.
  2. Rigenerare l'id di sessione ogni volta che cambia il livello di sicurezza (come l'accesso). Se lo desideri, puoi anche rigenerare l'id di sessione per ogni richiesta.
  3. Avere sessioni scadute
  4. Non usare i globi registrati
  5. Memorizzare i dettagli di autenticazione sul server. Cioè, non inviare dettagli come nome utente nel cookie.
  6. Controlla il $_SERVER['HTTP_USER_AGENT']. Ciò aggiunge una piccola barriera al dirottamento della sessione. Puoi anche controllare l'indirizzo IP. Ma ciò causa problemi agli utenti che hanno cambiato l'indirizzo IP a causa del bilanciamento del carico su più connessioni Internet ecc. (Che è il caso nel nostro ambiente qui).
  7. Blocca l'accesso alle sessioni sul file system o usa la gestione delle sessioni personalizzata
  8. Per le operazioni sensibili, è necessario richiedere agli utenti che hanno effettuato l'accesso di fornire nuovamente i propri dettagli di autenticazione

15
L'uso di SSL solo per alcune operazioni non è sufficiente, a meno che non si disponga di sessioni separate per il traffico crittografato e non crittografato. Se si utilizza una singola sessione su HTTPS e HTTP, l'attaccante la ruberà alla prima richiesta non HTTPS.
Kornel,

6
-1 l'agente utente è banale da falsificare. Quello che stai descrivendo spreca il codice e non è un sistema di sicurezza.
torre del

24
@ The Rook, può essere una barriera banale (l'attaccante può catturare l'agente utente di una vittima usando il proprio sito) e fa affidamento sulla sicurezza attraverso l'oscurità, ma è ancora una barriera aggiuntiva. Se l'HTTP User-Agent dovesse cambiare durante l'uso della sessione, sarebbe estremamente sospetto e molto probabilmente un attacco. Non ho mai detto che puoi usarlo da solo. Se lo combini con le altre tecniche hai un sito molto più sicuro.
grom

5
@grom Penso che sia come mettere un pezzo di nastro adesivo sulla tua porta e dire che impedirà alle persone di entrare.
Torre

8
Se stai controllando l'agente utente, bloccherai tutte le richieste degli utenti IE8 quando attivano la modalità di compatibilità. Guarda il divertimento che ho avuto per rintracciare questo problema nel mio codice: serverfault.com/questions/200018/http-302-problem-on-ie7 . Sto controllando l'agente utente, perché è una cosa così banale da falsificare, come altri hanno già detto.
bestattendance


11

I miei due (o più) centesimi:

  • Non fidarti di nessuno
  • Filtro input, output escape (cookie, dati di sessione sono anche i tuoi input)
  • Evita XSS (mantieni il tuo HTML ben formato, dai un'occhiata a PHPTAL o HTMLPurifier )
  • Difesa in profondità
  • Non esporre i dati

C'è un piccolo ma buono libro su questo argomento: Essential PHP Security di Chris Shiflett .

Sicurezza PHP essenziale http://shiflett.org/images/essential-php-security-small.png

Nella home page del libro troverai alcuni esempi di codici interessanti e capitoli di esempio.

È possibile utilizzare la tecnica sopra menzionata (IP e UserAgent), descritta qui: Come evitare il furto di identità


+1 per la prevenzione XSS. Senza questo è impossibile proteggersi dal CSRF, e quindi qualcuno può "cavalcare" la sessione senza nemmeno ottenere l'ID della sessione.
Kornel,

11

Penso che uno dei maggiori problemi (che viene affrontato in PHP 6) sia register_globals. In questo momento uno dei metodi standard utilizzati per evitare register_globalsè quello di utilizzare i $_REQUEST, $_GETo $_POSTarray.

Il modo "corretto" per farlo (a partire da 5.2, sebbene sia un po 'buggy lì, ma stabile a partire da 6, che arriverà presto) è attraverso i filtri .

Quindi invece di:

$username = $_POST["username"];

faresti:

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

o anche solo:

$username = filter_input(INPUT_POST, 'username');

2
Questo non ha alcuna relazione con la domanda.
The Pixel Developer

5
Veramente? Allora perché nella risposta accettata menzionano di non usare i globi di registro? Per quanto riguarda la maggior parte degli sviluppatori run-of-the-mill, i registri globali e la gestione delle variabili dei moduli non rientrerebbero sotto l'egida delle "sessioni" anche se tecnicamente non fa parte dell'oggetto "session"?
cmcculloh,

9
Sono d'accordo, questo non risponde pienamente alla domanda, ma fa sicuramente PARTE della risposta alla domanda. Ancora una volta, questo completa un punto elenco nella risposta accettata, "Non usare i globi di registro". Questo dice cosa fare invece.
cmcculloh,


5

L'uso dell'indirizzo IP non è davvero la migliore idea della mia esperienza. Per esempio; il mio ufficio ha due indirizzi IP che vengono utilizzati a seconda del carico e ci imbattiamo costantemente in problemi utilizzando gli indirizzi IP.

Invece, ho optato per l'archiviazione delle sessioni in un database separato per i domini sui miei server. In questo modo nessuno nel file system ha accesso alle informazioni di quella sessione. Questo è stato davvero utile con phpBB prima della 3.0 (da allora l'hanno risolto) ma penso sia comunque una buona idea.


3

Questo è piuttosto banale e ovvio, ma assicurati di session_destroy dopo ogni uso. Questo può essere difficile da implementare se l'utente non si disconnette esplicitamente, quindi è possibile impostare un timer per farlo.

Ecco un buon tutorial su setTimer () e clearTimer ().


3

Il problema principale con le sessioni e la sicurezza di PHP (oltre al dirottamento della sessione) viene dall'ambiente in cui ci si trova. Per impostazione predefinita, PHP memorizza i dati della sessione in un file nella directory temporanea del sistema operativo. Senza pensarci né pianificarlo, questa è una directory leggibile a livello mondiale, quindi tutte le informazioni sulla sessione sono pubbliche a chiunque abbia accesso al server.

Per quanto riguarda il mantenimento delle sessioni su più server. A quel punto sarebbe meglio passare da PHP alle sessioni gestite dall'utente dove chiama le funzioni fornite su CRUD (creare, leggere, aggiornare, eliminare) i dati della sessione. A quel punto è possibile archiviare le informazioni sulla sessione in un database o in una soluzione memcache in modo che tutti i server delle applicazioni abbiano accesso ai dati.

Anche l'archiviazione delle sessioni personali può essere vantaggiosa se ci si trova su un server condiviso perché consente di archiviarlo nel database che spesso si ha più controllo sul file system.


3

Ho impostato le mie sessioni in questo modo-

nella pagina di accesso:

$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);

(frase definita in una pagina di configurazione)

quindi sull'intestazione che si trova in tutto il resto del sito:

session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {       
    session_destroy();
    header('Location: http://website login page/');
    exit();     
}

3

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

eq Apache aggiungere intestazione:

X-XSS-Protection    1

httpd.conf -> <FilesMatch "\. (php | phtml | aspx | htm | html) $"> Set di intestazioni X-XSS-Protection "1" </FilesMatch>
user956584

Ricorda che X-XSS-Protectionnon è affatto utile. In effetti, lo stesso algoritmo di protezione potrebbe effettivamente essere sfruttato, rendendolo peggiore di prima.
Pacerier,

2

Verificherei sia IP che User Agent per vedere se cambiano

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}

5
L'IP può cambiare legittimamente se l'utente si trova dietro una proxy farm con bilanciamento del carico.
Kornel,

2
E user_agent può cambiare ogni volta che un utente aggiorna il proprio browser.
scatta l'

3
@scotts Sono d'accordo con la parte IP ma per l'aggiornamento del browser, imposti la sessione quando effettuano l'accesso, quindi non vedo come aggiornerebbero il browser senza creare una nuova sessione una volta effettuato nuovamente l'accesso.
JasonDavis,

Credo che user_agent possa cambiare anche quando si passa da una modalità compatibile in IE8. È anche molto facile falsificare.

Sì, ma per quanto riguarda gli utenti che avevano un IP statico eq GSM e viene cambiato ogni mezz'ora. Quindi, IP memorizzato nella sessione + nome host, QUANDO IP! = REMOTE_ADDR controlla l'host e confronta hostanmes eq. 12.12.12.holand.nl-> when is holand.nl == true. Ma alcuni host avevano un nome host basato su IP Quindi occorre confrontare la maschera 88.99.XX.XX
user956584

2

Se si utilizza session_set_save_handler () è possibile impostare il proprio gestore sessioni. Ad esempio, è possibile archiviare le sessioni nel database. Fare riferimento ai commenti di php.net per esempi di un gestore di sessioni di database.

Le sessioni DB sono buone anche se si hanno più server, altrimenti se si utilizzano sessioni basate su file, è necessario assicurarsi che ciascun server Web abbia accesso allo stesso filesystem per leggere / scrivere le sessioni.


2

Devi essere sicuro che i dati della sessione siano al sicuro. Guardando php.ini o usando phpinfo () è possibile trovare le impostazioni della sessione. _session.save_path_ ti dice dove sono stati salvati.

Controlla l'autorizzazione della cartella e dei suoi genitori. Non dovrebbe essere pubblico (/ tmp) o essere accessibile da altri siti Web sul tuo server condiviso.

Supponendo che si desideri ancora utilizzare la sessione php, è possibile impostare php in modo che utilizzi un'altra cartella modificando _session.save_path_ o salvando i dati nel database modificando _session.save_handler_.

Potreste essere in grado di impostare _session.save_path_ nel tuo php.ini (alcuni fornitori consentono) o per apache + mod_php, in un file .htaccess nella cartella principale sito: php_value session.save_path "/home/example.com/html/session". Puoi anche impostarlo in fase di esecuzione con _session_save_path () _.

Controlla il tutorial di Chris Shiflett o Zend_Session_SaveHandler_DbTabella per impostare e gestore di sessioni alternativo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.