PHP Session Fixation / Hijacking


145

Sto cercando di capire di più sulla fissazione e il dirottamento della sessione PHP e su come prevenire questi problemi. Ho letto i seguenti due articoli sul sito Web di Chris Shiflett:

Tuttavia, non sono sicuro di capire le cose correttamente.

Per aiutare a prevenire la fissazione della sessione è sufficiente chiamare session_regenerate_id (true); dopo aver effettuato correttamente l'accesso a qualcuno? Penso di capirlo correttamente.

Parla anche dell'utilizzo di token passati negli URL tramite $ _GET per impedire il dirottamento della sessione. Come si farebbe esattamente? Sto indovinando quando qualcuno accede a te genera il suo token e lo memorizza in una variabile di sessione, quindi su ogni pagina confronteresti quella variabile di sessione con il valore della variabile $ _GET?

Questo token dovrebbe essere modificato solo una volta per sessione o ad ogni caricamento della pagina?

Inoltre è un buon modo per prevenire il dirottamento senza dover passare un valore negli URL? questo sarebbe molto più semplice.


Forse potresti aggiungere collegamenti alle pagine in cui hai trovato questi consigli.
Gumbo,

Risposte:


220

Ok, ci sono due problemi separati ma correlati, e ognuno è gestito in modo diverso.

Sessione fissa

È qui che un utente malintenzionato imposta esplicitamente l'identificatore di sessione di una sessione per un utente. In genere in PHP è fatto dando loro un URL come http://www.example.com/index...?session_name=sessionid. Una volta che l'attaccante fornisce l'URL al client, l'attacco è lo stesso di un attacco di dirottamento di sessione.

Esistono alcuni modi per impedire la fissazione della sessione (esegui tutte):

  • Imposta session.use_trans_sid = 0nel tuo php.inifile. Questo dirà a PHP di non includere l'identificatore nell'URL e di non leggere l'URL per gli identificatori.

  • Imposta session.use_only_cookies = 1nel tuo php.inifile. Questo dirà a PHP di non usare mai gli URL con identificatori di sessione.

  • Rigenerare l'ID sessione ogni volta che lo stato della sessione cambia. Ciò significa che uno dei seguenti:

    • Autenticazione utente
    • Memorizzazione di informazioni sensibili nella sessione
    • Cambiare qualcosa sulla sessione
    • eccetera...

Dirottamento della sessione

Qui è dove un utente malintenzionato ottiene un identificativo di sessione ed è in grado di inviare richieste come se fossero quell'utente. Ciò significa che, poiché l'attaccante ha l'identificatore, sono quasi indistinguibili dall'utente valido rispetto al server.

Non è possibile impedire direttamente il dirottamento della sessione. Puoi comunque fare dei passi per renderlo molto difficile e difficile da usare.

  • Usa un identificatore hash di sessione forte: session.hash_functionin php.ini. Se PHP <5.3, session.hash_function = 1impostalo su per SHA1. Se PHP> = 5.3, impostalo su session.hash_function = sha256o session.hash_function = sha512.

  • Invia un hash forte: session.hash_bits_per_characterin php.ini. Impostalo su session.hash_bits_per_character = 5. Sebbene ciò non renda più difficile decifrare, fa la differenza quando l'attaccante tenta di indovinare l'identificatore di sessione. L'ID sarà più breve, ma utilizza più caratteri.

  • Imposta un'entropia aggiuntiva con session.entropy_filee session.entropy_lengthnel tuo php.inifile. Impostare il primo su session.entropy_file = /dev/urandome il secondo sul numero di byte che verranno letti dal file entropy, ad esempio session.entropy_length = 256.

  • Cambia il nome della sessione dal PHPSESSID predefinito. Ciò si ottiene chiamando session_name()con il proprio nome identificativo come primo parametro prima di chiamare session_start.

  • Se sei davvero paranoico, puoi anche ruotare il nome della sessione, ma fai attenzione che tutte le sessioni verranno automaticamente invalidate se lo cambi (ad esempio, se lo rendi dipendente dal tempo). Ma a seconda del tuo caso d'uso, potrebbe essere un'opzione ...

  • Ruota spesso l'identificatore di sessione. Non farei ogni richiesta (a meno che tu non abbia davvero bisogno di quel livello di sicurezza), ma a intervalli casuali. Vuoi cambiarlo spesso poiché se un attaccante dirotta una sessione non vuoi che siano in grado di usarlo per troppo tempo.

  • Includi l' agente utente$_SERVER['HTTP_USER_AGENT'] nella sessione. Fondamentalmente, quando inizia la sessione, archiviarlo in qualcosa di simile $_SESSION['user_agent']. Quindi, ad ogni richiesta successiva, verificare che corrisponda. Nota che questo può essere simulato, quindi non è affidabile al 100%, ma è meglio di così.

  • Includi l' indirizzo IP dell'utente$_SERVER['REMOTE_ADDR'] nella sessione. Fondamentalmente, quando inizia la sessione, archiviarlo in qualcosa di simile $_SESSION['remote_ip']. Questo può essere problematico da alcuni ISP che usano più indirizzi IP per i loro utenti (come faceva AOL). Ma se lo usi, sarà molto più sicuro. L'unico modo per un utente malintenzionato di falsificare l'indirizzo IP è compromettere la rete a un certo punto tra l'utente reale e l'utente. E se compromettono la rete, possono fare molto peggio di un dirottamento (come attacchi MITM, ecc.).

  • Includere un token nella sessione e sul lato browser che si incrementa e si confronta spesso. Fondamentalmente, per ogni richiesta fare $_SESSION['counter']++sul lato server. Fai anche qualcosa in JS sul lato browser per fare lo stesso (usando una memoria locale). Quindi, quando si invia una richiesta, è sufficiente prendere un nonce di un token e verificare che il nonce sia lo stesso sul server. In questo modo, dovresti essere in grado di rilevare una sessione dirottata poiché l'attaccante non avrà il contatore esatto, o se lo fanno avrai 2 sistemi che trasmettono lo stesso conteggio e possono dire che uno è forgiato. Questo non funzionerà per tutte le applicazioni, ma è un modo per combattere il problema.

