Firma richiesta basata su HMAC - Conservazione del sale

11

Sto lavorando a un progetto (non ad alta sicurezza) che al momento non è in diretta ma potrebbe essere pubblicato in un dato momento.

Abbiamo un'API REST (implementata utilizzando Restlet e Neo4j) in esecuzione su un server e un'app client Android.

Per mantenere le cose senza stato, abbiamo bisogno di inviare informazioni di autenticazione insieme a ciascuna richiesta. Abbiamo deciso di utilizzare un approccio basato su MAC: firmiamo un insieme di valori di intestazione e il corpo dell'entità di ciascuna richiesta HTTP utilizzando l'algoritmo HMAC-SHA256. Quindi inseriamo l'hash insieme al nome utente nell'intestazione Authorization della richiesta.

Per il segreto HMAC, utilizziamo una password che viene scelta dall'utente. Per rendere le cose più sicure, abbiamo cancellato la password prima di usarla e memorizzarla nel client.

Naturalmente, affinché il server possa convalidare l'intestazione HMAC-SHA256, dobbiamo trasmettere il segreto una volta. Ma poiché ciò accade solo una volta, non è un grosso rischio per la sicurezza.

Il problema con questa configurazione è la memorizzazione sicura delle password dell'utente. So che le password non dovrebbero mai essere sottoposte a hash senza usare un salt per prevenire gli attacchi di rainbow table. Ma quando creo un sale sicuro / casuale, un client che registra un utente per la prima volta non ha modo di accedere a quel sale per generare l'hash corretto.

Quale sarebbe la migliore decisione in questo caso? Devo semplicemente archiviare le password usando un algoritmo di hashing "convenzionale" come SHA256 senza usare sale? Immagino che sarebbe molto negligente. Potrei anche usare un algoritmo più sicuro come bcrypt o PBKDF2 con un "dummy salt" come lo username un hash MD5 del nome utente e un conteggio di iterazioni più elevato. Anche se il sale è noto, sarebbe molto lento e doloroso generare tabelle arcobaleno.

Il bcrypt con un "security-by-obscurity" sarebbe abbastanza sicuro? Oppure l'intera configurazione non è sicura e dovrebbe essere scambiata con un altro metodo di autenticazione?

    
posta Danilo Bargen 18.05.2012 - 00:40
fonte

3 risposte

5

La cosa più importante da fare è: usa SSL . Utilizza HTTPS, non HTTP.

Motivazione:

  • Se utilizzi SSL, il tuo approccio è ragionevole.

    • Dettaglio tattico: suggerisco di utilizzare PBKDF2 con un numero di iterazioni elevato per generare la chiave HMAC dalla password. Puoi usare un valore fisso (o un hash del nome utente) come il sale.

    • Questo avrà certamente dei punti deboli: poiché memorizzi un hash della password sul dispositivo client, qualcuno che ottiene l'accesso al dispositivo mobile può usare gli attacchi di dizionario per provare a recuperare la password, e potrebbero o potrebbero non avere successo, a seconda di quanto sia strong la password. Inoltre, chiunque abbia accesso al dispositivo mobile può apprendere la chiave crittografica, che è tutto ciò che è necessario per inviare richieste HTTP autenticate. In molte impostazioni, questa debolezza potrebbe essere un rischio accettabile.

  • Se non si utilizza SSL, lo schema avrà probabilmente maggiori problemi di sicurezza. Chiunque possa annusare il filo sarà in grado di apprendere un hash della password e, se la password non è strong, potrebbe essere in grado di recuperare la password dell'utente utilizzando la ricerca del dizionario.

Se vuoi una sicurezza ancora migliore, ecco un approccio leggermente più strong:

  • Utilizza SSL ovunque. Non scherzare con HTTP non criptato; usa HTTPS per tutto.

  • Utilizza una chiave crittografica a piena forza. fai in modo che il server generi una chiave crittografica crittograficamente casuale a 128 bit a piena forza per l'utilizzo con HMAC. Il server può memorizzare questa chiave.

    • La prima volta che il client si connette, avrà bisogno di imparare questa chiave crittografica. Per fare ciò, avere una richiesta speciale in cui il client fornisce nome utente e password e riceve la chiave crittografica in risposta se la password è corretta. (Il server può limitare queste richieste, per dissuadere gli attacchi del dizionario.) Quando il client riceve la chiave crittografica, la memorizza localmente.

    • Per ogni richiesta successiva, il client può cercare la sua copia memorizzata a livello locale della chiave crittografica e usarla per calcolare l'HMAC.

    • Se l'utente accede al sito Web da un nuovo dispositivo, nessun problema, quel dispositivo passa semplicemente attraverso il passaggio di inizializzazione menzionato sopra per recuperare la chiave crittografica, quindi tutto continua a funzionare.

Questo evita la necessità di memorizzare la password dell'utente o un hash della password dell'utente sul dispositivo finale. Impedisce anche attacchi di ricerca del dizionario contro la chiave crittografica; poiché la chiave crittografica è un valore completamente casuale scelto casualmente indipendente dalla password, gli attacchi di ricerca del dizionario offline contro la password non avranno esito positivo al momento di recuperare la chiave. Tuttavia, mantiene la debolezza che se un cattivo si mette le mani sul dispositivo client, sarà in grado di apprendere la chiave crittografica e quindi emettere richieste forgiate. Sospetto che sia il massimo che puoi, visto il tuo obiettivo.

    
risposta data 04.06.2012 - 07:51
fonte
4

Non sono sicuro di aver compreso completamente il tuo problema.

Il sale è solitamente codificato nella rappresentazione della stringa bcrypt.

Tuttavia, l'utilizzo del nome utente come sale probabilmente non funzionerà poiché bcrypt prevede esattamente 16 byte come salt. Quindi avresti bisogno di trasformare il nome utente prima. Quello che non capisco è, perché non è possibile che entrambe le parti abbiano il sale? Come hai detto, il sale serve solo a prevenire gli attacchi della tabella arcobaleno, quindi puoi probabilmente persino trasmetterlo senza che questo sia un problema di sicurezza.

    
risposta data 18.05.2012 - 00:53
fonte
1

Se si utilizza una password con hash come chiave HMAC, l'hash diventa il segreto condiviso. L'hashing (con o senza sale) proteggerà la password nel caso in cui venga utilizzata da qualche altra parte, ma non proteggerà il tuo servizio, poiché l'hash può essere utilizzato direttamente.

Penso che sia meglio considerare la chiave hmac una credenziale, un token. E non puoi salvare quelli veramente sicuri. Ovviamente dovresti metterli comunque in una posizione sicura.

Invece di "inviare una password una volta" ti consiglio di usare qualcosa di simile ai token di OAUTH per ricavare un segreto temporaneo, oppure puoi renderlo semplice e generare le "chiavi di accesso" sul server e consentire all'utente di copiarle (questo è ad esempio ciò che Amazon AWS fa). Se si tratta di una stringa casuale, non vi è alcun pericolo di perdita di password utente (solo, di nuovo, ovviamente, le credenziali).

Un'alternativa sarebbe utilizzare qualcosa come SRP, che si tradurrà in un segreto pre-master condiviso che può essere usato per la tua chiave di firma della richiesta.

    
risposta data 05.06.2014 - 23:41
fonte

Leggi altre domande sui tag