¿Dónde guardas tus cadenas de sal?

250

Siempre he usado una cadena de sal por entrada adecuada al cifrar las contraseñas para el almacenamiento de la base de datos. Para mis necesidades, almacenar la sal en la base de datos junto a la contraseña hash siempre ha funcionado bien.

Sin embargo, algunas personas recomiendan que la sal se almacene por separado de la base de datos. Su argumento es que si la base de datos se ve comprometida, un atacante aún puede construir una tabla de arco iris teniendo en cuenta una cadena de sal particular para descifrar una cuenta a la vez. Si esta cuenta tiene privilegios de administrador, es posible que ni siquiera necesite descifrar ninguna otra.

Desde una perspectiva de seguridad, ¿vale 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, lo más probable es que si la base de datos se ve comprometida, el archivo de sales también lo estará.

¿Hay alguna solución recomendada para esto?

friedo
fuente
99
Si hay un lugar donde puede almacenar la sal que el atacante no puede alcanzar, entonces también debe almacenar las contraseñas allí. Pero, ¿por qué no usar una sal diferente para cada contraseña?
jrockway
8
Él está usando una sal diferente para cada contraseña, jrockway.
Amber
99
¿Qué tan grandes son tus sales? Sus sales deben ser lo suficientemente grandes (¿32 bits?) Que prácticamente no hay posibilidad de que una tabla de arco iris haya sido calculada previamente para ello.
M. Dudley
@emddudley en estos días he tenido la costumbre de usar un número entero de 64 bits como sal, pero no hay ninguna razón por la que no pueda alargarlos.
friedo
10
Autor de PWDTK aquí sourceforge.net/projects/pwdtknet , honestamente no me preocuparía y simplemente almacenaría sal en la misma base de datos como contraseña. De todos modos, siempre debe suponer que un atacante conoce la sal, por lo que debe centrarse en usar una sal GRANDE CRIPTO-ALEATORIA y realizar suficiente estiramiento clave (iteraciones en PBKDF2) para que sea imposible hacer incluso una tabla de arcoíris para una sal conocida. Honestamente, lo que está tratando de lograr al poner la sal en otro lugar es "Seguridad por oscuridad" y, en general, no sirve de nada cuando mira cosas como otro servidor que posiblemente se caiga.
thashiznets

Respuestas:

259

El objetivo de las tablas de arco iris es que se crean de antemano y se distribuyen en masa para ahorrar tiempo de cálculo para los demás: se tarda tanto tiempo en generar tablas de arco iris sobre la marcha como simplemente descifrar la combinación de contraseña + sal directamente (ya que efectivamente, lo que se está haciendo al generar tablas de arco iris es ejecutar previamente los cálculos para forzar el hash), por lo que el argumento de que al conocer la sal alguien podría "generar una tabla de arco iris" es falso.

No tiene sentido almacenar las sales en un archivo separado siempre que sean por usuario: el objetivo de la sal es simplemente hacerlo para que una tabla de arco iris no pueda romper todas las contraseñas en la base de datos.

Ámbar
fuente
17
Convenido. El modelo de amenaza contra el que está protegiendo al almacenar la sal por separado es un usuario que de alguna manera puede acceder a la sal en el DB a través de medios nefastos, pero no el hash (en el DB). Y que esa persona comenzará a calcular una mesa de arco iris por adelantado, suponiendo que podrá encontrar el hash más tarde. No es imposible, pero tampoco vale la pena el esfuerzo de ingeniería para defender contra esta única vía de ataque.
Tom Ritter
Buena publicación, me preguntaba lo mismo. Nunca pensé en una sal por usuario. Estaba pensando que una sola sal funcionaría para todos los usuarios. ¿Qué pasa con una sal que se almacena como un archivo XML cargado por el servidor de aplicaciones? o tal vez de alguna manera codificado en un servlet?
jigzat
99
@Jigzat: la salazón no tiene sentido si no tiene una sal separada para cada usuario. El objetivo de las sales es hacer que romper los hashes sea una tarea separada para cada contraseña de usuario; Si la sal es la misma para todos, entonces ese no es el caso.
Ámbar
3
@TomRitter ese no es el único caso. asume que todas las contraseñas son complicadas. algunos atacantes pueden tomar la sal y el hash y verificar solo las 10,000 contraseñas más comunes. de esa manera obtendrán un número decente de personas. sin embargo, si no tienen acceso a la sal, es similar a que el usuario tenga una contraseña más segura y más larga. ahora, qué tan probable es que la base de datos de sal permanezca segura mientras se roba la base de datos de contraseñas está en debate, pero ese es un tema aparte.
chacham15
@Amber, creo que TomRitter es correcto. Almacenar la sal por separado significa la diferencia entre obligar a un atacante a usar un ataque de fuerza bruta versus un ataque de diccionario más fácil. Si conoce la sal, puede agregarla durante una ejecución del ataque del diccionario de fábrica. Si puede defender su sal al 100%, simplemente puede usar la misma sal y forzar a los atacantes a forzarlo todo (incluso para los usuarios que usan "contraseña" como contraseña). Pero puedes defender tu sal ... probablemente no. Por lo tanto, también podría reducir los puntos de falla al almacenarlo junto al hash y aplicar reglas de contraseña más fuertes.
Ultratrunks
35