Una nota sui due

La differenza tra Session Fixation e Hijacking sta solo nel modo in cui l'identificatore di sessione è compromesso. Nella fissazione, l'identificatore è impostato su un valore che l'attaccante conosce prima. Nel dirottamento viene indovinato o rubato all'utente. Altrimenti gli effetti dei due sono gli stessi una volta che l'identificatore è stato compromesso.

Rigenerazione ID sessione

Ogni volta che si rigenera l'identificatore di sessione utilizzando session_regenerate_idla vecchia sessione, è necessario eliminarlo. Ciò accade in modo trasparente con il gestore della sessione principale. Tuttavia, alcuni gestori di sessioni personalizzati che utilizzanosession_set_save_handler() non lo fanno e sono aperti agli attacchi con identificatori di sessione precedenti. Assicurati che se stai usando un gestore di sessioni personalizzato, tieni traccia dell'identificatore che apri e se non è lo stesso che salvi che elimini esplicitamente (o cambi) l'identificatore su quello vecchio.

Usando il gestore di sessioni predefinito, stai bene solo chiamando session_regenerate_id(true). Ciò rimuoverà le informazioni sulla vecchia sessione per te. Il vecchio ID non è più valido e causerà la creazione di una nuova sessione se l'attaccante (o chiunque altro) tenti di utilizzarlo. Fai attenzione con i gestori di sessione personalizzati ...

Distruggere una sessione

Se hai intenzione di distruggere una sessione (ad esempio quando esci), assicurati di distruggerla completamente. Ciò include la disattivazione del cookie. Utilizzando session_destroy:

function destroySession() {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
    session_destroy();
}

4
L'uso di 5 invece di 4 bit per personaggio non modifica in alcun modo la "forza" (qualunque sia la "forza" in questo caso). Ma sebbene i tuoi punti siano consigliabili in generale, mancano alcuni dettagli importanti. Ad esempio, cosa succede alla sessione associata al vecchio ID sessione o come una sessione con un vecchio ID sessione deve essere gestita dopo che è diventata non valida.
Gumbo,

2
@battal: No, questo è il punto. session_regenerate_idnon invalida la sessione che è ancora associata al vecchio ID; solo se il parametro delete_old_session è impostato su true la sessione verrà distrutta. Ma cosa succede se un utente malintenzionato avvia questa rigenerazione ID?
Gumbo,

6
Non sono d'accordo con la rigenerazione della sessione ogni volta che cambi una variabile di sessione, dovrebbe essere eseguita solo al login / logout. Anche il controllo dell'agente utente è insignificante e il controllo REMOTE_ADDR è problematico. Una cosa che vorrei aggiungere è session.entropy_file = /dev/urandom. La generazione di entropia interna di PHP si è dimostrata estremamente debole e il pool di entropia fornito da / dev / random o / dev / uranom è il migliore che puoi ottenere su un server web senza un hardware rng.
Torre del

4
Inoltre dovresti aggiungere session.cookie_httponlye session.cookie_secure. Il primo aiuta a contrastare xss (ma non è perfetto). Il 2 ° è il modo migliore per fermare OWASP A9 ...
arrosto il

4
Non capisco una risposta così grande ma manca il pezzo più importante: usa SSL / HTTPS. L'incremento del contatore è fonte di problemi con richieste multiple rapide l'una dopo l'altra, un utente aggiorna una pagina due volte o preme due volte i pulsanti di invio. La soluzione di indirizzo IP è un problema al giorno d'oggi con tutti gli utenti mobili e in continua evoluzione degli IP. Potresti guardare il primo set di IP, ma continua a chiedere problemi. La cosa migliore è prevenire il rilevamento dell'ID di sessione in primo luogo e che utilizza SSL / HTTPS.
Sanne,

