Hashing delle password degli utenti tramite Javascript lato client contro hashing lato server? [duplicare]

2

Sono entrato in una discussione con uno dei nostri sviluppatori senior sulle best practice per l'hashing delle password e la trasmissione e mi ha lasciato incuriosito su quale sia la migliore pratica standard del settore.

Nella revisione precedente / corrente del nostro servizio web, trasmettiamo le password in chiaro degli utenti con SSL al server e le cancelliamo sul lato server tramite SHA-256 prima di inserirle nel database. Tuttavia, un controllo di sicurezza da parte di una società di terze parti ha dichiarato che questo era insicuro e non una buona pratica.

Quindi, per la nostra versione futura, siamo passati all'utilizzo di cryptojs in password hash (unsalted) lato client, e questi valori sono memorizzati direttamente nel database senza ulteriori manipolazioni.

Il consenso generale è che in caso di una violazione della sicurezza interna, NON gestiamo MAI la password in chiaro di nessun utente, e preferiremmo piuttosto che qualcuno ignorasse le nostre implementazioni di sicurezza e avessimo una password con hash anziché una password in chiaro dell'utente.

Sono curioso di sapere se questo è adeguato o dovremmo eseguire un hash secondario salato sul lato server per proteggerci ulteriormente?

    
posta JD Davis 23.09.2015 - 15:11
fonte

1 risposta

6

In primo luogo, la "migliore pratica" è quella di cessare di usare il termine "crittografia" perché SHA-256 non è crittografia . Questo è chiamato hashing . Se i tuoi sviluppatori senior e gli auditor di terze parti parlano tutti di SHA-256 come "crittografia", allora stai sicuro che nessuno di loro sa veramente di cosa stanno parlando.

Nel tuo sistema, qualunque sia il client che invia, sia esso "crittografato" (con hash) o non sul client, è un valore che garantisce l'accesso; quel valore è quindi equivalente alla password e rivelarlo è altrettanto pericoloso per la sicurezza del tuo server come password in chiaro. Questo tipo di hashing sul lato client non porta il miglioramento della sicurezza che i vostri auditor sembrano ritenerlo fare. Ad aggravare la situazione è il fatto che quando il client esegue l'hashing con il codice Javascript, quel codice Javascript è stato appena inviato dal server stesso , quindi un server compromesso potrebbe inviare perfettamente qualche Javascript che semplicemente riceve la password dell'utente come lo digita e invia quella password a un server in Mongolia.

In ogni caso, le menti umane sono quelle che sono, le password memorizzate dall'utente sono deboli contro la forza bruta (chiamate "attacchi di dizionario"). Una semplice invocazione di una funzione di hash crittografica come SHA-256, indipendentemente da come sia protetta crittograficamente quella funzione, è troppo veloce per fornire molta protezione qui; un PC desktop disponibile in commercio può avere hash potenziali password con un conteggio di miliardi al secondo. L'hashing della buona password richiede funzioni dedicate con un costo computazionale configurabile (ma intrinsecamente elevato). Non sarai in grado di farlo correttamente in Javascript perché Javascript è debole per le attività ad alta intensità di calcolo.

La best practice è utilizzare SSL (sempre), trasmettere la password così com'è nel tunnel SSL e lasciare che il server applichi una corretta funzione di hashing della password, cioè bcrypt (con un conteggio di iterazione abbastanza alto - il più alto che si possa tollerare dato l'hardware disponibile e il carico di picco previsto).

Occasionalmente, si incontrano auditor in mancanza di qualcosa da dire, e potrebbe essere necessario eseguire alcune danze rituali per placarli. Una di queste danze è la spruzzatura della crittografia in vari luoghi, come la glassa per torte. Questo è un idiota ma innocuo, purché tu non rimuova le parti importanti. Nel tuo caso, puoi eseguire l'hashing SHA-256 sul lato client, ma non devi rimuovere l'hashing della password corretto sul lato server, cioè considerare il risultato dell'hash calcolato dal client come "password" e utilizzarlo come input per bcrypt. (Attenzione che le uscite hash sono binari , non testo, quindi è necessaria una certa codifica, es. Esadecimale o Base64 ).

L'extra SHA-256 sarebbe quindi inutile, ma non renderà il tuo sistema più debole, contrariamente a quello che stai cercando di fare:

So for our future release, we've transitioned to using cryptojs to encrypt passwords (unsalted) client-side, and these values are stored directly into the database without any further manipulation.

Se lo fai, allora il contenuto del database può essere usato per concedere l'accesso immediato al server. Un semplice sguardo di sola lettura al database (ad esempio un disco rigido rotto scartato, un nastro di backup perso, un attacco di SQL injection ...) e la tua sicurezza è andata in malora.

    
risposta data 23.09.2015 - 15:37
fonte

Leggi altre domande sui tag