¿Dónde guardas tus hilos de sal?
Siempre he usado una cadena salt por entrada adecuada al codificar contraseñas para el almacenamiento de bases de datos. Para mis necesidades, almacenar el salt en la base de datos junto a la contraseña hash siempre ha funcionado bien.
Sin embargo, algunas personas recomiendan almacenar la sal por separado de la base de datos. Su argumento es que si la base de datos se ve comprometida, un atacante aún puede crear una tabla arcoíris teniendo en cuenta una cadena de sal particular para poder descifrar una cuenta a la vez. Si esta cuenta tiene privilegios de administrador, es posible que ni siquiera necesite descifrar otras.
Desde una perspectiva de seguridad, ¿merece la pena almacenar sales en un lugar diferente? Considere una aplicación web con el código del servidor y la base de datos en la misma máquina. Si las sales se almacenan en un archivo plano en esa máquina, es probable que si la base de datos se ve comprometida, el archivo salt también lo esté.
¿Hay alguna solución recomendada para esto?
El objetivo de las tablas Rainbow es que se crean con anticipación y se distribuyen en masa para ahorrar tiempo de cálculo a otros: se necesita el mismo tiempo para generar tablas Rainbow sobre la marcha como para descifrar la combinación contraseña+sal directamente (ya que efectivamente, lo que se hace al generar tablas de arco iris es ejecutar previamente los cálculos para forzar el hash), por lo que el argumento de que conociendo la sal alguien podría "generar una tabla de arco iris" es falso.
No tiene ningún sentido almacenar sales en un archivo separado siempre que sean por usuario; el objetivo de la sal es simplemente hacer que una tabla de arco iris no pueda romper todas las contraseñas en la base de datos.
Proporcionaré una visión ligeramente diferente sobre esto.
Siempre guardo la sal mezclada con el hash de contraseña salado.
Por ejemplo, colocaré la primera mitad de la sal antes del hash salado de la contraseña y la última mitad de la sal después del hash salado de la contraseña. La aplicación conoce este diseño, por lo que puede recuperar estos datos y obtener el hash salt y la contraseña saltada.
Mi justificación para este enfoque:
Si los datos de contraseña/hash se ven comprometidos y caen en manos de un atacante, el atacante no sabrá cuál es la sal al mirar los datos. De esta manera, un atacante prácticamente no puede realizar un ataque de fuerza bruta para obtener una contraseña que coincida con el hash, ya que, para empezar, no conoce el hash y no tiene forma de saber qué partes de los datos son partes de la sal, o partes del hash de contraseña salada ( a menos que conozca la lógica de autenticación de su aplicación ).
Si el hash de la contraseña salada se almacena tal cual, entonces se puede realizar un ataque de fuerza bruta para obtener una contraseña que, cuando se sala y se aplica el hash, produce los mismos datos que el hash de la contraseña salada.
Sin embargo, por ejemplo, incluso si el hash de la contraseña salada se almacenara tal cual, pero antepuesto por un único byte aleatorio, siempre y cuando el atacante no sepa que este primer byte debe descartarse, esto también aumentaría la dificultad. de ataque. Su aplicación sabrá descartar el primer byte de los datos cuando se utilice para autenticar a su usuario.
La conclusión de esto...
1) Nunca almacene los datos que utiliza su aplicación de autenticación en su forma exacta.
2) Si es posible, mantenga en secreto su lógica de autenticación para mayor seguridad.
Da un paso más..
Si no puede mantener en secreto la lógica de autenticación de su aplicación, mucha gente sabe cómo se almacenan sus datos en la base de datos. Y supongamos que ha decidido almacenar el hash de contraseña salado mezclado con la sal, con parte de la sal anteponiendo el hash de contraseña salada y el resto de la sal agregándolo.
Al generar la sal aleatoria, también puede decidir aleatoriamente qué proporción de su sal almacenará antes/después del hash de contraseña salada.
Por ejemplo, genera una sal aleatoria de 512 bytes. Agrega el salt a su contraseña y obtiene el hash SHA-512 de su contraseña saltada. También genera un entero aleatorio 200. Luego almacena los primeros 200 bytes de la sal, seguidos del hash de contraseña salada, seguido del resto de la sal.
Al autenticar la entrada de contraseña de un usuario, su aplicación pasará por alto la cadena y asumirá que el primer byte de los datos es el primer byte de la sal, seguido del hash salado. Este pase fallará. La aplicación continuará usando los primeros 2 bytes de los datos como los primeros 2 bytes de la sal y se repetirá hasta que se encuentre un resultado positivo después de usar los primeros 200 bytes como los primeros 200 bytes de la sal. Si la contraseña es incorrecta, la aplicación continuará intentando todas las permutaciones hasta que no encuentre ninguna.
Las ventajas de este enfoque:
Mayor seguridad: incluso si se conoce su lógica de autenticación, la lógica exacta se desconoce en el momento de la compilación. Es prácticamente imposible realizar un ataque de fuerza bruta, incluso conociendo la lógica exacta. Una mayor cantidad de sal aumentará aún más la seguridad.
Las desventajas de este enfoque:
Dado que la lógica exacta se infiere en tiempo de ejecución, este enfoque consume mucha CPU. Cuanto mayor sea la longitud de la sal, más intensivo será el uso de CPU en este enfoque.
La autenticación de contraseñas incorrectas implicará el mayor costo de CPU. Esto puede resultar contraproducente para las solicitudes legítimas, pero aumenta la seguridad contra los atacantes.
Este enfoque se puede implementar de varias maneras y se puede hacer aún más seguro mediante el uso de salts de ancho variable y/o hashes de contraseña saltados.
A menudo, se anteponen al hash y se almacenan en el mismo campo.
No es necesario almacenarlas por separado; el punto es usar una sal aleatoria para cada contraseña, de modo que no se pueda usar una sola tabla de arcoíris con todo el conjunto de hashes de contraseñas. Con sales aleatorias, un atacante debe aplicar fuerza bruta a cada hash por separado (o calcular una tabla de arco iris para todas las sales posibles; mucho más trabajo).
Si tuviera una ubicación de almacenamiento más segura, tendría sentido simplemente almacenar los hashes allí.
Basado en el libro Desarrollo de aplicaciones web ASP.NET MVC 4 de William Penberthy:
- Obtener acceso a las sales almacenadas en una base de datos separada requiere que los piratas informáticos pirateen dos bases de datos diferentes para obtener acceso a la sal y a la contraseña de la sal. Almacenarlos en la misma tabla que la contraseña, o incluso en otra tabla de la misma base de datos, significaría que cuando los piratas informáticos obtengan acceso a la base de datos, tendrán acceso tanto al salt como al hash de la contraseña. Debido a que la seguridad incluye el proceso de hacer que la piratería en el sistema sea demasiado costosa o requiera mucho tiempo para que valga la pena, duplicar la cantidad de acceso que un pirata informático tendría que obtener debería hacer que el sistema sea más seguro.
- La facilidad de uso es la razón principal para mantener las sales en la misma base de datos que las contraseñas hash. No tendría que asegurarse de que dos bases de datos estén siempre disponibles al mismo tiempo y siempre sincronizadas. La ventaja de tener un salt es mínima si cada usuario tiene un salt aleatorio porque, aunque podría facilitar el descubrimiento de la contraseña de un individuo, la cantidad de fuerza necesaria para descifrar las contraseñas del sistema en general será alta. En este nivel de discusión, esa es realmente la expectativa: proteger las contraseñas. Si los piratas informáticos han adquirido una copia de la base de datos, los datos de su aplicación ya están comprometidos. En este punto, la cuestión es mitigar los riesgos de los usuarios debido al potencial de las contraseñas compartidas.
- El requisito de mantener dos bases de datos vinculadas separadas es extenso. Por supuesto, añade la percepción de seguridad, pero la única ventaja que ofrece es que protege una contraseña, un único elemento de datos. Si cada campo de la base de datos se cifrara individualmente y se usara la misma sal para eso, tendría más sentido almacenarlo por separado de los datos porque se mejora la seguridad básica de su sistema.