Come eseguire l'hashing del lato client della password usando BCrypt? [duplicare]

17

Sto migrando una vecchia applicazione che utilizzava l'hashing MD5 per Spring Security con la codifica BCrypt delle password. Voglio codificare la password sulla nuova pagina di creazione utente, modificare la pagina delle password e sulla pagina di accesso prima che venga inviata alla rete.

So che HTTPS è in grado di risolvere il problema, ma mi viene comunque richiesto di codificare la password prima di inviarla tramite la rete in base alle nostre linee guida organizzative.

Quale potrebbe essere la migliore soluzione possibile per eseguire l'hashing delle password utilizzando JavaScript?

Solo per spiegarlo meglio, sto usando l'API JCryption per crittografare la password usando AES, quindi il valore trasmesso sulla rete è AES(SHA1(MD5(plain password))) ora voglio sostituire MD5 con% soloBcrypt. Il resto delle cose rimane invariato. Questo approccio funzionerà contro "Man in the middle attack"?

    
posta Amit 08.07.2015 - 11:19
fonte

5 risposte

12

bcrypt non è pensato per questo tipo di hashing lato client

Una proprietà chiave di bcrypt è che, quando si eseguono due volte indipendenti con lo stesso testo in chiaro, la maggior parte delle implementazioni genererà hash differenti. Ciò è dovuto all'uso di un sale, progettato per rendere difficile vedere se due utenti diversi hanno la stessa password.

Al contrario, i moduli di accesso devono ricevere sempre gli stessi dati. Dopotutto, in quale altro modo verificherebbe che la password che l'utente ha digitato oggi è la stessa che ha digitato ieri?

Quindi, hai un algoritmo progettato per produrre diversi dati ogni volta, e lo stai inserendo in un'applicazione che deve verificare che i dati siano stessi ciascuno tempo. Probabilmente è un'indicazione che l'algoritmo non viene utilizzato come previsto.

Ciò che dovresti idealmente fare è utilizzare bcrypt in hash password sul server . Questo è ciò che è stato progettato per bcrypt: proteggere le password degli utenti nei momenti in cui il testo non è in memoria, che è di gran lunga lo stato più comune (ad esempio, i dump di DB rivelano solo la password con hash, non il testo in chiaro, se implementata correttamente). / p>

Personalmente vedo un certo valore nell'hashing lato client, perché aiuta a proteggere dagli attacchi che possono annusare il traffico (o che hanno accesso al server). Tuttavia, non conosco un modo per rendere l'hashing lato client sicuro come bcrypt sul lato server, motivo per cui dovresti continuare a utilizzare bcrypt sul lato server.

Se è necessario utilizzare bcrypt sul lato client, utilizzare un salt statico

Se stai andando a usare bcrypt per l'hashing sul lato client di un modulo di login, e vuoi che sia una sostituzione drop-in per MD5, devi usare un salt statico. Soprattutto se lo stai passando attraverso SHA1, perché ciò mancherebbe il bcrypt salt così come i dati dell'hashed stesso.

Questo rompe diverse ipotesi progettuali di bcrypt (come sempre usando un salt casuale), naturalmente.

Personalmente raccomando di usare lo username come salt (in modo che sia difficile dire se due utenti diversi abbiano la stessa password); tuttavia, non conosco alcuna ricerca che sia stata fatta sulla salatura in questo contesto.

Anche

AES (o qualsiasi cifra simmetrica) è inutile qui

Ricorda che AES è un algoritmo simmetrico, il che significa che hai bisogno della stessa chiave per decriptare e per crittografare i dati.

Che cosa significa questo per te? Bene, probabilmente hai ottenuto la chiave di crittografia nell'origine JavaScript, che viene offerta a qualsiasi client che visita la tua pagina di accesso. AES è un codice simmetrico, quindi la chiave di crittografia (identica alla chiave di decrittografia) dovrebbe essere privata. In altre parole, la tua chiave privata è nota al mondo - a questo punto non fornisce alcuna sicurezza efficace.

Quello che dovresti utilizzare è invece crittografia a chiave pubblica, come PGP o HTTPS (tecnicamente, HTTPS utilizza un approccio ibrido). Seriamente, utilizza solo HTTPS , a meno che l'organizzazione non ti rifiuti di avere un certificato SSL, per qualche motivo. Tieni presente che PGP non proteggerà realmente dagli attacchi MITM attivi, ma proteggerà almeno contro le intercettazioni.

    
risposta data 09.07.2015 - 02:44
fonte
44