Proporcionaré una versión ligeramente diferente de esto.

Siempre guardo la sal mezclada con el hash de contraseña salada.

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 obtener estos datos y obtener el hash de sal y contraseña salada.

Mi razonamiento 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 de 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 no conoce el hash para empezar 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 él conozca la lógica de autenticación de su aplicación ).

Si el hash de contraseña salada se almacena tal cual, entonces se puede realizar un ataque de fuerza bruta para obtener una contraseña que cuando se salada y hash produce los mismos datos que el hash de contraseña salada.

Sin embargo, por ejemplo, incluso si el hash de la contraseña salada se almacenó tal cual, pero se colocó previamente con un solo byte aleatorio, siempre que el atacante no sepa que este primer byte debe descartarse, esto también aumentaría la dificultad de ataque Su aplicación debería descartar el primer byte de los datos cuando se utiliza 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 su lógica de autenticación en secreto para mayor seguridad.

Ve un paso más allá ...

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 suponga que ha decidido almacenar el hash de contraseña salada mezclado junto con la sal, con algo de sal que antecede al hash de contraseña salada, y el resto de la sal añadiéndola.

Al generar la sal al azar, también puede decidir al azar 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. Agregue la sal a su contraseña y obtenga el hash SHA-512 de su contraseña salada. También genera un número entero aleatorio 200. Luego almacena los primeros 200 bytes de la sal, seguidos del hash de la contraseña salada, seguido del resto de la sal.

Al autenticar la entrada de contraseña de un usuario, su aplicación pasará la cadena y asumirá que el primer 1 byte de los datos es el primer 1 byte de la sal, seguido del hash salado. Este pase fallará. La aplicación continuará utilizando 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á probando todas las permutaciones hasta que no se encuentre ninguna.

Los pros de este enfoque:

Mayor seguridad: incluso si se conoce su lógica de autenticación, se desconoce la lógica exacta en tiempo de compilación. Es prácticamente imposible realizar un ataque de fuerza bruta, incluso con el conocimiento de la lógica exacta. El aumento de la longitud de la sal aumentará aún más la seguridad.

Los contras de este enfoque:

Dado que la lógica exacta se infiere en tiempo de ejecución, este enfoque requiere mucha CPU. Cuanto más larga sea la sal, más intensivo será este enfoque.

La autenticación de contraseñas incorrectas implicará el mayor costo de CPU. Esto puede ser contraproducente para 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 sales de ancho variable y / o hashes de contraseña salada.

