password_hash password_bcrypt password online ejemplo desencriptar php security hash passwords salt

php - password_bcrypt - ¿Es el tiempo() una buena sal?



password verify php (9)

Estoy viendo un código que no he escrito yo mismo. El código intenta codificar una contraseña con SHA512 y usa solo time() como sal. ¿Es el time() una sal demasiado simple para esto o es seguro este código?

Gracias por las respuestas y comentarios. Lo resumiré aquí para los nuevos lectores:

  • la sal debe ser diferente para cada usuario, por lo que si 2 usuarios se registran al mismo tiempo, sus sales no serán únicas. Este es un problema, pero no uno grande.
  • pero la sal no debe estar de ninguna manera relacionada con el usuario, por lo que el tiempo () no es una buena sal.
  • " Use una sal de alta entropía aleatoria, distribuida uniformemente. " - Eso es un bocado, entonces, ¿qué código podría generar una sal de random, evenly distributed, high entropy ?

Ok, entonces ¿qué tal si reemplazo time () con una cadena aleatoria de 32 caracteres de largo? La cadena aleatoria podría generarse a partir de un bucle 32 veces sobre un conjunto de caracteres alfabéticos. Suena bien?


Respuesta corta:

No, el time() no es una buena sal.

Respuesta larga:

copiado de mi respuesta a Salt Generation y software de código abierto

¿Qué es una sal?

Una sal es un conjunto aleatorio de bytes de una longitud fija que se agrega a la entrada de un algoritmo hash.


¿Por qué es útil salar (o siembra) un hash?

Agregar una sal aleatoria a un hash garantiza que la misma contraseña produzca muchos hashes diferentes. La sal generalmente se almacena en la base de datos, junto con el resultado de la función hash. Salar un hash es bueno por una serie de razones:

  1. La salazón aumenta en gran medida la dificultad / costo de los ataques precomputados (incluidas las tablas de arcoíris )
  2. Salting se asegura de que la misma contraseña no dé como resultado el mismo hash. Esto asegura que no puede determinar si dos usuarios tienen la misma contraseña. Y, lo que es más importante , no puede determinar si la misma persona usa la misma contraseña en diferentes sistemas.
  3. La salazón aumenta la complejidad de las contraseñas, lo que disminuye en gran medida la efectividad de los ataques de Dictionary- y de cumpleaños . (Esto solo es cierto si la sal se almacena separada del hash).
  4. La salazón adecuada aumenta en gran medida la necesidad de almacenamiento de ataques de precomputación, hasta el punto en que ya no son prácticos. (Las contraseñas alfanuméricas sensibles a las mayúsculas y minúsculas de 8 caracteres con sal de 16 bits, con hashes a un valor de 128 bits, ocuparían poco menos de 200 exabytes sin reducción del arco iris).


No hay necesidad de que la sal sea secreta.

Una sal no es una clave secreta, en cambio una sal ''funciona'' al hacer que la función hash sea específica para cada instancia. Con hash salado, no hay una función de hash, sino una para cada valor de sal posible. Esto evita que el atacante ataque contraseñas N hashed por menos de N veces el costo de atacar una contraseña. Este es el punto de la sal.
Una "sal secreta" no es una sal, se llama "clave", y significa que ya no está computando un hash, sino un Código de Autenticación de Mensaje (MAC). La computación MAC es un asunto complicado (mucho más complicado que simplemente juntar una clave y un valor en una función hash) y es un tema muy diferente.

La sal debe ser aleatoria para cada instancia en que se use. Esto asegura que un atacante tiene que atacar cada hash salado por separado.
Si confías en que tu sal (o algoritmo de salazón) es secreta, ingresas a los dominios de Seguridad a través de la oscuridad (no funcionará). Lo más probable es que no obtenga seguridad adicional del secreto salino; solo tienes la cálida sensación confusa de seguridad. Entonces, en lugar de hacer tu sistema más seguro, simplemente te distrae de la realidad.


Entonces, ¿por qué la sal tiene que ser aleatoria?

Técnicamente, la sal debe ser única . El punto de la sal es ser distinto para cada contraseña hash. Esto se entiende en todo el mundo . Como no existe una organización central que distribuya sales exclusivas bajo demanda, debemos confiar en la siguiente mejor opción, que es la selección aleatoria con un generador aleatorio impredecible, preferiblemente dentro de un espacio saliente lo suficientemente grande como para hacer que las colisiones sean improbables (dos instancias usando el mismo valor de sal).

