2011-06-24 794 views
8

¿Me he perdido algo? ¿Hay pasos adicionales para almacenar contraseñas en la base de datos?Aplicación web - Almacenar una contraseña

Almacenamiento de la contraseña:
        Después de mucha investigación sobre el tema de lo posible he llegado a la conclusión de que la mejor manera de almacenar las contraseñas de usuario en una aplicación web DB (en mi caso MySQL + PHP) es el siguiente:

  • Asigne una sal estática para todo el sitio. (16 caracteres rand incl 0-9, a-z, A-Z, []/* - ')
  • Asigna un sal aleatorio por usuario (almacenado en el DB).
  • Almacena el resultado hash_function ($ userPassword + $ sitewideSalt + $ randomSalt)
  • Almacena el $ randomSalt junto con el hash resultante.
  • Uso bcrypt carga de trabajo ajustable hash

  • Ataque # 1:atacante vuelca la base de datos a través de la inyección de SQL.
            resultados de base de datos de nuestra hash_function y el azar por la sal de usuario.

    Después del vaciado el atacante podría obtener $ userPassword y $ randomSalt por buscar su propia cuenta. Entonces adivinando la función hash como md5 podría iniciar un ataque de arco iris en el $ sitewideSalt. Pero eso podría tomar hasta 1,41 cientos de millones siglos [1].

    Mediante el uso de este tipo de seguridad no permite un volcado de la base de datos para comprometer las contraseñas almacenadas. El usuario todavía tiene que encontrar el $ sitewideSalt a través de otro método.

  • Ataque # 2:atacante encuentra un vector Inclusión de archivos locales (LFI).
            Attacker podría obtener el código sin formato para nuestra aplicación web.

    Después de explotación de la aplicación web a través de una posible LFI o RFI [2] el atacante lee el código fuente para nuestra aplicación web y obtiene nuestro algoritmo simple y el almacenado
    $ sitewideSalt.


¿Y ahora?
        Ahora el atacante tiene las dos sales que puede comenzar a usar para obtener las contraseñas reales. Excepto que debe crear 1 tabla arcoíris para cada usuario, ya que cada usuario tiene una sal específica de usuario diferente ($ randomSalt).

"Un servidor moderna puede calcular el hash MD5 de alrededor de 330 MB por segundo. Si sus usuarios tienen contraseñas que son minúsculas, caracteres alfanuméricos, y 6 caracteres de longitud, se puede probar cada única posible contraseña de ese tamaño en alrededor de 40 segundos. "
"... CUDA, se puede armar su propio pequeño grupo superordenador que le permitirá probar alrededor de 700 millones de contraseñas Una segunda ..." [3]

        Lo que tenemos que hacer ahora es amplíe la función de hash utilizando un algoritmo que consume mucho tiempo, como bcrypt. El factor de carga de trabajo de bcrypt puede ser de 5 a 6 órdenes de magnitud que el de las funciones de hashing más simples. Romper una sola contraseña puede llevar años en lugar de minutos. Y como bonus bcrypt ya genera una sal aleatoria para cada hash y lo almacena en el hash resultante.

  1. http://www.grc.com/haystack.htm
  2. http://www.wildcardsecurity.com/security101/index.php?title=Local_File_Inclusion

Respuesta

3

¡Buen trabajo! Me parece muy completo.

Sólo las sugerencias que habría son:

Girar la sal servicio.

Diseñe un método para rotar periódicamente la sal de todo el servicio y ejercítela regularmente.

Por ejemplo, después de generar un nuevo servicio de sal, lo utilizan para todas las cuentas nuevas & cualquier cambio de contraseña. Cuando un usuario existente intenta iniciar sesión, autentíquelos con el viejo sal de servicio. Si tiene éxito, actualice su hash con la nueva sal de servicio (y opcionalmente una nueva sal específica para el usuario). Para los usuarios que no inician sesión durante 'algún tiempo', generan aleatoriamente una nueva contraseña en su nombre. Esto mantendrá la seguridad de los usuarios que abandonaron su sitio, lo que obligará a los que vuelvan a utilizar las funciones de restablecimiento de contraseña. ('algún tiempo' = cualquier período con el que se sienta cómodo).

No codifique su sal de servicio.

No permita que un ataque de LFI comprometa la sal del servicio. Alimente la sal de servicio a su aplicación al inicio y consérvela en la memoria. Para comprometer la sal del servicio, un atacante tendría que ser capaz de ejecutar código para leer la sal de la memoria. Si un atacante puede hacer eso, de todas maneras estás bastante bien tratado. =)

No reutilice la sal de un usuario.

Busque oportunidades para dar a los usuarios nuevas sales. El usuario cambia su contraseña? Genera una nueva sal aleatoria. Esto dificulta aún más la fuerza bruta de su sal en todo el servidor si un atacante puede obtener su hash cada vez que lo desee. Acompañe esto con la rotación periódica de su sal de servicio, y apostaría a que tiene un fuerte elemento de disuasión contra la fuerza bruta.

(Marcando esto como un wiki de la comunidad si otros tienen ideas adicionales).

+0

Estoy un poco confundido. ¿cómo funciona la lógica del servicio sal para la autenticación? Supongo que almaceno una sal de servicio en mysql y luego cuando inicio sesión, lo anexo al hash de usuario y al hash de tienda y verifico si son iguales. pero, ¿no es lo mismo que no tener un servicio de sal? ya que si el hash de usuario y el hash de tienda coinciden, la sal de servicio añadida también coincidirá. –

+0

¿Por qué necesita rotar la sal regularmente? – sam

1

Usando Bcrypt para manejar las contraseñas es el único paso, o mejor dicho, abarca lo siguiente:

  1. Tome contraseña, proporciona a la biblioteca Bcrypt.
  2. Tienda de hash resultante.
  3. Comparar la contraseña para el hash.

También ha olvidado este enlace: http://codahale.com/how-to-safely-store-a-password/, que es lo que hace referencia con la cita.

Cuestiones relacionadas