¿Alguien no almacena sales?

90

Hablamos sobre el hashing y la salazón de contraseñas en clase hoy. Nuestro profesor tenía un entendimiento muy diferente del caso de uso de las sales del mío y dijo que es posible que no almacene la sal en absoluto y que solo compruebe cada intento de inicio de sesión con todas las sales posibles y que autorice si coincide.

Realmente no veo ningún punto en esto ya que ahora mi servicio es mucho más vulnerable a los ataques de fuerza bruta (enviar una contraseña, el servidor verifica muchos), pero creo que es un poco más seguro que los ataques de diccionario puro contra la contraseña hash.

Entonces, ¿hay algún caso de uso donde la gente realmente haga esto?

    
pregunta jazzpi 15.07.2016 - 11:33
fuente

9 respuestas

178

No almacenar la sal es un mal consejo.

El propósito principal de un salt es que cada contraseña de usuario tenga que ser atacada individualmente.

Si no almacena la sal, entonces, como dijo, debe probar cada combinación de sal para validar la contraseña. Si necesita verificar cada combinación de sal, esto significa que la sal no puede ser demasiado larga (mencionó 12 bits en un comentario). Si la sal no es larga, significa que la sal se repetirá para muchos usuarios. Si se repite para muchos usuarios, significa que el atacante podrá atacar a muchos usuarios al mismo tiempo, lo que ahorrará tiempo al atacante.

Al hacerlo, casi derrotas completamente el propósito de usar una sal.

    
respondido por el Gudradain 15.07.2016 - 14:29
fuente
125

Una sal 'secreta' se conoce como pepper .

De Wikipedia:

  

Se puede agregar un pimiento a una contraseña además de un valor de sal. Una pimienta desempeña un papel similar al de una sal, sin embargo, mientras que una sal se almacena comúnmente junto con el valor que se está picando, para que algo se defina como una pimienta, debe cumplir uno de los siguientes criterios que lo definen como un "secreto" más oculto. que el valor de sal:

     
  • El pimiento se mantiene separado del valor que se va a picar
  •   
  • La pimienta se genera aleatoriamente para cada valor que se va a hash (dentro de un conjunto limitado de valores), y nunca se almacena. Cuando los datos se comparan con un valor de hash para una coincidencia, esto se realiza mediante la iteración a través del conjunto de valores válidos para el pimiento, y cada uno a su vez se agrega a los datos que se van a probar (generalmente con el sufijo de los datos), antes de que la función de cifrado criptográfico se ejecute en el valor combinado.
  •   

La ventaja de un pimiento es que un atacante ahora debe calcular el número de posibles permutaciones de un valor de pimiento para cada entrada de texto sin formato.

Los pimientos aumentan la duración del ataque para un hash específico, mientras que una sal no lo hace.

Recuerde que una sal es una mitigación efectiva para los hashes precomputados y hace que un atacante pase mucho tiempo atacando un conjunto de hashes. Sin embargo, si solo preocupa un hash, y no se deben usar hashes precomputados, una sal no aumenta la duración del ataque. A Pepper, sin embargo, obliga al atacante a utilizar varias conjeturas para cada contraseña de texto sin formato, incluso para un solo hash.

De esta manera, un pimiento es similar al estiramiento de la tecla .

La mayoría de las implementaciones prefieren el estiramiento clave a los pimientos.

Mi observación personal es que la mayoría de las implementaciones prefieren el estiramiento clave a los pimientos. No tengo una referencia para esto, por lo que los lectores pueden proporcionar referencias de apoyo o discrepantes en los comentarios. Las personas tienden a preferir el estiramiento clave porque tiene un costo de rendimiento y seguridad conocidos y esperados. Para calcular la ronda N de un hash, se deben calcular N hashes. Sin embargo, con un pimiento, solo se puede calcular el número de intentos esperado . Considere un pimiento de 1 byte, el atacante necesitaría 256 intentos para adivinar todas las combinaciones posibles, pero el valor esperado es 128, y el atacante podría (en promedio de 1/256 veces) adivinar el valor en el primer intento.

Peppers y Key Stretching pueden funcionar unos contra otros.

El estiramiento de teclas es efectivo porque puede establecer el número de rondas en función de la cantidad de tiempo que desea que se realice el cálculo de un hash. Digamos que desea que una sola comprobación demore medio segundo en el hardware actual, solo aumenta las rondas hasta que eso ocurra.