Es tentador tratar de derivar una sal de algunos datos que es "presumiblemente único", como la identificación del usuario, pero tales esquemas a menudo fallan debido a algunos detalles desagradables:

  1. Si utiliza, por ejemplo, la identificación de usuario , algunos tipos malos que atacan a distintos sistemas pueden agrupar sus recursos y crear tablas precalculadas para las ID de usuario de 1 a 50. Una identificación de usuario es única en todo el sistema, pero no en todo el mundo .

  2. Lo mismo se aplica al nombre de usuario : hay una "raíz" por sistema Unix, pero hay muchas raíces en el mundo. Una mesa de arcoiris para "raíz" valdría la pena, ya que podría aplicarse a millones de sistemas. Peor aún, también hay muchos "bob", y muchos no tienen la capacitación de administrador del sistema: sus contraseñas podrían ser bastante débiles.

  3. La unicidad es también temporal. A veces, los usuarios cambian su contraseña. Para cada nueva contraseña , se debe seleccionar una nueva sal . De lo contrario, un atacante obtuvo el hash de la contraseña anterior y el hash de la nueva podría intentar atacar a ambos simultáneamente.

Usar una sal aleatoria obtenida de un PRNG criptográficamente seguro e impredecible puede ser algún tipo de exageración, pero al menos puede protegerte contra todos esos peligros. No se trata de evitar que el atacante sepa qué es una sal individual , se trata de no darles el objetivo grande y gordo que se utilizará en un número considerable de objetivos potenciales. La selección aleatoria hace que los objetivos sean lo más delgados posible.


En conclusión:

Use una sal de alta entropía aleatoria, distribuida uniformemente. Use una sal nueva cada vez que cree una nueva contraseña o cambie una contraseña. Almacene la sal junto con la contraseña hash. Favor de grandes sales (al menos 10 bytes, preferiblemente 16 o más).

Una sal no convierte una contraseña incorrecta en una buena contraseña. Solo se asegura de que el atacante pague al menos el precio de ataque del diccionario por cada contraseña incorrecta que rompa.


Fuentes útiles:
.com: sal no aleatoria para hashes de contraseñas
Bruce Schneier: Criptografía práctica (libro)
Matasano Security: suficiente con las tablas Rainbow
usenix.org: la cripta de Unix usó sal desde 1976
owasp.org : ¿Por qué agregar sal?
openwall.com : Salts

Renuncia:
No soy un experto en seguridad. (Aunque esta respuesta fue revisada por Thomas Pornin )
Si alguno de los profesionales de seguridad encuentra algo incorrecto, por favor comente o edite esta respuesta wiki.


En cuanto a lo que parece ser una buena fuente para su sal al azar
Lea también: ¿Cuál es la semilla más segura para la generación de números aleatorios?
En ausencia de generadores aleatorios dedicados, basados ​​en hardware, la mejor forma de obtener datos aleatorios es preguntarle al sistema operativo (en Linux, esto se llama /dev/random o /dev/urandom [ambos tienen ventajas y problemas, elija su poison]; en Windows, llame a CryptGenRandom() )

Si por alguna razón no tiene acceso a las fuentes de azar mencionadas anteriormente, en PHP podría usar la siguiente función:
De la fuente de phpass v0.3

