Scelta di un algoritmo ID sessione per una relazione client-server

22

Sto sviluppando un'applicazione che ha una relazione client-server, e ho difficoltà a decidere sull'algoritmo in base al quale viene determinato l'identificatore di sessione. Il mio obiettivo è limitare gli impostori dall'acquisizione di dati privati di altri utenti.

Sto considerando due opzioni:

Opzione 1: genera una stringa esadecimale casuale di 32 caratteri, la memorizza in un database e la trasferisce dal server al client all'accesso client riuscito. Il client memorizza quindi questo identificatore e lo utilizza in qualsiasi richiesta futura al server, che verrebbe sottoposto a un controllo incrociato con l'identificativo memorizzato.

Opzione 2: crea un hash da una combinazione dell'ora di inizio della sessione e del nome utente e / o della password hash del client e utilizzalo per tutte le future richieste al server. L'hash della sessione verrebbe archiviato in un database alla prima richiesta e verificato per eventuali richieste future da parte del client.

Altre informazioni: più client possono essere connessi simultaneamente dallo stesso IP e nessun client deve avere lo stesso identificatore di sessione.

Domanda: quale di queste opzioni rappresenta un approccio migliore per quanto riguarda le mie preoccupazioni (di seguito) su ciascuna?

La mia preoccupazione per la prima opzione è che l'identificatore è completamente casuale e quindi potrebbe essere replicato per caso (anche se è un caso 1 in un 3.4 * 10 38 ) , e utilizzato per "rubare" i dati privati di un utente (che avrebbe anche bisogno di usare il client in quel momento).

La mia preoccupazione per la seconda opzione è che ha un difetto di sicurezza, ovvero che se la password hash di un utente viene intercettata in qualche modo, l'intero hash della sessione potrebbe essere duplicato e i dati privati dell'utente potrebbero essere rubati.

Grazie per qualsiasi inserimento.

    
posta Vulcan 02.12.2012 - 21:49
fonte

3 risposte

26

Il concetto base di un identificativo di sessione è che si tratta di un nome segreto di breve durata per la sessione , una relazione dinamica che è sotto il controllo del server (cioè sotto il controllo del tuo codice ). Spetta a te decidere quando avviare e interrompere le sessioni. Le due caratteristiche di sicurezza di un algoritmo di generazione dell'identificativo di sessione riuscito sono:

  1. Nessuna due sessioni distinte deve avere lo stesso identificatore, con una schiacciante probabilità.
  2. Non dovrebbe essere computazionalmente fattibile "colpire" un identificatore di sessione quando si provano a caso, con probabilità non trascurabile.

Queste due proprietà sono ottenute con un ID di sessione casuale di almeno, diciamo, 16 byte (32 caratteri con rappresentazione esadecimale), a condizione che il generatore sia PRNG crittograficamente strong ( /dev/urandom su sistemi Unix-like, CryptGenRandom() su Windows / Win32, RNGCryptoServiceProvider su .NET ...). Poiché memorizzi anche l'ID di sessione sul lato del server di database, potresti controllare i duplicati, e probabilmente il tuo database lo farà probabilmente per te (vorrai che questo ID sia una chiave di indice), ma è ancora tempo sprecato perché la probabilità è molto bassa. Considera che ogni volta che esci da casa, scommetti sull'idea che non sarai colpito da un fulmine. Essere uccisi da un fulmine ha una probabilità di circa 3 * 10 -10 al giorno ( really ) . Questo è un rischio che minaccia la vita , la tua vita, per essere precisi. Eppure respingi quel rischio, senza mai pensarci. Che senso ha quindi preoccuparsi delle collisioni con ID di sessione che sono milioni di volte meno probabili e non ucciderebbero nessuno se si fossero verificati?

Non ha molto senso lanciare una funzione hash in più nella cosa. La casualità applicata correttamente ti darà già tutta l'unicità di cui hai bisogno. La complessità aggiunta può solo portare a punti di debolezza aggiuntivi.

Le funzioni crittografiche sono rilevanti in uno scenario in cui non si desidera solo avere una sessione, ma si desidera anche evitare qualsiasi costo di archiviazione basato sul server; diciamo, non hai database sul server. Questo tipo di scaricamento dello stato richiede un MAC ed eventualmente la crittografia (vedere questa risposta per alcuni dettagli).

    
risposta data 02.12.2012 - 23:57
fonte
5

Gli ID di sessione devono essere di forza crittografica casuali e unici. Se un utente malintenzionato può indovinare un ID sessione legittimo, può impersonare quell'utente.

L'opzione 1 è la soluzione migliore, se usi un CSPRNG corretto e non qualcosa come rand() da una libreria standard. Usare qualcosa come l'opzione 2 non è così sicuro, dal momento che i nomi e gli orari degli utenti sono facilmente indovinati o forzati.

Dai un'occhiata al codice del generatore di ID sessione di PHP funziona, e vedrai che una funzione di hash viene utilizzata per combinare l'indirizzo IP del client, l'ora corrente (secondi e microsecondi) e alcuni valori del RNG di Linear Congruence Generator (LGC) di PHP come base di riferimento. Se è disponibile una sorgente casuale specifica per OS, un'ulteriore entropia viene mescolata nell'ID da quella funzione. Questo fornisce un margine di sicurezza ragionevole se non è disponibile una fonte di entropia strong, ma fornisce una sicurezza elevata se lo è.

    
risposta data 03.12.2012 - 00:01
fonte
1

Gli identificativi di sessione devono essere firmati, quindi non devi preoccuparti di persone che cercano di indovinare l'id di sessione.

Controlla anche le collisioni per assicurarti di non aver già dato quell'identificatore.

    
risposta data 18.04.2013 - 14:50
fonte