I know HTTPS can solve the problem, but I am still instructed to encode the password before sending it over network as per our organizational guidelines.

Questo definisce davvero la tua situazione.

Fondamentalmente, hai una soluzione semplice da utilizzare comunque (usa HTTPS), se non altro perché senza HTTPS un utente malintenzionato attivo può dirottare la connessione dopo la fase di autenticazione, indipendentemente da qualsiasi "codifica" e hashing che usi per la password (un attaccante che è in grado di eseguire un attacco Man-in-the-Middle riuscirà indipendentemente da quanto si ritrae ritualmente con le funzioni hash e la crittografia). Quindi, hai anche una linea guida che è allo stesso tempo idiota e amministrativamente inevitabile. Il tuo problema è quindi: come puoi fare le cose correttamente e rispettare le "linee guida"?

Si noti che la linea guida ha poco senso a diversi livelli. Non solo la mancanza di SSL rende il protocollo vulnerabile al dirottamento; ma anche qualsiasi tipo di "codifica" non fa nulla di buono contro gli attaccanti passivi. La ragione è che se il protocollo è "il client mostra la 'password codificata'" allora un intercettatore passivo semplicemente guarderà quella "password codificata" e la invierà da sé - quindi, quel tipo di codifica non migliora effettivamente la sicurezza in nessuna modo. Rende solo alcune persone si sentono più sicure perché capiscono la crittografia come una sorta di salsa barbecue ("più spruzziamo ovunque meglio è").

Quello che ti suggerisco è che tu faccia quanto segue:

  1. Innanzitutto, prova a vendere l'idea che "HTTPS" incarna la "codifica". In altre parole, inviando la password all'interno di un tunnel SSL, si sta già rispettando la linea guida, poiché la password è debitamente codificata (e, in realtà, crittografata ), insieme al resto dei dati.

  2. Se l'infestazione da stupidità è più seria e qualche auditor (chiamiamolo Bob) continua a lamentarsi della tua mancanza di "codifica", quindi prova ad applicare alcune codifiche reversibili sul lato client. Per esempio. prima di inviare la password, applica Base64 . Ciò significa che se la password è "bobsucks", ciò che verrà inviato (all'interno del protocollo SSL, ovviamente) sarà "Ym9ic3Vja3M=", e Bob sarà più felice, perché quest'ultima stringa è ovviamente a molto più sicuro.

Il punto importante qui è che poiché il requisito non ha senso, la soluzione non avrà molto senso neanche.

    
risposta data 08.07.2015 - 14:33
fonte
25

Non hai sicurezza senza autenticazione

Just to explain it further, I am using JCryption API for encrypting the password using AES, so the value transmitted over network is AES(SHA1(MD5(plain password))) now I want to replace MD5 with Bcrypt only. Rest of the things remain unchanged. This approach works even against "Man in the middle attack".

No, non è così. Non riesco a esprimerlo abbastanza strong. Ora potrei non convincerti a usare https (potresti anche non avere una scelta) ma spero di poterti convincere che è assolutamente insicuro e qualsiasi convinzione che tu abbia a proposito fornire un po 'di sicurezza non è corretto. Se costretti ad andare avanti senza usare TLS / SSL, puoi almeno rendere molto chiaro a tutti coloro che sono coinvolti che il sistema è vulnerabile e dovrebbe essere descritto come "facilmente aggirato per la sicurezza". Uno script kiddie che esegue un hotspot MITM presso i tuoi Starbucks locali può falsificare i tuoi utenti e rubare credenziali o dirottare le sessioni, quindi non è qualcosa che richiede competenze sofisticate o attacchi complessi.

Se il canale di comunicazione non è sicuro, non ci si deve aspettare che il codice che si invia sia il codice effettivamente eseguito dal client. C'è una ragione per cui si chiama https (http sicuro) non solo httpe (http criptato), la sicurezza è più di una semplice crittografia. La comunicazione di crittografia senza autenticazione è inutile.

Alcune cose a cui pensare:

  • Senza https come fanno i tuoi utenti a sapere che sono nella tua pagina di accesso?
  • Come sai che un utente malintenzionato non ha modificato la pagina di accesso inviata all'utente per inviargli una copia in chiaro delle credenziali prima di crittografarla e inviarla a te?
  • Stai tentando di crittografare il doppio hash della password come trasmetterai in modo sicuro la chiave di crittografia?

