security - La necesidad de esconder la sal para un hash
encryption brute-force (10)
En el trabajo tenemos dos teorías competitivas para las sales. Los productos en los que trabajo utilizan algo así como un nombre de usuario o número de teléfono para saltear el hash. Esencialmente, es algo diferente para cada usuario, pero está disponible para nosotros. El otro producto genera al azar una sal para cada usuario y cambia cada vez que el usuario cambia la contraseña. La sal luego se cifra en la base de datos.
Mi pregunta es si el segundo enfoque es realmente necesario. Puedo entender desde una perspectiva puramente teórica que es más seguro que el primer enfoque, pero qué ocurre desde un punto de vista práctico. Ahora mismo para autenticar a un usuario, el salt debe estar desencriptado y aplicado a la información de inicio de sesión.
Después de pensarlo, simplemente no veo una ganancia de seguridad real con este enfoque. Cambiar la sal de la cuenta a la cuenta, hace que sea extremadamente difícil para alguien intentar aplicar la fuerza bruta del algoritmo de hashing incluso si el atacante sabía cómo determinar rápidamente cuál era para cada cuenta. Esto se basa en la suposición de que las contraseñas son suficientemente fuertes. (Obviamente, encontrar el hash correcto para un conjunto de contraseñas donde son dos dígitos es mucho más fácil que encontrar el hash correcto de contraseñas que son 8 dígitos). ¿Soy incorrecto en mi lógica o hay algo que me falta?
EDITAR: Bien, esta es la razón por la que creo que es realmente imposible encriptar la sal. (déjame saber si estoy en el camino correcto).
Para la siguiente explicación, asumiremos que las contraseñas son siempre de 8 caracteres y la sal es 5 y todas las contraseñas están compuestas de letras minúsculas (simplemente hace que las matemáticas sean más fáciles).
Tener una sal diferente para cada entrada significa que no puedo usar la misma tabla de arco iris (en realidad podría hacerlo técnicamente si tuviera una de tamaño suficiente, pero ignorémosla por el momento). Esta es la verdadera clave para la sal de lo que yo entiendo, porque para descifrar cada cuenta tengo que reinventar la rueda, por así decirlo, para cada una. Ahora, si sé cómo aplicar la sal correcta a una contraseña para generar el hash, lo haría porque una sal realmente solo aumenta la longitud / complejidad de la frase hash. Así que estaría reduciendo el número de combinaciones posibles que necesitaría generar para "saber" Tengo la contraseña + sal de 13 ^ 26 a 8 ^ 26 porque sé lo que es la sal. Ahora eso lo hace más fácil, pero todavía muy difícil.
Entonces, encriptar la sal. Si sé que la sal está encriptada, no intentaré descifrarla (suponiendo que sé que tiene un nivel suficiente de encriptación) primero. Yo lo ignoraría. En lugar de tratar de descifrar cómo descifrarlo, volviendo al ejemplo anterior, generaría una tabla de arco iris más grande que contiene todas las claves para el 13 ^ 26. Sin saber que la sal definitivamente me retrasaría, pero no creo que agregue la tarea monumental de tratar de descifrar la encriptación de sal primero. Es por eso que no creo que valga la pena. ¿Pensamientos?
Aquí hay un enlace que describe cuánto tiempo pasarán las contraseñas bajo un ataque de fuerza bruta: http://www.lockdown.co.uk/?pg=combi
... algo así como un nombre de usuario o número de teléfono para saltear el hash. ...
Mi pregunta es si el segundo enfoque es realmente necesario. Puedo entender desde una perspectiva puramente teórica que es más seguro que el primer enfoque, pero ¿qué ocurre desde un punto de vista práctico?
Desde un punto de vista práctico, una sal es un detalle de implementación. Si alguna vez cambia la forma en que se recopila o se mantiene la información del usuario, y en ocasiones cambian los nombres de usuario y los números de teléfono, para usar sus ejemplos exactos, entonces puede haber comprometido su seguridad. ¿Desea que un cambio tan externo tenga preocupaciones de seguridad mucho más profundas?
¿La suspensión del requisito de que cada cuenta tenga un número de teléfono necesita una revisión de seguridad completa para garantizar que no haya abierto esas cuentas a un compromiso de seguridad?
Aquí hay un ejemplo simple que muestra por qué es malo tener la misma sal para cada hash
Considera la siguiente tabla
UserId UserName, Password
1 Fred Hash1 = Sha(Salt1+Password1)
2 Ted Hash2 = Sha(Salt2+Password2)
Caso 1 cuando sal 1 es lo mismo que salt2 Si Hash2 se reemplaza con Hash1, el usuario 2 podría iniciar sesión con la contraseña del usuario 1
Caso 2 cuando sal 1 no es la misma sal2 Si Hash2 se reemplaza con Hash1, el usuario 2 no puede iniciar sesión con la contraseña de los usuarios 1.
El segundo enfoque es solo un poco más seguro. Las sales protegen a los usuarios de los ataques de diccionario y los ataques de tabla de arco iris. Hacen más difícil para un atacante ambicioso comprometer todo su sistema, pero aún son vulnerables a los ataques que se centran en un usuario de su sistema. Si usa información públicamente disponible, como un número de teléfono, y el atacante se da cuenta de esto , entonces los ha guardado un paso en su ataque. Por supuesto, la pregunta es discutible si el atacante obtiene toda su base de datos, sales y todo.
EDITAR: Después de volver a leer esta respuesta y algunos de los comentarios, se me ocurre que parte de la confusión puede deberse al hecho de que solo estoy comparando los dos casos muy específicos presentados en la pregunta: sal al azar vs. sal no aleatoria. La cuestión de usar un número de teléfono como sal es discutible si el atacante obtiene toda su base de datos, no la cuestión de usar una sal en absoluto.
En realidad, depende del tipo de ataque que intente proteger sus datos.
El propósito de una sal única para cada contraseña es evitar un ataque de diccionario contra la base de datos de contraseñas completa.
Encriptar la sal única para cada contraseña haría más difícil descifrar una contraseña individual, sí, pero debe sopesar si realmente hay un gran beneficio. Si el atacante, por fuerza bruta, encuentra que esta cadena:
Marianne2ae85fb5d
hash a un hash almacenado en el DB, ¿es realmente tan difícil de entender qué parte es el pase y qué parte es la sal?
Hay dos técnicas, con diferentes objetivos:
La "sal" se usa para hacer que dos contraseñas que de otro modo sean iguales se encripten de manera diferente. De esta forma, un intruso no puede usar eficientemente un ataque de diccionario contra una lista completa de contraseñas encriptadas.
El "secreto" (compartido) se agrega antes de enviar un mensaje, para que un intruso no pueda crear sus propios mensajes y hacerlos aceptar.
La respuesta aquí es preguntarte a ti mismo de qué estás tratando de proteger realmente. Si alguien tiene acceso a su base de datos, entonces tienen acceso a las sales encriptadas, y probablemente también tengan acceso a su código. Con todo lo que podrían descifrar las sales encriptadas? Si es así, la encriptación es bastante inútil de todos modos. La sal realmente está ahí para hacerlo, por lo que no es posible formar una tabla arcoiris para descifrar toda la base de datos de contraseñas de una vez si se rompe. Desde ese punto de vista, siempre que cada sal sea única no hay diferencia, se requeriría un ataque de fuerza bruta con sus sales o las sales encriptadas para cada contraseña individualmente.
Mi comprensión de "sal" es que hace que el agrietamiento sea más difícil, pero no trata de ocultar los datos adicionales. Si está tratando de obtener más seguridad haciendo que la sal sea "secreta", entonces realmente solo quiere más bits en sus claves de cifrado.
Ocultar una sal es innecesario.
Se debe usar una sal diferente para cada hash. En la práctica, esto es fácil de lograr al obtener 8 o más bytes del generador de números aleatorios de calidad criptográfica.
De una respuesta anterior mía :
La sal ayuda a frustrar los ataques de diccionario precalculados.
Supongamos que un atacante tiene una lista de contraseñas probables. Él puede hacer hash cada uno y compararlo con el hash de la contraseña de su víctima, y ver si coincide. Si la lista es grande, esto podría llevar mucho tiempo. Él no quiere pasar tanto tiempo en su próximo objetivo, por lo que registra el resultado en un "diccionario" donde un hash apunta a su entrada correspondiente. Si la lista de contraseñas es muy, muy larga, puede usar técnicas como una Tabla Arcoíris para ahorrar espacio.
Sin embargo, supongamos que su próximo objetivo sacó su contraseña. Incluso si el atacante sabe cuál es la sal, su tabla precalculada no tiene ningún valor: la sal cambia el hash resultante de cada contraseña. Él tiene que volver a codificar todas las contraseñas en su lista, fijando la sal del objetivo a la entrada. Cada sal diferente requiere un diccionario diferente, y si se usan suficientes sales, el atacante no tendrá espacio para almacenar diccionarios para todos ellos. El espacio de negociación para ahorrar tiempo ya no es una opción; el atacante debe recurrir a hash cada contraseña en su lista para cada objetivo que quiere atacar.
Por lo tanto, no es necesario mantener la sal en secreto. Asegurar que el atacante no tenga un diccionario precalculado correspondiente a esa sal en particular es suficiente.
Después de pensar en esto un poco más, me he dado cuenta de que engañarte a ti mismo al pensar que la sal puede ocultarse es peligroso. Es mucho mejor asumir que la sal no se puede ocultar, y diseñar el sistema para que sea seguro a pesar de eso. Proporciono una explicación más detallada en otra respuesta.
Tiendo a esconder la sal. Uso 10 bits de sal al anteponer un número aleatorio de 1 a 1024 al comienzo de la contraseña antes de mezclarlo. Al comparar la contraseña que el usuario ingresó con el hash, hago un bucle de 1 a 1024 e intento con cada valor posible de sal hasta encontrar la coincidencia. Esto lleva menos de 1/10 de segundo. Tengo la idea de hacerlo de esta manera desde PHP password_hash y password_verify . En mi ejemplo, el "costo" es 10 por 10 bits de sal. O por lo que dijo otro usuario, la "sal" oculta se llama "pimienta". La sal no está encriptada en la base de datos. Es brutalmente forzado a salir. Haría que la tabla del arco iris fuera necesaria para invertir el hash 1000 veces más grande. Uso sha256 porque es rápido, pero aún se considera seguro.
Una sal escondida ya no es sal. Es pimienta. Tiene su uso. Es diferente de la sal.
Pepper es una clave secreta que se agrega a la contraseña + sal que convierte el hash en un HMAC (Código de autenticación de mensajes basado en hash). Un pirata informático con acceso a la salida hash y la sal pueden teóricamente calcular la fuerza bruta de una entrada que generará el hash (y, por lo tanto, pasar la validación en el cuadro de texto de la contraseña). Al agregar pimienta, aumenta el espacio del problema de una manera criptográficamente aleatoria, lo que hace que el problema no se pueda solucionar sin un hardware serio.
Para obtener más información sobre pimienta, mira here .
Ver también hmac .