Actualización: tenga en cuenta que no estoy preguntando qué es una sal, qué es una tabla de arcoíris, qué es un ataque de diccionario o cuál es el propósito de una sal. Estoy preguntando: si conoce la sal y el hash de los usuarios, ¿no es bastante fácil calcular su contraseña?
Entiendo el proceso y lo implemento yo mismo en algunos de mis proyectos.
s = random salt
storedPassword = sha1(password + s)
En la base de datos que almacena:
username | hashed_password | salt
Cada implementación de salazón que he visto agrega la sal al final de la contraseña o al comienzo:
hashed_Password = sha1(s + password )
hashed_Password = sha1(password + s)
Por lo tanto, un ataque de diccionario de un hacker que se precie (ja, ja) simplemente ejecutaría cada palabra clave contra las sales almacenadas en las combinaciones comunes enumeradas anteriormente.
¿Seguramente la implementación descrita anteriormente simplemente agrega otro paso para el pirata informático, sin resolver realmente el problema subyacente? ¿Qué alternativas existen para solucionar este problema o estoy entendiendo mal el problema?
Lo único que puedo pensar en hacer es tener un algoritmo de combinación secreto que une la sal y la contraseña en un patrón aleatorio, o agrega otros campos de usuario al proceso de hash, lo que significa que el hacker tendría que tener acceso a la base de datos Y el código para encajar para que un ataque de diccionario resulte fructífero. (Actualización, como se señaló en los comentarios, es mejor asumir que el pirata informático tiene acceso a toda su información, por lo que probablemente esto no sea lo mejor).
Permítanme dar un ejemplo de cómo propongo que un pirata informático piratee la base de datos de un usuario con una lista de contraseñas y hashes:
Datos de nuestra base de datos pirateada:
RawPassword (not stored) | Hashed | Salt
--------------------------------------------------------
letmein WEFLS... WEFOJFOFO...
Diccionario de contraseñas común:
Common Password
--------------
letmein
12345
...
Para cada registro de usuario, haga un bucle de las contraseñas comunes y realice un hash:
for each user in hacked_DB
salt = users_salt
hashed_pw = users_hashed_password
for each common_password
testhash = sha1(common_password + salt)
if testhash = hashed_pw then
//Match! Users password = common_password
//Lets visit the webpage and login now.
end if
next
next
Espero que esto ilustre mucho mejor mi punto.
Dadas 10,000 contraseñas comunes y 10,000 registros de usuarios, necesitaríamos calcular 100,000,000 hashes para descubrir tantas contraseñas de usuarios como sea posible. Puede que tarde unas horas, pero no es realmente un problema.
Actualización sobre la teoría del craqueo
Asumiremos que somos un servidor web corrupto, que tiene acceso a una base de datos de hashes y sales SHA1, junto con su algoritmo para mezclarlos. La base de datos tiene 10.000 registros de usuarios.
Este sitio afirma poder calcular 2,300,000,000 hash SHA1 por segundo usando la GPU. (En la situación del mundo real probablemente será más lento, pero por ahora usaremos esa cifra citada).
(((95 ^ 4) / 2300000000) / 2) * 10000 = 177 segundos
Dado un rango completo de 95 caracteres ASCII imprimibles, con una longitud máxima de 4 caracteres, dividida por la tasa de cálculo (variable), dividida por 2 (asumiendo que el tiempo promedio para descubrir la contraseña requerirá en promedio el 50% de permutaciones) para 10,000 los usuarios tardarían 177 segundos en calcular todas las contraseñas de los usuarios cuya longitud sea <= 4.
Ajustémoslo un poco por realismo.
(((36 ^ 7) / 1000000000) / 2) * 10000 = 2 días
Suponiendo que no se distingue entre mayúsculas y minúsculas, con una longitud de contraseña <= 7, solo caracteres alfanuméricos, tomaría 4 días resolver los registros de 10,000 usuarios, y he reducido a la mitad la velocidad del algoritmo para reflejar la sobrecarga y las circunstancias no ideales.
Es importante reconocer que este es un ataque de fuerza bruta lineal, todos los cálculos son independientes entre sí, por lo que es una tarea perfecta para que múltiples sistemas la resuelvan. (IE es fácil de configurar 2 computadoras que ejecutan un ataque desde diferentes extremos que requerirían la mitad del tiempo de ejecución).
Dado el caso de hash recursiva de una contraseña 1000 veces para hacer esta tarea más costosa computacionalmente:
(((36 ^ 7) / 10000000000) / 2) * 1000 segundos = 10,8839117 horas
Esto representa una longitud máxima de 7 caracteres alfanuméricos, a una velocidad de ejecución inferior a la mitad de la cifra citada para un usuario .
El hash recursivo 1000 veces bloquea eficazmente un ataque general, pero los ataques dirigidos a los datos del usuario siguen siendo vulnerables.
fuente
Respuestas:
Sí, solo necesita 3 días para sha1 (salt | contraseña). Es por eso que los buenos algoritmos de almacenamiento de contraseñas utilizan hash de 1000 iteraciones: necesitará 8 años.
fuente
No detiene los ataques de diccionario.
Lo que hace es evitar que alguien que logra obtener una copia de su archivo de contraseña use una tabla de arco iris para averiguar cuáles son las contraseñas de los hashes.
Sin embargo, eventualmente puede ser forzado. La respuesta a esa parte es obligar a sus usuarios a no utilizar palabras del diccionario como contraseñas (requisitos mínimos de al menos un número o carácter especial, por ejemplo).
Actualización :
Debería haber mencionado esto antes, pero algunos (¿la mayoría?) Los sistemas de contraseñas usan una sal diferente para cada contraseña, probablemente almacenada con la contraseña misma. Esto hace que una sola mesa de arco iris sea inútil. Así es como funciona la biblioteca de criptas UNIX , y los sistemas operativos modernos tipo UNIX han ampliado esta biblioteca con nuevos algoritmos hash.
Sé a ciencia cierta que se agregaron soporte para SHA-256 y SHA-512 en versiones más recientes de GNU crypt.
fuente
Para ser más precisos, un ataque de diccionario , es decir, un ataque en el que se prueban todas las palabras de una lista exhaustiva, no se vuelve "imposible", pero se vuelve poco práctico : cada bit de sal duplica la cantidad de almacenamiento y cálculo necesarios .
Esto es diferente de los ataques de diccionario precalculados, como los ataques que involucran tablas de arco iris, donde no importa si la sal es secreta o no.
Ejemplo: con un salt de 64 bits (es decir, 8 bytes), debe verificar 2 64 combinaciones de contraseña adicionales en su ataque de diccionario. Con un diccionario que contiene 200.000 palabras tendrás que hacer
pruebas en el peor de los casos, en lugar de 200.000 pruebas sin sal.
Un beneficio adicional de usar salt es que un atacante no puede precalcular los hashes de contraseña de su diccionario. Simplemente tomaría demasiado tiempo y / o espacio.
Actualizar
Su actualización asume que un atacante ya conoce la sal (o la ha robado). Esta es, por supuesto, una situación diferente. Aún así, el atacante no puede usar una tabla de arco iris precalculada. Lo que importa mucho aquí es la velocidad de la función hash. Para que un ataque no sea práctico, la función hash debe ser lenta. MD5 o SHA no son buenos candidatos aquí porque están diseñados para ser rápidos, los mejores candidatos para algoritmos hash son Blowfish o algunas variaciones de este.
Actualización 2
Una buena lectura sobre el tema de la seguridad de los hashes de contraseña en general (va mucho más allá de la pregunta original pero sigue siendo interesante):
Corolario del artículo: Use hash salados creados con bcrypt (basado en Blowfish) o Eksblowfish que le permite usar un tiempo de configuración configurable para hacer que el hash sea lento.
fuente
Un diccionario es una estructura donde los valores se indexan por claves. En el caso de un ataque de diccionario precalculado, cada clave es un hash y el valor correspondiente es una contraseña que da como resultado el hash. Con un diccionario precalculado en la mano, un atacante puede buscar "instantáneamente" una contraseña que producirá el hash necesario para iniciar sesión.
Con la sal, el espacio necesario para almacenar el diccionario crece rápidamente ... tan rápidamente que tratar de precalcular un diccionario de contraseñas pronto se vuelve inútil.
Las mejores sales se eligen al azar de un generador criptográfico de números aleatorios. Ocho bytes es un tamaño práctico y más de 16 bytes no sirve para nada.
Salt hace mucho más que "hacer más irritante el trabajo de un atacante". Elimina toda una clase de ataque: el uso de diccionarios precalculados.
Otro elemento es necesario para asegurar completamente las contraseñas, y es el "fortalecimiento de claves". Una ronda de SHA-1 no es lo suficientemente buena: un algoritmo de hash de contraseña seguro debería ser muy lento computacionalmente.
Mucha gente usa PBKDF2, una función de derivación de claves, que retroalimenta los resultados a la función hash miles de veces. El algoritmo "bcrypt" es similar, utilizando una derivación de clave iterativa que es lenta.
Cuando la operación de hash es muy lenta, una tabla precalculada se vuelve cada vez más deseable para un atacante. Pero la sal adecuada derrota ese enfoque.
Comentarios
A continuación se muestran los comentarios que hice sobre la pregunta.
Sin sal, un atacante no usaría el método demostrado en la "Actualización 2". Simplemente haría una búsqueda en una tabla precalculada y obtendría la contraseña en tiempo O (1) u O (log n) (siendo n el número de contraseñas candidatas). Salt es lo que lo impide y lo obliga a utilizar el enfoque O (n) que se muestra en la "Actualización 2".
Una vez reducido a un ataque O (n), tenemos que considerar cuánto tiempo toma cada intento. El fortalecimiento de claves puede hacer que cada intento en el ciclo tome un segundo completo, lo que significa que el tiempo necesario para probar 10k contraseñas en 10k usuarios se extenderá de 3 días a 3 años ... y con solo 10k contraseñas, es probable que no descifre cero contraseñas en ese tiempo.
Debe considerar que un atacante va a utilizar las herramientas más rápidas que pueda, no PHP, por lo que miles de iteraciones, en lugar de 100, serían un buen parámetro para el fortalecimiento de claves. Debería llevar una gran fracción de segundo calcular el hash de una sola contraseña.
El fortalecimiento de claves es parte de los algoritmos estándar de derivación de claves PBKDF1 y PBKDF2, de PKCS # 5, que son excelentes algoritmos de ofuscación de contraseñas (la "clave derivada" es el "hash").
Muchos usuarios de StackOverflow se refieren a este artículo porque fue una respuesta a la publicación de Jeff Atwood sobre los peligros de las tablas de arco iris. No es mi artículo favorito, pero trata estos conceptos con más detalle.
Por supuesto, asume que el atacante lo tiene todo: sal, hash, nombre de usuario. Suponga que el atacante es un empleado corrupto de la empresa de alojamiento que arrojó la tabla de usuarios en su sitio de fans myprettypony.com. Está intentando recuperar estas contraseñas porque se dará la vuelta y verá si sus fans de pony usaron la misma contraseña en sus cuentas de citibank.com.
Con un esquema de contraseñas bien diseñado, será imposible para este tipo recuperar las contraseñas.
fuente
El objetivo de la salazón es evitar la amortización del esfuerzo del atacante.
Sin sal, una única tabla de entradas de contraseña hash precalculadas (por ejemplo, MD5 de todas las cadenas alfanuméricas de 5 caracteres, fáciles de encontrar en línea) se puede utilizar en cada usuario en todas las bases de datos del mundo.
Con una sal específica del sitio, el atacante tiene que calcular la tabla él mismo y luego puede usarla en todos los usuarios del sitio.
Con una sal por usuario, el atacante tiene que realizar este esfuerzo para cada usuario por separado.
Por supuesto, esto no hace mucho para proteger contraseñas realmente débiles directamente de un diccionario, pero protege contraseñas razonablemente fuertes contra esta amortización.
fuente
Además, un punto importante más, el uso de una sal específica de USUARIO evita la detección de dos usuarios con la MISMA contraseña: sus hashes coincidirían. Por eso muchas veces el hash es hash (salt + usuario + contraseña)
Si intenta mantener el hash en secreto, el atacante tampoco podrá verificar los hash.
Editar: acabo de notar que el punto principal se hizo en un comentario anterior.
fuente
Las sales se implementan para prevenir ataques de mesa arcoíris. Una tabla de arco iris es una lista de hashes precalculados, lo que hace que traducir un hash a su frase sea mucho más simple. Debe comprender que la salazón no es efectiva como una prevención moderna para descifrar una contraseña a menos que tengamos un algoritmo hash moderno.
Entonces, digamos que estamos trabajando con SHA1, aprovechando los exploits recientes descubiertos con este algoritmo, y digamos que tenemos una computadora funcionando a 1,000,000 de hashes / segundo, se necesitarían 5.3 millones de millones de años para encontrar una colisión , así que sí php puede trabajar 300 por segundo, gran woop, realmente no importa. La razón por la que saltamos es porque si alguien se molestara en generar todas las frases comunes del diccionario (2 ^ 160 personas, bienvenidos a las hazañas de la era 2007).
Así que aquí hay una base de datos real, con 2 usuarios que uso para fines de prueba y administración.
De hecho, el esquema de salazón es su sha1 (tiempo de registro + nombre de usuario). Adelante, dime mi contraseña, estas son contraseñas reales en producción. Incluso puede sentarse allí y hacer una lista de palabras en php. Enloquecer.
No estoy loco, solo sé que esto es seguro. Por diversión, la contraseña de prueba es
test
.sha1(sha1(1281546174.065087 + test) + test) = 5872548f2abfef8cb729cac14bc979462798d023
Debería generar una tabla de arco iris completa con perpendicular solo
27662aee8eee1cb5ab4917b09bdba31d091ab732
para este usuario. Eso significa que puedo permitir que mis contraseñas no se vean comprometidas por una sola tabla de arco iris, el pirata informático necesita generar una tabla de arco iris completa para 27662aee8eee1cb5ab4917b09bdba31d091ab732 para la prueba, y nuevamente f3f7735311217529f2e020468004a2aa5b3dee7f para briang. Piense en los 5,3 millones de millones de millones de años para todos los valores hash. Piense en el tamaño de almacenar solo los 2 ^ 80 hashes (eso es más de 20 yottabytes ), no va a suceder.No confunda la salazón como un medio para hacer que un hash sea algo que nunca podrá decodificar, es un medio para evitar que una tabla de arco iris traduzca todas sus contraseñas de usuario. Es imposible a este nivel de tecnología.
fuente
La idea detrás del ataque de diccionario es que tomas un hash y encuentras la contraseña, a partir de la cual se calculó este hash, sin cálculo de hash. Ahora haga lo mismo con la contraseña salada, no puede.
No usar un salt hace que la búsqueda de contraseñas sea tan fácil como buscar en la base de datos. Agregar una sal hace que el atacante realice un cálculo hash de todas las contraseñas posibles (incluso para adjuntar un diccionario, esto aumenta significativamente el tiempo de ataque).
fuente
En términos más simples: sin sal, cada contraseña candidata solo necesita ser hash una vez para compararla con cada usuario, en cualquier lugar del "universo conocido" (colección de bases de datos comprometidas), cuya contraseña se hash mediante el mismo algoritmo. Con la salazón, si el número de posibles valores de sal excede sustancialmente el número de usuarios en el "universo conocido", cada contraseña candidata debe tener un hash por separado para cada usuario con el que se probará.
fuente
En pocas palabras, la salazón no evita el ataque de un hash (fuerza bruta o diccionario), solo lo hace más difícil; el atacante necesitará encontrar el algoritmo de salazón (que si se implementa correctamente hará uso de más iteraciones) o fuerza bruta el algoritmo, que a menos que sea muy simple, es casi imposible. La salazón también descarta casi por completo la opción de búsquedas de tablas de arco iris ...
fuente
Salt hace que los ataques de tablas de Rainbow sean mucho más difíciles, ya que hace que sea mucho más difícil descifrar un hash de contraseña único. Imagina que tienes una contraseña horrible de solo el número 1. Un ataque de tabla de arco iris rompería esto de inmediato.
Ahora imagine que cada contraseña en la base de datos tiene un valor aleatorio largo de muchos caracteres aleatorios. Ahora su pésima contraseña de "1" se almacena en la base de datos como un hash de 1 más un montón de caracteres aleatorios (la sal), por lo que en este ejemplo la tabla del arco iris debe tener el hash de algo como: 1.
Entonces, asumiendo que su sal es algo seguro y aleatorio, digamos ()% ISLDGHASKLU ( % #% #, la tabla de arco iris del hacker debería tener una entrada para 1 * ()% ISLDGHASKLU (*% #% #. Ahora usando una tabla de arco iris incluso esta simple contraseña ya no es práctica.
fuente