Ibraheem
fuente
99
Con su enfoque, solo está agregando un secreto a su proceso de hash (el algoritmo que aplica la sal). Este secreto se puede agregar mucho más fácilmente agregando un pimiento adicionalmente a la sal, traté de señalar esto en mi tutorial . Las funciones hash modernas como BCrypt aplicarán la sal por sí mismas, utilizando la sal original en cada iteración, por lo que no tendría control sobre esto de todos modos.
martinstoeckli
@martinstoeckli Si bien tiene razón de que BCrypt aplica la sal por su cuenta, el almacenamiento de esa sal + hash depende de usted como desarrollador. Por lo tanto, puede agregar fácilmente un pimiento al salt + hash y conservarlo en la base de datos. Luego, en la recuperación posterior, lee el valor de la base de datos, elimina el valor de pimienta y pasa el valor restante a BCrypt.
PeterToTheThird
2
@PeterToTheThird: esto negaría la ventaja del pimiento. El pepper agrega un secreto del lado del servidor, y solo funciona mientras permanezca en secreto (opuesto a la sal). Un ataque típico es la inyección SQL, cuando alguien obtiene acceso a la base de datos pero no al código, un pimiento almacenado en la base de datos será inútil. La mayoría de las implementaciones de BCrypt agregarán la sal automáticamente al valor hash resultante, por lo que este valor ya contiene la sal, el factor de costo, el algoritmo y el hash. Esta cadena se puede almacenar en un solo campo de 60 caracteres de longitud.
Martinstoeckli
Para agregar, cuando se utiliza una función de "fortalecimiento de clave" como BCrypt, no tiene control sobre el uso de la sal. Sin embargo, si quisieras usar un pimiento, simplemente agregarías el pimiento a la sal, y lo usarías como una "sal con pimienta" en lugar de la entrada de "sal" a la función de hash. El "pimiento" es un dato adecuado que no se almacena en la base de datos, sino que se incrusta en el código de autenticación o se almacena en otra ubicación segura. Abordé el problema desde una perspectiva genérica, usando SHA-512 como una función de ejemplo, pero BCrypt, etc. también se puede usar de manera similar.
Ibraheem
2
@martinstoeckli: sí, la implementación real depende de la función hash que use. Obviamente, debe tener en cuenta los parámetros y las salidas de la función hash al implementar su lógica de autenticación. En última instancia, un pimiento es solo otra variable introducida en su función de hashing, que no se almacena en la misma ubicación que la sal y el hash.
Ibraheem
23

A menudo, se anteponen al hash y se almacenan en el mismo campo.

No es necesario almacenarlos por separado: el punto es usar una sal aleatoria para cada contraseña para que una sola tabla de arco iris no se pueda usar contra 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íris 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 hash allí.

nadie
fuente
44
Pero, ¿qué sucede si todas las contraseñas hash se filtran, incluida su sal coincidente? ¿No es eso tan inseguro?
mghaoui
10
@mghaoui Pero si quisieras saber la "contraseña" aún tendrías que construir una Tabla Arco Iris para cada sal, a menos que algunas de las sales sean iguales.
Franklin
4

Basado en el libro de desarrollo de aplicaciones web ASP.NET MVC 4 de William Penberthy:

  1. Para obtener acceso a las sales almacenadas en una base de datos separada, los piratas informáticos deben hackear dos bases de datos diferentes para obtener acceso a la sal y la contraseña salada. 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 obtienen acceso a la base de datos, tendrán acceso tanto al hash de sal como a la contraseña. Debido a que la seguridad incluye el proceso de hacer que la piratería en el sistema sea demasiado costosa o que requiera mucho tiempo para valer la pena, duplicar la cantidad de acceso que tendría que obtener un pirata informático debería hacer que el sistema sea más seguro.
  2. 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 una sal es mínima si cada usuario tiene una sal aleatoria 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, el problema es mitigar los riesgos de los usuarios debido al potencial de las contraseñas compartidas.
  3. El requisito de mantener dos bases de datos vinculadas separadas es extenso. Por supuesto, agrega la percepción de seguridad, pero la única ventaja que brinda es que protege una contraseña, un solo elemento de datos. Si cada campo de la base de datos se encriptara individualmente, y se usara esta 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.
DaNeSh
fuente
Sin embargo, si la aplicación puede autenticarse en ambas bases de datos, ¿no es esencialmente lo mismo que si fuera una base de datos, si el atacante ha comprometido el código de la aplicación?
John Ernest
0

El objetivo de una sal es hacer que todas las tablas del arco iris sean inútiles y requieren que se haga un nuevo conjunto de ellas. Se tarda tanto en adivinar una cuerda como en hacer una mesa arcoiris. Por ejemplo, el hash SHA-256 de "contraseña" es 5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8. Después de agregar una sal, como "badpassword", la nueva cadena que se va a codificar es "passwordbadpassword" que, debido al efecto de avalancha, cambia drásticamente la salida a 457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6.

Normalmente, la sal solo se almacena en la misma base de datos que la contraseña, también porque si una base de datos está pirateada, es probable que la otra también lo esté.

Eric Jin
fuente