it-swarm.dev

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

Sto sviluppando un'applicazione che ha una relazione client-server e non riesco a decidere l'algoritmo con cui viene determinato l'identificatore di sessione. Il mio obiettivo è impedire agli impostori di acquisire dati privati ​​di altri utenti.


Sto considerando due opzioni:

Opzione 1: Genera una stringa esadecimale casuale di 32 caratteri, salvala in un database e passala dal server al client dopo aver effettuato correttamente l'accesso al client. Il client quindi memorizza questo identificatore e lo utilizza in qualsiasi futura richiesta al server, che lo farebbe un controllo incrociato con l'identificatore memorizzato.

Opzione 2: Crea un hash da una combinazione dell'ora di inizio della sessione e del nome utente di accesso del client e/o della password con hash e usalo per tutte le future richieste al server. L'hash della sessione verrà archiviato in un database alla prima richiesta e verificato per eventuali richieste future dal client.

Altre informazioni: È possibile connettere più client dallo stesso IP contemporaneamente e non due client devono avere lo stesso identificatore di sessione.


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

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

La mia preoccupazione per la seconda opzione è che ha un difetto di sicurezza, vale a dire che se una password con hash di un utente viene intercettata in qualche modo, l'intero hash di sessione potrebbe essere copiato e i dati privati ​​dell'utente potrebbero essere rubati.

Grazie per qualsiasi input.

23
FThompson

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

  1. Nessuna sessione distinta deve avere lo stesso identificatore, con probabilità schiacciante.
  2. Non dovrebbe essere fattibile dal punto di vista computazionale "colpire" un identificatore di sessione quando si provano quelli casuali, con probabilità non trascurabili.

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 un PRNG crittograficamente forte (/dev/urandom Su Sistemi simili a Unix, CryptGenRandom() su Windows/Win32, RNGCryptoServiceProvider su .NET ...). Dato che memorizzi anche l'ID sessione in un lato server database, tu could verifica la presenza di duplicati, e in effetti il ​​tuo database probabilmente lo farà per te (vorrai che questo ID sia una chiave di indice) , ma è comunque tempo perso perché la probabilità è molto bassa. Considera che ogni volta che esci di casa, stai scommettendo sull'idea che non verrai colpito da un fulmine. Essere ucciso da un fulmine ha una probabilità di circa 3 * 10-10 al giorno ( davvero ). Questo è un rischio di morte, la tua vita, per essere precisi. Eppure respingi quel rischio, senza mai pensarci. Che senso ha, quindi, preoccuparsi di collisioni tra ID sessione che sono milioni di volte meno probabili e che non ucciderebbero nessuno se si verificassero?

È inutile lanciare una funzione di hash aggiuntiva nella cosa. La casualità applicata correttamente ti darà già tutta l'unicità di cui hai bisogno. Una maggiore complessità può solo comportare ulteriori punti deboli.

Le funzioni crittografiche sono rilevanti in uno scenario in cui non si desidera solo avere una sessione, ma si desidera anche evitare costi di archiviazione basati su server; ad esempio, non hai un database sul server. Questo tipo di offload dello stato richiede un MAC e possibilmente la crittografia (vedi questa risposta per alcuni dettagli).

28
Thomas Pornin

Gli ID di sessione devono essere casuali e univoci per la forza crittografica. Se un utente malintenzionato può indovinare un ID di sessione legittimo, può impersonare tale utente.

L'opzione 1 è la soluzione migliore, purché si utilizzi un CSPRNG appropriato e non qualcosa come Rand() da una libreria standard. L'uso di qualcosa come l'opzione 2 non è così sicuro, dal momento che nomi utente e tempi sono facilmente indovinati o forzati.

Dai un'occhiata a come funziona codice generatore ID sessione PHP e vedrai che viene utilizzata una funzione hash per combinare l'indirizzo IP del client, l'ora corrente (secondi e microsecondi) e alcuni valori da GNP Linear Congruence Generator (LGC) RNG come base. Se è disponibile una fonte casuale specifica del sistema operativo, ulteriore entropia viene miscelata nell'ID da quella funzione. Ciò fornisce un margine di sicurezza ragionevole se non è disponibile alcuna fonte entropica forte, ma fornisce una sicurezza elevata se presente.

6
Polynomial

Gli identificatori di sessione devono essere firmati, quindi non devi preoccuparti delle persone che provano a indovinare l'ID di sessione.

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