Demistificazione dell'autenticazione Web (cookie di sessione stateless)

41

Attualmente sto studiando i protocolli di autenticazione utente per un sito Web che sto sviluppando. Vorrei creare un cookie di autenticazione in modo che gli utenti possano rimanere loggati tra le pagine.

Ecco la mia prima battuta:

cookie = user_id|expiry_date|HMAC(user_id|expiry_date, k)

Dove k è HMAC(user_id|expiry_date, sk) e sk è una chiave a 256 bit nota solo al server. HMAC è un hash SHA-256. Nota che '|' è un separatore, non solo una concatenazione.

Questo sembra in PHP (nota, questa domanda è indipendente dalla lingua, PHP è solo un esempio):

$key = hash_hmac('sha256', $user_id . '|' . $expiry_time, SECRET_KEY);
$digest = hash_hmac('sha256', $user_id . '|' . $expiry_time, $key);
$cookie = $user_id . '|' . $expiry_time . '|' . $digest;

Riesco a vedere che è vulnerabile a Replay Attacks come indicato in Un Secure Cookie Protocol , ma dovrebbe essere resistente agli attacchi Volume e allo spionaggio crittografico.

LA QUESTIONE: Sono sulla buona linea qui, o c'è una vulnerabilità enorme che mi è sfuggita? C'è un modo per difendersi da Replay Attack che funziona con indirizzi IP assegnati dinamicamente e non usa le sessioni? Non voglio archiviare nulla sul lato server per avere questo lavoro.

Inoltre, non sto pianificando o rotolando da solo. Sto chiedendo questo per giudicare meglio quale soluzione dovrei scegliere. Quindi nessuna risposta "Basta usare X" senza una spiegazione.

NOTE

Il materiale più recente che ho letto:
Dos e cosa non fare dell'autenticazione client sul Web alias Fu et al.
( link )

Un protocollo per cookie protetto alias Liu et al.
( link )
che si espande sul metodo precedente

Cookie di sessione stateless indurito
( link )
che si espande anche sul metodo precedente.

Dato che l'argomento è estremamente complicato, sto cercando solo risposte dagli esperti di sicurezza con esperienza del mondo reale nella creazione e nell'interruzione degli schemi di autenticazione.

    
posta Joony 11.02.2013 - 15:27
fonte

4 risposte

34

"Gli attacchi di riproduzione" non si applicano realmente ai cookie, perché un cookie è per definizione qualcosa che deve essere riprodotto: il browser dell'utente restituisce lo stesso valore del cookie, ed è così che il tuo server sa che è lo stesso utente.

Ciò che si vuole evitare è qualcuno che spia la linea, osserva il valore del cookie e quindi invia lo stesso cookie sulle proprie connessioni. L'unica soluzione pratica conosciuta è quella di eseguire l'intero protocollo all'interno di un tunnel che garantisce la riservatezza e l'integrità dei dati in transito, e questo è noto come "SSL" (aka HTTPS ).

Quindi ci sono due modi per generare e verificare i valori dei cookie sul server:

  • Puoi solo generare un valore casuale di dimensioni sufficienti (cioè 16 byte o giù di lì), in modo che sia altamente improbabile per un utente malintenzionato indovinare il valore per pura fortuna. Il server ricorda per ogni utente il suo "token di sessione" corrente, come una colonna aggiuntiva nel database "users".

  • Produci il token come valore non dimenticabile calcolato deterministicamente dall'identificatore dell'utente. Questo è quello che fai, e questo è un concetto ragionevole. Fondamentalmente, invece di memorizzare alcuni stati extra sul server, lo scarichi sul client e usi un MAC con un tasto sul lato server in modo che i client non possano falsificare i valori del cookie "validi".

Il tuo codice descrive due chiamate HMAC nidificate, il che è strano e ingiustificato. Una chiamata è sufficiente. La costruzione generica è che un cookie contiene un valore v e un MAC m tale che v codifica lo stato che si desidera memorizzare nel client, e m è calcolato su v . Lo stato che vuoi memorizzare, nel tuo caso, è: "questo client ha l'ID utente i e connesso al momento t ". Puoi utilizzare qualsiasi codifica che desideri purché sia possibile decodificarlo in modo inequivocabile.

