Pregunta

Actualmente estamos almacenando contraseñas de texto sin formato para una aplicación web que tenemos.

Sigo recomendando pasar a un hash de contraseña, pero otro desarrollador dijo que esto sería menos seguro: más contraseñas podrían coincidir con el hash y un ataque de diccionario/hash sería más rápido.

¿Hay algo de verdad en este argumento?

¿Fue útil?

Solución

Absolutamente ninguno.Pero no importa.He publicado una respuesta similar antes:

Es desafortunado, pero las personas, incluso los programadores, son demasiado emocionales para dejarse influenciar fácilmente por argumentos.Una vez que haya invertido en su puesto (y, si publica aquí, así es), no es probable que lo convenza sólo con hechos.Lo que hay que hacer es cambiar la carga de la prueba.Debes sacarlo a buscar datos que espera que te convenzan y, al hacerlo, descubrir la verdad.Desafortunadamente, él tiene el beneficio del status quo, por lo que el camino hasta allí es difícil.

Otros consejos

De Wikipedia

Algunos sistemas informáticos almacenan contraseñas de usuario, con las cuales comparar los intentos de inicio de sesión de usuario, como ClearText.Si un atacante obtiene acceso a un almacén de contraseñas tan interna, todas las contraseñas y, por lo tanto, todas las cuentas de usuario se verán comprometidas.Si algunos usuarios emplean la misma contraseña para cuentas en diferentes sistemas, también se verán comprometidos.

Los sistemas más seguros almacenan cada contraseña en una forma criptográficamente protegida, por lo que el acceso a la contraseña real seguirá siendo difícil para un fisoteo que obtenga acceso interno al sistema, mientras que la validación de los intentos de acceso de los usuarios sigue siendo posible.

Un enfoque común almacena solo una forma "hash" de la contraseña de texto sin formato.Cuando un usuario escribe una contraseña en dicho sistema, el software de manejo de contraseñas se ejecuta a través de un algoritmo de hash criptográfico, y si el valor hash generado por la entrada del usuario coincide con el hash almacenado en la base de datos de contraseña, se permite el acceso al usuario.El valor hash se crea aplicando una función hash criptográfica a una cadena que consiste en la contraseña enviada y, por lo general, otro valor conocido como sal.La sal evita que los atacantes construyan una lista de valores hash para contraseñas comunes.MD5 y SHA1 se usan con frecuencia funciones de hash criptográfica.

Hay mucho más que puedes leer sobre el tema en esa página.En mi opinión, y en todo lo que he leído y con lo que he trabajado, el hash es un mejor escenario a menos que utilice un algoritmo muy pequeño (<256 bits).

No hay absolutamente ninguna excusa para mantener contraseñas de texto sin formato en la aplicación web.Utilice un algoritmo hash estándar (¡SHA-1, no MD5!) con un valor de sal, para que los ataques de arcoíris sean imposibles.

No entiendo cómo su otro desarrollador dice que "más contraseñas podrían coincidir con el hash".

Existe un argumento para que un "ataque hash sería más rápido", pero solo si no agrega sal a las contraseñas porque están codificadas.Normalmente, las funciones hash le permiten proporcionar una sal, lo que hace que el uso de una tabla hash conocida sea una pérdida de tiempo.

Personalmente, diría "no".Con base en lo anterior, así como en el hecho de que si de alguna manera obtienes exposición de texto sin cifrar, un valor hash salado es de poco valor para alguien que intenta ingresar.El hash también ofrece la ventaja de hacer que todas las contraseñas parezcan tener la misma longitud.

es decir, si el hash de cualquier cadena siempre da como resultado un hash de 20 caracteres, entonces si solo tiene que mirar el hash, no podrá saber si la contraseña original tenía ocho caracteres o dieciséis, por ejemplo.

Encontré exactamente el mismo problema en mi lugar de trabajo.Lo que hice para convencerlo de que el hashing era más seguro fue escribir una inyección SQL que devolvió la lista de usuarios y contraseñas de la sección pública de nuestro sitio.Se intensificó de inmediato como un problema de seguridad importante :)

Para evitar ataques de diccionario/hash, asegúrese de utilizar un token que sea único para cada usuario y estático (nombre de usuario/fecha de ingreso/guía de usuario funciona bien)

Si no agrega sal a su contraseña, es sospechoso de sufrir ataques de Rainbow Table (diccionarios precompilados que tienen entradas válidas para un hash determinado).

El otro desarrollador debería dejar de hablar de seguridad si almacena contraseñas en texto sin formato y comenzar a leer sobre seguridad.

Las colisiones son posibles, pero generalmente no son un gran problema para las aplicaciones de contraseñas (son principalmente un problema en áreas donde se utilizan hashes como una forma de verificar la integridad de los archivos).

Entonces:Sal tus contraseñas (agregando Salt al lado derecho de la contraseña*) y usa un buen algoritmo hash como SHA-1 o preferiblemente SHA-256 o SHA-512.

