L'uso di bcrypt sugli hash SHA1 esistenti è sufficiente quando si cambia l'implementazione della password?

52

Sto lavorando per migliorare un CMS in cui l'attuale implementazione della memorizzazione della password è solo sha1(password) . Ho spiegato al mio capo che farlo in quel modo è incredibilmente insicuro e gli ho detto che dovremmo passare a bcrypt e lui ha accettato.

Il mio piano era di eseguire tutti gli hash esistenti tramite bcrypt e memorizzarli nel campo della password, e quindi usare il seguente codice psudo per verificare la password: correctPassword = bcrypt_verify(password, storedHash) or bcrypt_verify(sha1(password), storedHash) .

In questo modo, i nuovi utenti o gli utenti che modificano le loro password otterranno "reali" hash bcrypt, mentre gli utenti esistenti non dovranno modificare le loro password. Ci sono degli svantaggi nel fare questo? Mentre sarebbe probabilmente l'ideale chiedere a tutti gli utenti di scegliere una nuova password, perdiamo molto in termini di sicurezza facendo questo?

Stavo pensando che anche se un utente malintenzionato avesse accesso sia al database che al codice, il cracking non sarebbe sostanzialmente più veloce anche se la maggior parte dell '"input" di bcrypt era una stringa esadecimale di 40 caratteri, poiché la parte lenta ( bcrypt_verify() ) deve ancora essere invocato per ogni tentativo di password su ciascun utente.

    
posta Alex 22.10.2015 - 11:24
fonte

4 risposte

72

In realtà questo è un buon modo per proteggere le password altrimenti memorizzate in modo non sicuro. C'è però un punto debole in questo schema, che può essere facilmente superato nel contrassegnare i vecchi hash, quindi preferirei questa soluzione:

if (checkIfDoubleHash(storedHash))
  correctPassword = bcrypt_verify(sha1(password), storedHash)
else
  correctPassword = bcrypt_verify(password, storedHash)

Immagina che un utente malintenzionato stia recuperando un vecchio backup. Vedrebbe gli hash SHA e potrebbe usarli direttamente come password se esegui il test con bcrypt_verify(...) or bcrypt_verify(sha1(...)) .

La maggior parte delle librerie di bcrypt aggiunge un segno dell'algoritmo usato da sé, quindi non è un problema se aggiungi il tuo "doppio simbolo di cancelletto", ma naturalmente puoi anche usare un campo di database separato per questo:

$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
 |
 hash-algorithm = 2y = BCrypt
    
risposta data 22.10.2015 - 12:56
fonte
7

Perché non usare semplicemente bcrypt (sha1 (password)) per tutte le password sia vecchie che nuove? Questo evita il problema delle persone che usano i tuoi vecchi hash come password ed è anche più semplice della tua proposta.

    
risposta data 22.10.2015 - 21:44
fonte
4

È una buona strategia, non perderete alcuna sicurezza a meno che un utente non decida di generare una password veramente casuale più lunga di 160 bit poiché verrà troncata. Quindi la differenza è minima. (nel qual caso ci vorrebbe ancora un tempo significativo per rinforzare il testo originale)

Potresti optare per l'implementazione di una logica per migrare le password la prossima volta che un utente la modifica, ma non vedo alcun rischio che richiederebbe una modifica immediata delle password, a meno che tu non creda che gli hash siano trapelati.

    
risposta data 22.10.2015 - 11:34
fonte
2

Recentemente ho implementato un sistema simile per la migrazione delle password a bcrypt. Comunque invece di SHA1 usavamo gli hash SHA256 (password + sale) in origine.

Questo sale viene rigenerato quando l'utente passa a bcrypt mentre accede (facoltativo) o dopo aver modificato la password. Quindi l'hash non sarebbe basato sull'originale. Inizialmente utilizziamo questo nonce come IV per crittografare l'hash bcrypt nel database con una chiave memorizzata all'esterno del database.

Questo impedisce solo iniezioni di attacchi e dati estratti esclusivamente dal database fornendo informazioni utili sulla password. Ma il sovraccarico non era un problema per noi e possiamo cambiare questa chiave esterna ogni volta che è necessario.

L'uso dell'hash SHA256 come input per bcrypt mantiene anche la lunghezza della password di input sotto il massimo per bcrypt ( related articoli )

L'unica preoccupazione che ho visto anche con l'utilizzo di SHA1 in questo modo quando cercavo consigli e problemi con qualsiasi cosa stavo facendo era di Thomas Pornin nel secondo di questi due link:

Using a secure hash function to preprocess the password is secure; it can be shown that if bcrypt(SHA-256(password)) is broken, then either the password was guessed, or some security characteristic of SHA-256 has been proven false. There is no need to fiddle with the salt at that level; just hash the password, then use bcrypt on the result (with the salt, as bcrypt mandates). SHA-256 is considered to be a secure hash function.

Quindi è possibile che mantenere SHA1 non possa essere una buona scelta - perché altrimenti migrare dall'usarlo solo in primo luogo. Detto questo è improbabile che ci sarebbe un tipo di attacco che fornirà qualsiasi valore pratico nell'attaccare un bcrypt (SHA1 (password)) nel prossimo futuro che non implicherebbe compromessi di qualche tipo con bcrypt stesso.

    
risposta data 23.10.2015 - 02:30
fonte

Leggi altre domande sui tag