Per riassumere: produrre valori di cookie con un MAC è un modo valido per fare la gestione delle sessioni, e HMAC / SHA-256 è utile per questo. Ma devi considerarlo come un ottimizzazione : memorizzi i valori nel client per evitare di memorizzarli sul server. Ciò ha la sfortunata conseguenza che il cliente può dimenticare i dati dal tuo controllo (il client può distruggere il cookie) o può fare distorsioni temporali (il client può modificare il valore memorizzato nel suo browser a un valore di cookie più vecchio - un problema che è mitigato includendo le date nei cookie, sotto il controllo del MAC).

Se riesci a mantenere il lato server statale e ad usare solo valori di cookie casuali, allora fallo: è più semplice e dà più controllo al server.

    
risposta data 11.02.2013 - 16:54
fonte
13

Il primo passo per proteggere qualsiasi applicazione web sta usando SSL. Ciò mantiene i tuoi cookie riservati, previene attacchi di replay, assicura che l'utente stia parlando con il server giusto, previene MitM, impedisce agli aggressori di modificare i dati sulla rete ...

Quindi imposta il flag secure sul cookie, quindi viene inviato solo su SSL. Impostando il flag http-only , per impedire a javascript di leggerlo non fa male neanche.

Finalmente riguardo al tuo schema di cookie:

  • L'HMAC nidificato non ti guadagna nulla. Basta andare con user_id|expiry_date|HMAC(user_id|expiry_date, SECRET_KEY)
  • Modifica SECRET_KEY regolarmente
  • Il user_id non deve mai cambiare. Ad esempio, utilizza il valore numerico user_id, non il nome utente o l'indirizzo email
  • user_idexpiry_date dovrebbero mai contenere un | per garantire la separazione del dominio pulita
  • Se sei paranoico, usa un server di login specializzato, che firma il cookie anziché MACarlo. Quindi il server di login è l'unico server che ha la chiave necessaria per creare i cookie, i normali server web possono solo convalidarlo. = > riduce la superficie di attacco
  • Il server può creare cookie validi per qualsiasi utente. Potrebbe non essere opportuno.
risposta data 11.02.2013 - 15:49
fonte
8

Prima di tutto:

Non inventare i tuoi protocolli di sicurezza. È molto probabile che ti sbagli.

Ora che è fuori mano, diamo un'occhiata a questo. Se riuscirò mai a ottenere HMAC(userid|expiry_date, k) , senza accedere o essersi autenticato come tale utente, ho infranto la sicurezza di questo sistema. Questo si estende a tutti i tipi di problemi, come gli attacchi di sessione o di dirottamento delle sessioni (spesso causati da non, o in modo errato, usando SSL / TLS).

Quando stai controllando il cookie di sessione, stai perdendo informazioni dai canali temporali? Stai definitivamente usando HMAC correttamente? Hai detto che il tuo HMAC è SHA-256, in realtà intendi HMAC-SHA-256? Perché passare attraverso una complicata procedura HMAC, quando si può semplicemente generare una stringa casuale e associarla con un utente sul server (ad esempio in un database)? Perché non usare solo user_id|expiry_date|HMAC-SHA-256(user_id|expiry_date, sk) (dove | è concatenazione, non il carattere letterale del pipe)?

Per quanto riguarda la difesa dagli attacchi di replay in un ambiente basato sul Web, consulta il progetto CSRFGuard di OWASP . Non sarai in grado di integrarlo direttamente, ma potrebbe esserci un equivalente PHP da qualche parte. Tuttavia, è tutto da discutere se il tuo sito è vulnerabile agli attacchi XSS.

La sicurezza dovrebbe essere trasferita a un quadro rispettato e testato, non eseguito ad-hoc

Modifica, una breve parola sugli attacchi di fissazione della sessione:

Supponevo che se non stai trasmettendo la sicurezza a un framework ben testato, sei probabilmente vulnerabile. Dovrai fondamentalmente controllare che stai emettendo una chiave di sessione distinta quando l'utente si autentica (cioè diverso da quello con cui l'utente ha iniziato). Con la strategia precedente, user_id|expiry_date|HMAC(user_id|expiry_date, k) non cambierà quando l'utente si autentica, lasciandoli vulnerabili a un attacco di fissazione di sessione.

    
risposta data 11.02.2013 - 15:53
fonte
3

As the subject is extremely complicated I'm am only looking for answers from security experts with real world experience in creating and breaking authentication schemes.

Hai ragione che l'argomento è estremamente complicato.

Vai con le funzioni di sessione fornite dal tuo framework e non provare a eseguire il rollover. Se stai usando un semplice PHP invece di un framework ... shudders .

    
risposta data 11.02.2013 - 15:38
fonte

Leggi altre domande sui tag