Con un pimiento, ya que necesita adivinar varios valores para cada contraseña, el tamaño de un pimiento debe relacionarse inversamente con el número de rondas para mantener constante el tiempo de cálculo.

Consejos prácticos sobre implementaciones hash

El mejor consejo para las implementaciones de contraseña / hash es utilizar metodologías conocidas y bibliotecas probadas. Debería utilizar bcrypt o pbkdf2 con una sal única y muchas rondas. Estos algoritmos tienden a tener implementaciones bien conocidas en muchos lenguajes y marcos. Si encuentra una biblioteca bien conocida y probada que incluye un pimiento, además de sales y estiramientos clave, puede valer la pena usarlo, pero el beneficio adicional a menudo supera los costos de rendimiento.

    
respondido por el amccormack 15.07.2016 - 16:14
fuente
21

Fondo: Debería usar un Hash de contraseña lenta. (es decir, bcrypt) Por "lento" quiero decir computacionalmente costoso, tomando más de 100 ms (en su hardware) con protección DoS * para probar una sola contraseña. Esto es para aumentar la potencia de procesamiento necesaria (en el hardware del atacante) para encontrar la contraseña por fuerza bruta, en caso de que el hash sea robado.

Por usuario la sal única es altamente recomendada. (en el caso de bcrypt se genera automáticamente) Salt debe ser altamente único (es decir, largo y aleatorio), pero no secreto . Usar sal única significa que un atacante tendría que ejecutar un trabajo de fuerza bruta separado para cada usuario .

Si no hubiera 'sal', el atacante podría usar instantáneamente una Rainbow Table y sin fuerza bruta.

Si solo usas 'sal compartida', entonces un atacante podría descifrar las contraseñas de todos los usuarios con un single brute force Job. (no es tan rápido como una mesa de arco iris, pero es mucho más fácil que un Job de fuerza bruta separado para cada uno)

Respuesta: Si no "guardaras" la sal ("la fuerza bruta del hash en el tiempo de ejecución", como sugiere tu profesor)

  • las posibles sales tendrían que ser muy pocas
  • el hash tendría que ser un poco más rápido

Esto anularía totalmente el propósito de Salt , paraliza gravemente el beneficio de un hash lento. Ese es un gran error de diseño por parte de su profesor. Básicamente, está lanzando su propio esquema de almacenamiento de contraseñas , donde debería estar utilizando el algoritmo bcrypt (o scrypt o PBKDF2 ) ya que fue diseñado para ser utilizado .

* Como comentó @Navin , este sería un posible vector de ataque DoS. Una solución es limitar el número de intentos por hora por IP y por nombre de usuario. También es posible que reduzcas la "lentitud" de tu hash para tomar solo 10 ms. Esto no es tan bueno como 100 ms desde una perspectiva de "hash robado", pero sigue siendo mucho mejor que "microsegundos".

    
respondido por el George Bailey 15.07.2016 - 15:37
fuente
16

Tu profesor no es correcto. El objetivo de un salt es aumentar la entropía de las contraseñas de hash para evitar cualquier tipo de ataque previo al cálculo, así como evitar que la misma contraseña de diferentes usuarios tenga el mismo valor de hash.

Ser capaz de probar todos los valores posibles de sal significa que debe tener una cantidad muy BAJA de entropía en la sal, lo que significa que es posible realizar un cálculo previo a través de tablas de arco iris.

    
respondido por el Steve Sether 15.07.2016 - 15:37
fuente
3

Podrías usar la sal de esta manera. Sería una especie de proceso de estiramiento de hachís. Por lo general, se estira un hash repitiendo el algoritmo varios miles de veces, lo que ralentiza a los atacantes y usuarios en 1000 veces, pero a los usuarios no les importa la ralentización. Usar una sal de esta manera tendría el efecto de hacer un algoritmo de estiramiento de hash al tener que repetirlo para muchos hashes desconocidos.

