Come immagazzino i dati di sessione su un server in modo sicuro

1

Sto costruendo un sistema in cui la sicurezza è importante e vorrei memorizzare i dettagli della sessione sul server in una tabella di sessione. Tuttavia, sono preoccupato che se un utente attaccato si impossessasse del database, avrebbe accesso a tutti i dettagli della sessione per tutti gli utenti loggati.

Come posso aggirare questo - è solo per mantenere i dettagli della sessione crittografati e inviare un segreto all'utente come un cookie, il che significa che su ogni richiesta c'è la decrittazione. Questo ovviamente rallenterà l'utente.

Non posso memorizzare dettagli di sessione in un cookie sul computer dell'utente poiché questo cookie potrebbe crescere molto e potrebbe superare 4kb (dimensione massima dell'intestazione richiesta).

    
posta Yule 09.01.2017 - 16:53
fonte

3 risposte

3

In generale, le informazioni sulla sessione non sono solitamente crittografate sul lato server. In genere, come parte del modello di minaccia, si presume che se un utente malintenzionato ottiene l'accesso al server, ha già tutto ciò di cui ha bisogno. Di solito i dati di sessione non sono più sensibili rispetto al resto del contenuto del database.

Ci sono alcune opzioni:

  • memorizzali sul filesystem in testo semplice. Se il tuo modello di minaccia suggerisce che SQLi è più probabile dell'accesso al filesystem, questa è una mossa facile.
  • Codifica ID sessione e dati utilizzando le routine di crittografia incorporate del database. Questo ti protegge dai casi in cui un backup del database è compromesso, ma non ti protegge dal furto del disco o da un utente malintenzionato con accesso SQL.
  • Cifra i tuoi ID di sessione e i dati di sessione nel database, utilizzando un set di chiavi in un file di configurazione sul server da qualche parte. Il vantaggio di questo è che l'utente malintenzionato dovrebbe avere accesso sia al database (ad esempio tramite SQL injection) che al filesystem allo stesso tempo per decodificare gli ID di sessione e i dati di sessione.
  • Codifica gli ID di sessione e i dati utilizzando una chiave scelta a caso che viene memorizzata nella cache all'interno del processo del daemon del server (ad esempio APC o memcached per PHP). Ciò sarebbe estremamente difficile per un utente malintenzionato di accedere a senza l'esecuzione completa del codice nel sistema, ma ha il lato negativo che tutti i dati della sessione sarebbero invalidati se si riavvia il processo del server.

Raccomando l'uso della crittografia autenticata, con crittografia e autenticità separate. Lo pseudocodice per la crittografia è il seguente:

iv = secure_random(16)
encrypted = iv || AES-CBC-128(session_id || session_data, enc_key, iv)
auth_encrypted = HMAC-SHA256(encrypted, auth_key) || encrypted

Lo pseudocodice per la decrittazione è il seguente:

mac = auth_encrypted[0:31]
encrypted = auth_encrypted[32:]
expected_mac = HMAS-SHA256(encrypted, auth_key)
if mac != encrypted_mac:
    session was tampered with
else:
    iv = encrypted[0:15]
    encrypted = encrypted[16:]
    decrypted = AES-CBC-128_Decrypt(encrypted, enc_key, iv)

Fornisce la crittografia autenticata per impedire la manomissione dei dati di sessione sul lato server.

    
risposta data 09.01.2017 - 17:16
fonte
0

L'approccio standard a questo è di rendere le sessioni con una durata relativamente breve - il modo più comune per un utente malintenzionato di accedere al database è attraverso l'ottenimento di backup e tali sessioni sarebbero scadute in quel backup.

Se un utente malintenzionato ha accesso dal vivo al database live, probabilmente non ha bisogno di sessioni, quindi potrebbe non essere una tale preoccupazione.

In alternativa, se non hai bisogno di condividere sessioni su server, puoi semplicemente tenere le sessioni in memoria. (La maggior parte delle implementazioni di sessione predefinite lo fanno nella maggior parte dei framework di cui sono a conoscenza)

Un'alternativa alle sessioni potrebbe essere Token Web JSON - anche quelli hanno una durata, ma sono autosufficienti - contengono attestazioni (cioè, sono utente X) e sono convalidati mediante firma o crittografia. Ciò richiede che tu abbia un server di autenticazione centrale che firma tutti i token (che altri server leggono e possono verificare) in una configurazione di chiave pubblica / privata o che tutti i server hanno accesso a una chiave di crittografia comune (che ovviamente deve essere protetta molto bene - HSM o equivalente è spesso usato per questo). Dal momento che vengono passati avanti e indietro dal client, non è necessario memorizzarli, poiché è possibile verificarli ogni volta che il client esegue un'azione.

    
risposta data 09.01.2017 - 17:03
fonte
0

This will obviously slow down the user.

No, non lo farà.

Sì, sarà più lento dell'archiviazione di testo normale e ridurrà la capacità ma la differenza sarà trascurabile (a meno che tu non stia molto male in questo).

Il mio livello di sessione di crittografia costa circa 0,002 secondi per richiesta (dimensione sessione 4k) su hardware abbastanza run-of-the-mill con AES a 256 bit. Gli esseri umani non possono percepire differenze di durata inferiori a circa 0,030 secondi.

Se parliamo specificamente di PHP, tieni presente che c'è anche un costo di circa 0,0005 secondi per richiesta per utilizzare un serializzatore personalizzato, richiesto per il mio gestore. OTOH ci sono altre cose che puoi fare con un gestore personalizzato per migliorare la capacità.

maximum request header size

Questo non è limitato da HTTP - potrebbe essere un vincolo di configurazione locale. Certamente alcuni browser limitano le dimensioni dei cookes.

I can't store session details in a cookie

No, ma è possibile memorizzare più dati in più cookie e memoria strutturata sul client (esistono librerie per gestirli). Ma aggiunge molta complessità. E come spiegato sopra, non vi è alcun vantaggio netto.

    
risposta data 10.01.2017 - 01:18
fonte

Leggi altre domande sui tag