PD:Un poco más de detalle sobre Hashes aquí.

* No estoy seguro de si Salt debe ir al principio o al final de la cadena.El problema es que si tiene colisiones (dos entradas con el mismo hash), agregar Salt en el lado "incorrecto" no cambiará el hash resultante.De todas formas no tendrás grandes problemas con Rainbow Tables, sólo con colisiones

Hay un viejo dicho sobre los programadores que se hacen pasar por criptógrafos :)

Jeff Atwood tiene una buena publicación sobre el tema: Probablemente estés almacenando contraseñas incorrectamente

Para responder más extensamente, estoy de acuerdo con todo lo anterior, el hash lo hace más fácil En teoria para obtener la contraseña del usuario ya que varias contraseñas coinciden con el mismo hash.Sin embargo, esto es mucho menos probable que suceda que alguien que tenga acceso a su base de datos.

Lo cierto es que si haces hash en algo, sí, habrá colisiones, por lo que sería posible que dos contraseñas diferentes desbloquearan la misma cuenta.

Sin embargo, desde un punto de vista práctico, ese es un argumento pobre: ​​una buena función hash (md5 o sha1 estaría bien) puede garantizar que para todas las cadenas significativas, especialmente las cortas, no habrá colisiones.Incluso si así fuera, tener dos contraseñas coincidentes para una cuenta no es un gran problema: si alguien está en condiciones de adivinar contraseñas al azar lo suficientemente rápido como para poder ingresar, tienes problemas mayores.

Yo diría que almacenar las contraseñas en texto plano representa un riesgo de seguridad mucho mayor que las colisiones de hash en la coincidencia de contraseñas.

No soy un experto en seguridad, pero tengo la sensación de que si el texto sin formato fuera más seguro, el hash no existiría en primer lugar.

En teoría, sí.Las contraseñas pueden ser más largas (más información) que un hash, por lo que existe la posibilidad de que se produzcan colisiones de hash.Sin embargo, la mayoría de los ataques se basan en diccionarios y la probabilidad de colisiones es infinitamente menor que la de una coincidencia directa exitosa.

Depende de contra qué te estés defendiendo.Si se trata de un atacante que elimina su base de datos (o engaña a su aplicación para que muestre la base de datos), entonces las contraseñas de texto sin formato son inútiles.Hay muchos ataques que se basan en convencer a la aplicación para que libere sus datos privados: inyección de SQL, secuestro de sesión, etc.A menudo es mejor no conservar los datos en absoluto, sino conservar la versión hash para que los malos no puedan usarla fácilmente.

Como sugiere su compañero de trabajo, esto se puede solucionar de manera trivial ejecutando el mismo algoritmo hash en un diccionario y usando tablas de arcoíris para extraer la información.La solución habitual es utilizar una sal secreta más información adicional del usuario para que los resultados hash sean únicos, algo como:

String hashedPass=CryptUtils.MD5("alsdl;ksahglhkjfsdkjhkjhkfsdlsdf" + user.getCreateDate().toString() +  user.getPassword);

Siempre que su sal sea secreta o su atacante no conozca la fecha precisa de creación del registro del usuario, un ataque de diccionario fallará, incluso en el caso de que pueda abrir el campo de contraseña.

Nada es menos seguro que almacenar contraseñas en texto plano.Si está utilizando un algoritmo de hash decente (al menos SHA-256, pero incluso SHA-1 es mejor que nada), entonces sí, las colisiones son posibles, pero no importa porque dado un hash, es imposible* calcular qué hash de cadenas.Si codifica el nombre de usuario CON la contraseña, esa posibilidad también desaparece.

* - técnicamente no imposible, pero "computacionalmente inviable"

Si el nombre de usuario es "graeme" y la contraseña es "stackoverflow", cree una cadena "graeme-stackoverflow-1234" donde 1234 es un número aleatorio, luego haga un hash y almacene "salida hash1234" en la base de datos.Cuando se trata de validar una contraseña, tome el nombre de usuario, la contraseña proporcionada y el número del final del valor almacenado (el hash tiene una longitud fija, por lo que siempre puede hacer esto) y compárelos con el hash. parte del valor almacenado.

más contraseñas podrían coincidir con el hash y un ataque de diccionario/hash sería más rápido.

Si y no.Utilice un algoritmo hash moderno, como una variante SHA, y ese argumento se vuelve muy, muy débil.¿Realmente hay que preocuparse si ese ataque de fuerza bruta va a durar sólo 352 años en lugar de 467 años?(Broma anecdótica). El valor que se puede obtener (no tener la contraseña almacenada en texto plano en el sistema) supera con creces la preocupación de su colega.

Espero que me perdonen por incluir una solución que escribí sobre esto, usando JavaScript del lado del cliente para codificar la contraseña antes de transmitirla: http://blog.asgeirnilsen.com/2005/11/password-authentication- without.html

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top