Che cosa succede se eseguo la mia autenticazione personalizzata oltre alla crittografia

Non è proprio così semplice. Il bootstrap di un canale sicuro su uno non sicuro non è un problema banale. In teoria è possibile creare un protocollo personalizzato che replica tutti gli aspetti di https inclusa la negoziazione del protocollo, l'autenticazione del server, l'infrastruttura a chiave pubblica, lo scambio di chiavi, la crittografia, l'integrità e la revoca dei messaggi (e sono sicuro che molto di più ho dimenticato). Una volta che hai finito, sarebbe altrettanto grande e complesso di TLS. Supponiamo anche che avesse meno difetti di qualsiasi implementazione TLS e che potessi farlo in meno di un paio d'anni, avresti comunque un problema quasi impossibile. Come hai intenzione di ottenere questi componenti lato client al client? "Oh, certo, il client lo ha scaricato in sicurezza ... e aspetta". Se il bootstrap su una comunicazione sicura su un canale non sicuro sembra facile, onestamente non hai guardato abbastanza in profondità, sono le tartarughe fino in fondo.

Ora vorrei essere chiaro, TLS ha molti problemi e anche il sistema CA ha molti problemi. Non ho intenzione di fingere che sia perfetto, ma la comunicazione sicura è un problema di pollo e uova che è la soluzione migliore che abbiamo.

L'hashing del lato client può essere eseguito su https

Dalla tua formulazione sembra che la domanda sia "hashing lato client O hashing lato server su https" ma spero che tu possa vedere che è un errore. Hai bisogno di https indipendentemente da come autenticerai i tuoi utenti. Quindi, se accetti di aver bisogno di https, la domanda diventa "Perché o quando avrebbe senso utilizzare l'hashing lato client (su https) anziché l'hashing lato server (su https)? Nella maggior parte dei casi non lo sarebbe. L'hashing del lato client è più complesso e non più sicuro, ma ha un vantaggio e il server ha una conoscenza zero della password che non è il caso nell'hash del lato server. In alcuni scenari, si desidera server) per essere denunziabile: non è possibile perdere una chiave che non si possiede e non è possibile forzare la decrittografia dei file di un cliente se non ti ha mai fornito la chiave di decrittografia, quindi ci sono scenari in cui potrebbe essere obbligatorio requisito ma dovrebbe essere parte del design del progetto, non una decisione arbitraria. Se hai domande specifiche su come gestire gli scenari di conoscenza zero, sarebbe meglio fare come una nuova domanda.

    
risposta data 08.07.2015 - 15:00
fonte
9

La soluzione migliore è: no.

Se invii le password su HTTPS, l'hashing non fornisce ulteriore sicurezza.

Se invii le password su un semplice HTTP, un utente malintenzionato può prendere la password con hash e usarla per accedere a se stessa; in alternativa, possono manomettere il codice JavaScript per inviare la password a loro prima dell'hashing. In entrambi i casi, l'hashing della password non fornisce alcuna sicurezza.

    
risposta data 08.07.2015 - 11:27
fonte
4

Dal momento che sembra che tu abbia deciso di implementare questa linea guida, risponderò direttamente alla tua domanda. Ma comprendi che BCrypt e MD5 sono molto diversi. BCrypt fa deliberatamente un lavoro sostanziale, mentre MD5 fa molto meno, quindi avrai bisogno di gestire le promesse:

<!-- https://github.com/nevins-b/javascript-bcrypt -->
<script src='bCrypt.js'></script>
<script src='isaac.js'></script>
<script>
  // ... your code, then:
  var bcrypt = new bCrypt();
  bcrypt.hashpw('plain password', bcrypt.gensalt(), function (hashed) {
      var cipher = AES(SHA1(hashed));
      // now you have your "secure" hash
  });
</script>

Ti esorto a considerare il saggio saggio nelle altre risposte. Gli scenari in cui questa linea guida aggiunge valore sono rari, quindi chiedetevi: Perché investire in doppio lavoro in un'infrastruttura ridondante che non aggiunge sicurezza e rallenta l'esperienza utente?

References:

  1. La crittografia del trasporto protegge tutti i segreti .

  2. L'invio di un hash equivale all'invio di una password e generare un hash sicuro è necessariamente lento .

  3. La resistenza brute-force di bcrypt rispetto a MD5 per l'hashing delle password? e risultati del test delle prestazioni dell'algoritmo hash .

risposta data 08.07.2015 - 19:17
fonte

Leggi altre domande sui tag