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.