¿Es seguro / prudente almacenar un salt en el mismo campo que la contraseña de hash?

60

Al usar Argon2 para las contraseñas de hash en mi aplicación, he notado que genera una cadena como esta (por ejemplo, para la contraseña "rabbit"):

$argon2i$v=19$m=65536,t=3,p=1$YOtX2//7NoD/owm8RZ8llw==$fPn4sPgkFAuBJo3M3UzcGss3dJysxLJdPdvojRF20ZE=

Entiendo que todo lo anterior a p= son parámetros, el cuerpo de p= es el valor salt y la última parte es la contraseña con hash.

¿Es aceptable almacenar esto en un campo en una base de datos SQL ( varchar(99) en este caso), o debería separarse la cadena en sus partes constituyentes? ¿Debo almacenar la sal por separado de la contraseña con hash y mantener los parámetros en el código?

    
pregunta TheHonestAtheist 06.04.2018 - 16:26
fuente

7 respuestas

116

Deberías almacenarlo en un solo campo. No intentes dividirlo en partes.

Sé que esto puede parecer un poco poco intuitivo para las personas que provienen de un fondo de base de datos, donde el modus operandi es normalizar los datos y el uso de cadenas serializadas se considera un truco feo. Pero desde una práctica de seguridad, esto tiene mucho sentido.

¿Por qué? Debido a que la unidad más pequeña que necesita el desarrollador individual para operar es esa cadena completa. Eso es lo que la aplicación necesita para pasar a la biblioteca hash para verificar si una contraseña proporcionada es correcta o no. Desde la perspectiva de los desarrolladores, la biblioteca hash puede ser una caja negra, y ella no tiene que preocuparse por lo que realmente significan esas partes molestas.

Esto es algo bueno, porque la mayoría de los desarrolladores son humanos imperfectos (lo sé, porque yo también lo soy). Si dejas que separen esa cuerda y luego intentas unirlas todas, probablemente desordenen las cosas, como darles a todos los usuarios la misma sal o ninguna sal.

Sólo almacenar los parámetros en el código también es una mala idea. A medida que los procesadores se vuelvan más rápidos, es posible que desee aumentar el factor de costo en el futuro. Durante la fase de migración, diferentes contraseñas tendrán diferentes factores de costo. Por lo tanto, necesitará información en el nivel de contraseña sobre el factor de costo que se utilizó para hacer el hash.

    
respondido por el Anders 06.04.2018 - 16:36
fuente
47

Lo que te falta es que los hashes funcionan con los datos originales, menos la cadena original. Cuando desea validar una cadena contra un hash, toma la cadena suministrada, más los datos de hash originales (costo, sal, etc.) y genera un nuevo hash. Si el nuevo hash coincide con el anterior, la cadena se valida (en otras palabras, la cadena nunca se descifra , se reinicia ).

Tener la sal no te ayuda con la fuerza bruta. La sal es una parte esencial de un hachís, de la misma manera que los tambores forman parte de un bloqueo. Si lo sacas, nadie puede usarlo.

Separar el almacenamiento no tiene sentido. Tendrá que volver a ensamblar el hash completado para validarlo en la mayoría de los casos. Es por eso que todos los componentes se almacenan en una cadena útil de forma predeterminada.

    
respondido por el Machavity 06.04.2018 - 19:34
fuente
8

Sí, puede almacenarlo en un solo campo, y muchas bases de datos / aplicaciones almacenan el hash + sal en un solo campo / archivo, etc.

El más famoso es Linux (que no es una base de datos), que almacena el hash en el archivo / etc / shadow con el formato:

  

"$ id $ salt $ hashed", la forma imprimible de un hash de contraseña como se produce   por crypt (C), donde "$ id" es el algoritmo utilizado. (En GNU / Linux, "$ 1 $"   significa MD5, "$ 2a $" es Blowfish, "$ 2y $" es Blowfish (correcto   manejo de caracteres de 8 bits), "$ 5 $" es SHA-256 y "$ 6 $" es SHA-512, [4]   otros Unix pueden tener diferentes valores, como NetBSD.

     

(fuente: enlace )

La sal no debe ser secreta (o al menos no más secreta que el hash). Su propósito principal es hacer que los ataques de fuerza bruta sean mucho más difíciles, ya que el atacante tiene que usar una sal diferente para cada usuario individual.

Pero su pregunta tiene más matices, porque no solo está preguntando acerca de las sales, sino también de los parámetros. Cosas como el algoritmo de hash, el recuento de iteraciones y la sal. En cualquier caso, no almacene esto en el código, todavía pertenecen a la base de datos.

Imagina que tienes muchos usuarios y has usado SHA1 como algoritmo de hash. Entonces el campo de su base de datos sería algo como SHA1: SALT: HASH .

Si quisiera actualizar su base de datos a BCRYPT, ¿cómo haría esto?

Por lo general, implementaría algún código para que cuando un usuario inicie sesión, verifique la contraseña y, si es válida, vuelva a codificar la contraseña con un algoritmo más nuevo. Ahora el campo para el usuario se ve así: BCRYPT: SALT: HASH .

Pero entonces algunos usuarios estarán en SHA1 y otros en BCRYPT, y dado que esto es a nivel de usuario, necesita los parámetros que indican a su código qué usuarios están en la base de datos.

En resumen, almacenar los parámetros y el hash en un solo campo está bien, pero dividirlos por cualquier motivo (eficiencia, código más sencillo, etc.) también está bien. Lo que no está bien es almacenar esto en su código :)