Sin embargo, este es un enfoque extremadamente inusual. Las formas tradicionales de hacer salado hacen que las sales se hagan mucho mejor (para que nadie pueda calcular una tabla de contraseñas). Las formas tradicionales de hacer el estiramiento de hash hacen lo que se supone que el estiramiento de hash hace mucho mejor (para que los atacantes tarden más tiempo en calcular las contraseñas). Usar una sal de esta manera es como mezclarlos a los dos juntos. El resultado es una especie de trabajo, pero los enfoques más limpios hacen ambas soluciones lejos mejor que el feo desajuste de las técnicas.

    
respondido por el Cort Ammon 16.07.2016 - 00:07
fuente
2

En lugar de pensar en sal en términos de fuerza bruta, me gusta pensar en decir que hace que sea imposible decir nada acerca de una contraseña, incluida su relación con otras contraseñas, al mirarla. Si el sistema no utiliza sal, observar las contraseñas de hash de dos usuarios indicaría si sus contraseñas reales coincidían. Si un sistema utiliza solo el nombre de usuario pero no es nada aleatorio, específico del tiempo o específico del sistema, si observa las contraseñas con hash de un usuario en dos máquinas que utilizan el mismo método, se indicaría si las contraseñas de los usuarios coincidían. Si el sistema utiliza el ID del sistema y el nombre de usuario, pero no es aleatorio ni específico del tiempo, entonces alguien con acceso a dos hashes de contraseña diferentes por el mismo usuario podría indicar si las contraseñas asociadas coinciden.

El efecto de la sal al azar es hacer que no haya dos hashes que usen la misma contraseña, incluso si involucran al mismo usuario en el mismo sistema. Si bien uno podría lograr un efecto similar sin almacenar las sales si los intentos de inicio de sesión fuesen forzados brutalmente, tal enfoque limitaría la longitud práctica de la sal que se podría usar y, por lo tanto, aumentaría la probabilidad de que las contraseñas utilizadas en dos contextos tuvieran la la misma sal y por lo tanto ser reconocible como coincidencia.

    
respondido por el supercat 15.07.2016 - 17:52
fuente
1

¿Qué te da la salazón? Los atacantes tienen bases de datos calculadas previamente de valores hash para contraseñas, comunes y no. Si capturan su base de datos y tienen el hash de las contraseñas para cada usuario, es sencillo verificar sus hashes con esos valores sin un salt.

Con una sal aleatoria que se almacena junto con la contraseña, este método rápido increíblemente ya no es posible. Pero si el atacante tiene la sal y el hash, todavía es posible usar ataques de diccionario para contraseñas débiles o forzoso para las cortas. Todo lo que el atacante debe hacer es usar el salt y probar diferentes contraseñas usando un diccionario o un ataque de fuerza bruta.

Ahora digamos que cuando se cambia la contraseña, la hash con un valor aleatorio de 12 bits que no se almacena junto con la sal que es. Luego, cada vez que verifique la contraseña, deberá probar todos los valores de 4096. En mi computadora, esto toma aproximadamente 3.5 ms, por lo que se pueden verificar 284 contraseñas cada segundo. Un poco más de uso de la CPU en el servidor cuando alguien inicia sesión, pero para alguien que intenta ataques de fuerza bruta o de diccionario, acaba de hacer su trabajo mucho más difícil, incluso si tienen el hash y la sal.

    
respondido por el Jason Goemaat 18.07.2016 - 04:24
fuente
0

Parece haber algún mérito en la idea de no almacenar un número controlado de bits de la sal, que se configura de forma independiente y es independiente del tamaño de la sal.

Supongamos que tenemos sales de 32 bits. Podríamos optar por almacenar solo 22 bits y la fuerza bruta a través de los 10 restantes cuando nos autentiquemos. El efecto de esto es como si se agregaran más rondas a la función de hashing. No tanto como para que la autenticación legítima se vea afectada, pero sí lo suficiente para aumentar la dificultad del craqueo de fuerza bruta.

El año que viene, las máquinas se vuelven más rápidas. Así que barremos la base de datos de contraseñas y eliminamos un poco de cada sal: ahora almacenamos solo 21 bits, y tenemos que aplicar fuerza bruta a través de 11.

Es como si hubiéramos duplicado la fuerza de hash, pero sin la interrupción de reemplazar el algoritmo y lograr que los usuarios vuelvan a hash sus contraseñas (lo que queda en la política de caducidad de contraseñas).

Este enfoque de "descarte progresivo de sal" podría extender la vida útil de las funciones de hash.