37

Entrambi gli attacchi di sessione hanno lo stesso obiettivo: ottenere l'accesso a una sessione legittima di un altro utente. Ma i vettori di attacco sono diversi:

  • In un attacco di Session Fixation , l'attaccante ha già accesso a una sessione valida e cerca di forzare la vittima a utilizzare questa sessione particolare.

  • In un attacco di Session Hijacking , l'attaccante tenta di ottenere l'ID della sessione di una vittima per utilizzare la propria sessione.

In entrambi gli attacchi l'ID di sessione sono i dati sensibili su cui si concentrano questi attacchi. Quindi è l'ID di sessione che deve essere protetto sia per un accesso in lettura (dirottamento della sessione) sia per un accesso in scrittura (fissazione della sessione).

In questo caso si applica anche la regola generale di protezione dei dati sensibili tramite HTTPS. Inoltre, dovresti fare quanto segue:

Per prevenire attacchi con Session Fixation , assicurarsi che:

Per prevenire attacchi di dirottamento di sessione , assicurarsi che:

Per prevenire entrambi gli attacchi di sessione, assicurarsi che:

  • accettare solo sessioni avviate dall'applicazione. È possibile farlo imprimendo una sessione all'avvio con informazioni specifiche del cliente. È possibile utilizzare l' ID utente-agente ma non utilizzare l'indirizzo IP remoto o qualsiasi altra informazione che potrebbe cambiare tra le richieste.
  • per modificare l'ID della sessione utilizzando session_regenerate_id(true)dopo un tentativo di autenticazione ( truesolo in caso di successo) o una modifica dei privilegi e distruggere la vecchia sessione. (Accertarsi di archiviare eventuali modifiche di $_SESSIONutilizzo session_write_close prima di rigenerare l'ID se si desidera conservare la sessione associata al vecchio ID; in caso contrario, solo le sessioni con il nuovo ID saranno interessate da tali modifiche.)
  • per utilizzare un'implementazione di scadenza della sessione corretta (vedi Come faccio a scadere una sessione PHP dopo 30 minuti? ).

Post fantastico, specialmente l'ultima sezione.
Mattis,

6

I token che menzioni sono un "nonce" - numero usato una volta. Non devono essere necessariamente utilizzati una sola volta, ma più a lungo vengono utilizzati, maggiori sono le probabilità che il nonce possa essere catturato e utilizzato per dirottare la sessione.

Un altro svantaggio per i nonci è che è molto difficile costruire un sistema che li usi e che consenta più finestre parallele nello stesso modulo. ad es. l'utente apre due finestre in un forum e inizia a lavorare su due post:

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'

Se non hai modo di tracciare più finestre, avrai memorizzato solo un nonce - quello della finestra B / Q. Quando l'utente invia il proprio post dalla finestra A e passa in nonce 'P', questo sistema rifiuterà il post come P != Q.


Cosa c'entra questo con la fissazione della sessione?
Torre del

2
Ha un punto valido soprattutto nel regno dell'utilizzo simultaneo di molte richieste AJAX.
DanielG

2

Non ho letto l'articolo di Shiflett, ma penso che tu abbia frainteso qualcosa.

Per impostazione predefinita, PHP passa il token di sessione nell'URL ogni volta che il client non accetta i cookie. Altrimenti, nel caso più comune, il token di sessione viene archiviato come cookie.

Ciò significa che se inserisci un token di sessione nell'URL PHP lo riconoscerà e proverà a utilizzarlo successivamente. La fissazione della sessione si verifica quando qualcuno crea una sessione e quindi induce un altro utente a condividere la stessa sessione aprendo un URL che contiene il token di sessione. Se l'utente esegue l'autenticazione in qualche modo, l'utente malintenzionato conosce quindi il token di sessione di un utente autenticato, che potrebbe avere privilegi diversi.

Come sono sicuro Shiflett spiega, la solita cosa da fare è rigenerare un token diverso ogni volta che cambiano i privilegi di un utente.


Per aggiungere a questo, si prega di essere sicuri di distruggere eventuali sessioni precedentemente aperte in quanto saranno ancora valide con le autorizzazioni utente esistenti.
corrodedmonkee,

0

Sì, è possibile impedire la fissazione della sessione rigenerando l'ID sessione una volta effettuato l'accesso. In questo modo se l'attaccante non conoscerà il valore del cookie della sessione appena autenticata. Un altro approccio che arresta completamente il problema è impostato session.use_only_cookies=Truenella configurazione di runtime. Un utente malintenzionato non può impostare il valore di un cookie nel contesto di un altro dominio. La fissazione della sessione si basa sull'invio del valore del cookie come GET o POST.

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.