TL:DR

Troy Hunt publicó recientemente un podcast que sugiere que, en lugar de migrar a BCRYPT de la manera anterior, es más efectivo simplemente tomar todos los hashes SHA1 que se encuentran actualmente en la base de datos, y hacerlos usando BCRYPT.

Efectivamente BCRYPT(SHA1(clear_password))

Cuando un usuario inicia sesión,

BCRYPT(SHA1(clear_password)) == <db_field>

De esta manera, todos los usuarios de la plataforma se actualizan a la vez, y no tiene una base de datos con múltiples formatos de hash para contraseñas. Muy limpio y muy bonito.

Creo que esta idea tiene mucho sentido, pero aunque todos migran a la vez, no es instantáneo. A menos que esté dispuesto a aceptar algún tiempo de inactividad en la aplicación (mientras vuelve a aplicar todas las contraseñas), seguirá habiendo un pequeño espacio de tiempo en el que algunos usuarios están en BCRYPT y otros en SHA1, por lo tanto, su base de datos todavía debe almacenar el parámetros del algoritmo de hash, y su código se ejecutaría en función de él.

    
respondido por el keithRozario 06.04.2018 - 19:00
fuente
4

Desde un punto de vista de seguridad, no importa si la contraseña de sal y hash se almacenan en un solo campo o en campos separados, aunque me inclino por un solo campo para simplificar. La única razón para separarlos es si su código de aplicación necesita pasar el salt y la contraseña por separado a la función de validación. Si el código de su aplicación solo requiere una única cadena combinada, entonces también puede almacenarlo de esa manera.

Como ejemplo, la Membresía ASP.NET más antigua divide el hash y el sal de la contraseña en dos campos DB, y la Identidad ASP.NET más reciente tiene el hash y el salt en un solo campo DB, y a su vez las funciones más nuevas han sido modificado para manejar la cadena única como entradas y salidas.

    
respondido por el TTT 06.04.2018 - 21:27
fuente
3
  

¿Es aceptable almacenar esto en un campo en una base de datos SQL (varchar (99) en este caso)

No. El tamaño de los datos puede cambiar en algún momento. Se debe utilizar un campo varchar (MAX) a menos que las especificaciones indiquen que el tamaño siempre será exactamente 99 y que no habrá variación de ese nunca . Deje que la base de datos se encargue de los requisitos de almacenamiento.

    
respondido por el Andrew Morton 07.04.2018 - 21:36
fuente
1

Para saber si es más o menos seguro, debemos entender el propósito de una sal.

Una sal sirve para algunos propósitos (que puedo imaginar)

  1. Prevenir ataques del diccionario

Un ataque de diccionario es donde se usa una palabra lógica como parte de una contraseña. El arquetipo es la palabra password o incluso P@ssW0rd . Las personas son imperfectas y es más fácil para ellos recordar palabras y luego cadenas aleatorias de letras y números. Un ataque de diccionario se basa en esto para acortar el camino que toma un ataque de fuerza bruta. Obviamente, si le agregamos una porción aleatoria de cosas, entonces hace que este tipo de ataque sea imposible, o no tiene sentido y los devuelve a la fuerza bruta forzando todo el asunto.

Si un atacante conoce la sal utilizada, tendría que editar todos sus archivos de diccionario para cada contraseña, y eso supone que saben cómo se agrega la sal a la contraseña original. Un gran beneficio de una lista de diccionarios es decir que toma 1000 contraseñas y 1 millón de palabras de diccionario. Luego los recorres tratando de obtener algunas coincidencias con contraseñas más débiles. Por lo tanto, tener que editar 1 millón de palabras 1000 veces no es realmente práctico.

  1. Evita los ataques de tabla Hash o Rainbow.

Una tabla Rainbow es donde los hashes se calculan previamente y se almacenan en algún tipo de base de datos. Por ejemplo, podría tomar MD5 y simplemente comenzar a hacer hashing aleatorio y guardarlo. Luego, cuando quiere descifrar una contraseña, simplemente busca en la tabla del arco iris.

Si un atacante tiene la sal, tiene que volver a compilar la tabla del arco iris para cada sal utilizada. El beneficio de este ataque es tener esos datos compilados por adelantado y reutilizándolos una y otra vez. Esto los pone de nuevo a fuerza bruta forzando la contraseña. Al extraer y eliminar todas las contraseñas de manera diferente, eso básicamente significa que debe volver a calcular la tabla del arco iris para cada sal. Por eso es importante usar diferentes sales para cada contraseña.

Veranos

Ninguna de estas razones realmente confía en que la sal sea secreta. Obviamente, todos son menos fuertes si un atacante conoce la sal. Pero la información adicional que obtienen siempre les ayudará. Así que no diría que vaya a publicitarlo, pero hay un dicho acerca de la seguridad basada en la oscuridad ...

Descargo de responsabilidad No soy un experto en criptología, pero estas son algunas de las principales razones que me vienen a la mente cuando pienso en las sales.

Espero que ayude.

    
respondido por el ArtisticPhoenix 08.04.2018 - 02:42
fuente
0

La sal solo se usa para bloquear los ataques de las tablas del arco iris. Por lo tanto, su sal puede almacenarse con la contraseña con hash, como se hace en el sistema GNU / Linux más reciente donde se almacena la sal en / etc / shadow.

    
respondido por el maggick 06.04.2018 - 16:36
fuente

Lea otras preguntas en las etiquetas