¿El uso de bcrypt en los hash SHA1 existentes es lo suficientemente bueno al cambiar la implementación de la contraseña?

52

Estoy trabajando para mejorar un CMS en el que la implementación actual de la contraseña de almacenamiento es solo sha1(password) . Le expliqué a mi jefe que hacerlo de esa manera es increíblemente inseguro y le dije que deberíamos cambiar a bcrypt, y él estuvo de acuerdo.

Mi plan era simplemente ejecutar todos los hashes existentes a través de bcrypt y almacenarlos en el campo de la contraseña, y luego usar el siguiente psudo-código para verificar la contraseña: correctPassword = bcrypt_verify(password, storedHash) or bcrypt_verify(sha1(password), storedHash) .

De esta manera, los usuarios nuevos o los usuarios que cambian sus contraseñas obtendrán hash bcrypt "reales", mientras que los usuarios existentes no tendrán que cambiar sus contraseñas. ¿Hay alguna desventaja para hacer esto? Si bien probablemente sería ideal pedir a todos los usuarios que elijan una nueva contraseña, ¿perdemos mucho en la seguridad al hacer esto?

Estaba pensando que incluso si un atacante tuviera acceso tanto a la base de datos como al código, el craqueo no sería sustancialmente más rápido incluso si la mayoría de la "entrada" a bcrypt era una cadena hexagonal de 40 caracteres, ya que la parte lenta ( bcrypt_verify() ) aún debe invocarse para cada intento de contraseña en cada usuario.

    
pregunta Alex 22.10.2015 - 11:24
fuente

4 respuestas

72

En realidad, esta es una buena manera de proteger las contraseñas almacenadas de otra manera no segura. Sin embargo, hay un punto débil en este esquema, que se puede superar fácilmente al marcar hashes antiguos, por lo que preferiría esta solución:

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

Imagina que un atacante obtiene una copia de seguridad antigua. Él vería los hashes SHA, y podría usarlos directamente como contraseñas si prueba con bcrypt_verify(...) or bcrypt_verify(sha1(...)) .

La mayoría de las bibliotecas bcrypt agregan una marca del algoritmo utilizado, por lo que no es un problema si agrega su propia "marca de doble hash", pero, por supuesto, también puede usar un campo de base de datos independiente para esto:

$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
 |
 hash-algorithm = 2y = BCrypt
    
respondido por el martinstoeckli 22.10.2015 - 12:56
fuente
7

¿Por qué no usar simplemente bcrypt (sha1 (contraseña)) para todas las contraseñas antiguas y nuevas? Esto evita el problema de las personas que usan sus antiguos hash como contraseñas y también es más simple que su propuesta.

    
respondido por el Peter Green 22.10.2015 - 21:44
fuente
4

Es una buena estrategia, no perderá ninguna seguridad a menos que un usuario decidiera generar una contraseña verdaderamente aleatoria de más de 160 bits, ya que se truncará. Así que la diferencia es mínima. (en cuyo caso aún tomaría una cantidad de tiempo significativa para aplicar la fuerza bruta al texto original)

Puede optar por implementar alguna lógica para migrar las contraseñas la próxima vez que un usuario las cambie, pero no veo ningún riesgo que requiera un cambio inmediato de las contraseñas, a menos que crea que los hashes se hayan filtrado.

    
respondido por el Lucas Kauffman 22.10.2015 - 11:34
fuente
2

Recientemente implementé un sistema similar para migrar contraseñas a bcrypt. Sin embargo, en lugar de SHA1, usábamos hashes SHA256 (contraseña + sal) originalmente.

Esta sal se regenera cuando cambiamos el usuario a bcrypt cuando inician sesión (opcional) o al cambiar su contraseña. Así que el hash no estaría basado en el original. Luego, utilizamos esta fuente de acceso principal como IV para cifrar el hash bcrypt en la base de datos con una clave almacenada fuera de la base de datos.

Hacer esto solo previene realmente los ataques de inyección y los datos extraídos únicamente de la base de datos que proporciona información de contraseña útil. Pero los gastos generales no nos preocupaban y podemos cambiar esta clave externa siempre que sea necesario.

El uso del hash SHA256 como entrada para bcrypt también mantiene la longitud de la contraseña de entrada por debajo del máximo para bcrypt ( related articles )

La única preocupación que también vi alguna referencia al uso de SHA1 de esta manera cuando buscaba consejos y problemas con todo lo que estaba haciendo era de Thomas Pornin en el segundo de esos dos enlaces:

  

El uso de una función hash segura para preprocesar la contraseña es seguro; se puede demostrar que si bcrypt (SHA-256 (contraseña)) se rompe, entonces la contraseña fue adivinada o si alguna característica de seguridad de SHA-256 ha sido probada como falsa. No hay necesidad de jugar con la sal a ese nivel; solo hash la contraseña, luego usa bcrypt en el resultado (con la sal, como mandatos de bcrypt). SHA-256 se considera una función hash segura.

Por lo tanto, es posible que mantener SHA1 puede no ser una buena opción. ¿Por qué si no migrar para usarlo solo en primer lugar? Dicho esto, es improbable que haya un tipo de ataque que proporcione algún valor práctico para atacar a un bcrypt (SHA1 (contraseña)) en un futuro cercano que no implique algún tipo de compromiso con el propio bcrypt.

    
respondido por el John Pettit 23.10.2015 - 02:30
fuente

Lea otras preguntas en las etiquetas