<?php /** * Generate pseudo random bits * @copyright: public domain * @link http://www.openwall.com/phpass/ * @param int $length number of bits to generate * @return string A string with the hexadecimal number * @note don''t try to improve this, you will likely just ruin it */ function random_bits($entropy) { $entropy /= 8; $state = uniqid(); $str = ''''; for ($i = 0; $i < $entropy; $i += 16) { $state = md5(microtime().$state); $str .= md5($state, true); } $str = unpack(''H*'', substr($str, 0, $entropy)); // for some weird reason, on some machines 32 bits binary data comes out as 65! hex characters!? // so, added the substr return substr(str_pad($str[1], $entropy*2, ''0''), 0, $entropy*2); } ?>


No, el tiempo () no es una buena sal

Lo mejor es no reinventar la rueda cuando se trata de autenticación, pero para responder a su pregunta, no . El problema con el tiempo ():

  • Es predecible y se correlaciona con cosas potencialmente detectables. Estos problemas hacen que sea más fácil hacer una comparación cruzada de diferentes resultados hash.
  • No hay muchos valores posibles. Dado que los bits de orden superior no cambian, es una sal aún más estrecha de lo que parece.
  • Usarlo repite errores previos. Si esta aplicación fuera la primera en usar time () como sal, al menos requeriría un nuevo ataque.

¡No! Nunca use la hora actual como sal. Puede usar algo como ''SecureRandom'' en Java para generar una sal aleatoria segura. Siempre use un número aleatorio impredecible como sal.
Utilizar el tiempo como sal le ayudará a eliminar colisiones solo hasta cierto punto (porque dos usuarios pueden aplicar las mismas contraseñas al mismo tiempo), pero aún así puede recuperar las contraseñas.


El nombre de usuario debe ser suficiente y tal vez la marca de tiempo de registro, pero debe almacenarlo en algún lugar de la base de datos. De todos modos, cada valor que use para saltear su hash de contraseña debe almacenarse de alguna manera, para que pueda volver a calcular el hash.

¿Salar con el nombre de usuario + una marca de tiempo es lo suficientemente seguro? Debería ser. Para craquear SHA512 Hashes normalmente se usan tablas Rainbow. Un nombre de usuario + una marca de tiempo debe ser una sal que sea lo suficientemente uniquq, por lo que no hay forma de que exista una tabla Rainbow en la red que contenga hashes precalculados con contraseñas, que se salan de esta manera.


Esta publicación puede desviarse demasiado de su pregunta original, pero espero que la encuentre útil;

La seguridad se trata de levantar barreras y obstáculos; defensa en profundidad. No existe una solución de hash verdaderamente segura, solo difíciles de romper. Es como colocar una alarma antirrobo y cerraduras en las ventanas de su casa: haga que su sitio sea menos atractivo para entrar que el de otra persona.

Sal para un algoritmo de cripta es solo una pequeña parte del problema de seguridad. Una sola sal simplemente significa que hay una cosa menos que descubrir al tratar de descifrar la contraseña para múltiples usuarios. Una sal de baja entropía (como el tiempo del servidor) lo hace un poco más difícil, y una sal de alta entropía lo hace aún más difícil. Cuál de estos usar, y si es algo de lo que debe preocuparse depende principalmente de la sensibilidad de los datos que está protegiendo, pero también de qué otras medidas de seguridad tiene implementadas. Un sitio que simplemente da un pronóstico del tiempo personalizado para una ciudad seleccionada obviamente tiene datos menos confidenciales que uno que tenga su domicilio, el apellido de soltera de su madre, su fecha de nacimiento y otra información que pueda ser utilizada con fines de identificación.

Así que aquí está el problema; una sal de alta entropía sigue siendo una mala sal si se puede obtener fácilmente.

En el mundo real, almacenar una sal en la base de datos (al azar o no) es probablemente menos seguro que usar una sal constante y enterrarlo lejos de los ojos privados en un archivo inaccesible a través del navegador web. Mientras que una sal de entropía única y alta es más difícil de adivinar, si ha permitido el inicio de sesión de raíz desde cualquier servidor en MySql y ha establecido la contraseña en ''contraseña'' ¡en realidad no importa! Constriñe lo fácil que es descifrar la base de datos en lugar de obtener un inicio de sesión válido en su servidor, lo que es posiblemente más difícil de hacer de forma discreta ya que puede poner fail2ban y una gran cantidad de observadores vector de ataque en su lugar dependiendo de su configuración.

Puede combinar los dos enfoques al almacenar la ubicación de un archivo que contiene una sal específica del usuario en la base de datos, en lugar de la sal en sí misma. Si tener que descifrar tanto el sistema de archivos como la base de datos está garantizado depende de si la sensibilidad de los datos que intenta proteger garantiza esta sobrecarga.

Otra recomendación alternativa de los expertos en seguridad es almacenar el nombre de usuario en una base de datos separada (e idealmente una tecnología diferente) a la contraseña, y una referencia entre los dos usando un UUID. Por ejemplo, use MySQL y SQLite. Esto significa que ambas bases de datos tienen que estar resquebrajadas (y también por eso, para ir a un hoyo separado por ejemplo, no debe almacenar los datos de usuario y los números de tarjeta de crédito en la misma base de datos ya que una no sirve de nada sin el otro).

Tenga en cuenta que los algoritmos como SHA-512 y Blowfish pueden devolver la sal como parte de su hash. Tenga cuidado con esto, como si almacenara el hash completo, regalaría el algoritmo, lo que significa que hay dos cosas menos que los hackers deben descubrir (la sal también delata el algoritmo).

Asegúrate de aplicar contraseñas y nombres de usuario sólidos, por lo que los ataques de diccionario fallarán; Sé de diccionarios para todas las 6 combinaciones alfanuméricas de entradas de nombre de usuario / contraseña para MD5 y sospecho que hay más que esto disponible para todo tipo de algoritmos. Con la explosión de la computación en nube y CPGPU de bajo costo, el tamaño y la complejidad de los diccionarios disponibles van a explotar.

En definitiva, la forma más segura nunca es generar programáticamente una sal, sino que requieren que el usuario la ingrese junto con su nombre de usuario y contraseña a través de un enlace SSL (para que no pueda ser fisgoneado), pero nunca la almacene. Este es el enfoque adoptado por las compañías de tarjetas de crédito; es decir, la clave de seguridad CSV de 3 dígitos en su tarjeta de crédito que debe ingresar cada vez que compra en línea, ya que nunca debe almacenarse en ninguna base de datos. Si realmente desea generar la sal, envíela por separado (por ejemplo, a través de un mensaje SMS o correo electrónico) y aun así indúquela de manera manual cada vez. Con este enfoque, aunque más seguro, debe contrastar la complejidad con respecto a si los usuarios simplemente dejarán de usar el sitio ya que les ha hecho demasiado difícil que se molesten con él.

Todo lo anterior aún se basa en el hecho de que también tienes protección contra secuestro de sesión, scripts entre sitios, etc., etc. El algoritmo de contraseñas más fuerte del mundo es irrelevante si todo lo que necesito hacer es calcular un PHPSESSID válido para un usuario conectado y secuestrarlo!

No soy un experto en seguridad, pero he leído sobre esto todo lo que razonablemente puedo hacer. El hecho de que haya tantos libros sobre el tema indica cuán grande es realmente la respuesta a su pregunta.

Un par de libros geniales que te gustaría probar y que he encontrado son invaluables;

Vulnerabilidades de la aplicación web Detectar, explotar, prevenir - ISBN-13: 978-1-59749-209-6

Prevención de ataques web con Apache - ISBN-13: 978-0-321-32128-2


La sal se usa para evitar ataques de arco iris al romper la coincidencia entre la contraseña y el hash precalculado. Entonces, la tarea principal de una sal es ser diferente para cada registro de usuario / contraseña. La calidad de la aleatorización de la sal no importa tanto si la sal es diferente para diferentes usuarios.


Sí.
Parece que una marca de tiempo Unix, almacenada en la base de datos de usuarios como un campo "Miembro desde" va a ser una sal decente.

Sin embargo, la pregunta sobre sal es la más insignificante. Hay cosas mucho más importantes a las que debes prestarle atención:

  1. Lo más probable es que una contraseña, un algoritmo de sal o un algoritmo hash no sea la parte más débil de su sitio. Alguna inyección de archivos cojos o XSS o CSRF seguramente lo es. Entonces, no lo hagas demasiado.
    Hablando de una verdadera cadena aleatoria de 32 char de largo en la aplicación web típica es como hablar de una puerta blindada de 32 pulgadas en el granero de madera.

  2. Hablando de contraseñas, lo más importante es la complejidad de las contraseñas. Con una contraseña débil, sin sal ni algoritmos hash, incluso super-ingenioso-increíble-difícil, podría ayudar. Es un dolor pedirle a los usuarios que usen una contraseña compleja, pero sin eso todo lo demás se convierte en una porquería.
    Por lo tanto, su primera preocupación debe ser la complejidad de la contraseña. 12-16 caracteres de casos diferentes, incluidos los números y la puntuación es un requisito.

  3. En cuanto a la sal, no veo beneficio en el uso del tiempo, ya que tienes que almacenarla junto con otros datos de usuario. Mejor usa un correo electrónico: es lo suficientemente aleatorio y ya lo tienes de todos modos. No olvide volver a crear una contraseña si el usuario cambia su correo electrónico. parece que un timstamp de Unix va a ser una sal decente, no es necesario usar el correo electrónico o cualquier otra cosa.

Actualizar
Como puedo ver, muchas personas aún no entienden el punto.
Como ese chico de los comentarios, diciendo

Muchos usuarios usan contraseñas débiles (debemos educarlos, o al menos seguir intentándolo), pero eso no es excusa; todavía merecen buena seguridad

Merecen, sin duda. Pero con una contraseña débil, la misión. es. imposible.

Si su contraseña es débil, entonces no habrá sal que la proteja.

Si bien la sal no es tan importante para pasar un texto de 10 kilobytes sobre el tema.


la fecha en que un miembro se une a un foro / sitio web generalmente es de acceso abierto, lo que sería igual que el tiempo (), lo que hace que su sal sea inútil.


Actualizado

No es una sal muy buena, pero probablemente lo suficientemente buena como para derrotar a todos los atacantes menos decididos e ingeniosos. Los requisitos para una buena sal son:

  • Diferente para cada usuario
  • el tiempo suficiente (como mínimo 8 caracteres alfanuméricos) para hacer que la concatenación de sal y la contraseña (potencialmente débil) sean demasiado largos para un ataque de fuerza bruta.

time() valores de time() no son lo suficientemente largos, ya que tienen 10 caracteres, pero solo dígitos.

Además, a veces dos usuarios pueden obtener el mismo valor cuando se crean dentro del mismo segundo. Pero eso es solo un problema si tiene situaciones en las que muchos usuarios se crean automáticamente en el mismo segundo.

En cualquier caso, mucho más importante que una sal perfecta es utilizar una buena función de hash, y SHA512 es uno de los mejores que tenemos disponible en este momento.