Sin embargo, este tipo de enfoques ralentizan la autenticación legítima y el ataque de fuerza bruta por un factor igual, por lo que, en el mejor de los casos, proporcionan una capa de seguridad menor. Nuestro enfoque debe ubicarse en mejoras que agreguen solo una cantidad constante de tiempo adicional para el uso legítimo, mientras se multiplica la dificultad de craqueo. Por supuesto, una mejora que tiene esta propiedad es aumentar la cantidad de entropía en la frase de contraseña! Cada bit de entropía agregado a la contraseña agrega un costo constante a los usuarios legítimos, pero duplica el esfuerzo de craqueo de fuerza bruta. Una contraseña de longitud N lleva O (N) a hash (y tipo), pero O (2 ** N) a fuerza bruta. Al agregar 12 bits de entropía a una contraseña, se ocultan 12 bits de sal.

    
respondido por el Kaz 16.07.2016 - 01:08
fuente
0

Fuera en la naturaleza tenemos una tabla de usuarios. Una tabla de usuarios suele ser

ID   |  username | salt | encrypted_password               | horridly_insecure_reset_key
===========================================================================
1    | user1     | foo  | 09b6d39aa22fcb8698687e1af09a3af9 | NULL
2    | user2     | bar  | 6c07c60f4b02c644ea1037575eb40005 | NULL
3    | user3     | baz  | 09b6d39aa22fcb8698687e1af09a3af9 | reset

Entonces, un método de autenticación tendrá un aspecto parecido a

def authenticate(user, password)
    u = User.find(user: user)
    return u.encrypted_password == encrypt(password + u.salt)
end

Al tener un salt por usuario, garantiza que incluso si se conoce la contraseña para user1 no se puede averiguar la contraseña para user2 o user3 sin su salt.

También te aseguras de no poder descifrar el salt al tener un conjunto de contraseñas cifradas y probar algunas contraseñas cifradas.

En esencia, de esta manera, cada ataque contra un usuario debe iniciarse desde cero.

Incluso si un atacante tiene una lista de usuarios y sales, todavía necesita hacer el cracking contra todos y cada uno de los usuarios para ver si tienen una coincidencia de contraseña. Si tuviera un grupo de sales, o un sal estático, podría saber que la contraseña del usuario1 es la contraseña y luego encontrar todas las contraseñas cifradas que coincidan. De esta manera, al menos, los retrasa un poco más.

Ahora, cuando observamos las sales, queremos reducir la reutilización de la sal. Dos sales idénticas facilitarán a los atacantes. Si dos personas comparten la misma sal y la misma contraseña, romper un usuario romperá el otro.

Digamos que solo usamos estas tres sales. Y tenemos 3000 usuarios. Eso significa que 1000 personas tienen la misma sal. Si el 1% de ellos tiene una contraseña de "contraseña", esas personas pueden ser descifradas al mismo tiempo. 10 cuentas son hackeadas a la vez. Porque conocemos las tres sales. Es un tramo muy fácil para que 30 personas sean atacadas a la vez.

Ahora si cada sal es única. Y sabemos que la contraseña del usuario1 es la contraseña, que no le sirve de nada. Aún tienes solo 1 usuario crackeado. Aún tiene que hacer "do password + salt = contraseña encriptada" para todos los otros 2999 usuarios.

Una nota muy importante.

La seguridad a través de la oscuridad no es seguridad. Eso no significa que debas publicar tu tabla de usuarios en google porque es una tontería. Pero al medir la seguridad, debes asumir que el atacante tiene todo. No puede decir: "Pero ellos no sabrán la aplicación porque no tienen el código fuente". Porque ellos podrían. No significa regalar tus sales, solo significa que no es una verdadera seguridad. Suponga que tienen el nombre de usuario y el nombre salt, y luego intente dificultarles la obtención de la contraseña.

SUPER IMPORTANTE NOTA

El código y la tabla utilizados aquí son aproximadamente 9,000 veces demasiado simples para un uso real. Las contraseñas no están encriptadas, las sales son demasiado cortas, el método es un poco simplista, en resumen, hacer algo como esto en la producción no es algo que deba considerarse seguro. Escogí estas causas simples para el punto de demostración, no porque sean seguras.

    
respondido por el coteyr 21.07.2016 - 15:54
fuente

Lea otras preguntas en las etiquetas