¿Qué tan seguro es almacenar una contraseña encriptada en el almacenamiento local HTML5?

5

Background

Estoy intentando desarrollar una aplicación web en la que un usuario pueda iniciar sesión con su contraseña 'P' y, al iniciar sesión, puede crear una contraseña maestra 'MP'. MP se puede usar para abrir / cerrar una bóveda (como los administradores de contraseñas) en la que el usuario puede almacenar información confidencial. Al hacer una investigación sobre el tema, he decidido asegurar lo siguiente:

  • La contraseña maestra MP nunca se almacena / envía al servidor
  • Todo el cifrado / descifrado se realiza en el lado del cliente (en mi caso es el navegador)

Ahora que estoy almacenando la clave MP ′ (definida a continuación) en la memoria, la bóveda se cierra esencialmente cada vez que se actualiza el navegador o el usuario abre el sitio en una nueva pestaña. ¿Cómo puedo mantener la bóveda para que permanezca abierta durante el tiempo que el usuario quiera? La cookie no es una solución, ya que hará que se envíe MP ′ al servidor en cada solicitud; sin embargo, el almacenamiento local HTML5 puede ser una posibilidad

Ahora, si un pirata informático obtiene acceso al almacenamiento local, obtendría un MP ′ y podrá descifrar toda la información confidencial al usarlo. Como solución aquí es en lo que estoy pensando:

  1. Cuando se abre la bóveda, el cliente solicita una clave aleatoria única 'Rk' desde el servidor
  2. El servidor genera Rk, lo almacena en la sesión del usuario y lo envía de vuelta al cliente
  3. El cliente usa Rk para cifrar MP ′ para obtener MP ′ ′
  4. MP ′ ′ se almacena en el almacenamiento local de HTML5 mientras que Rk se guarda en la memoria
  5. Cuando sea necesario, el MP ′ ′ se puede descifrar usando Rk y se usa para operaciones posteriores
  6. Al actualizar el navegador, el cliente vuelve a buscar Rk del servidor (el servidor simplemente devuelve el que ya está almacenado en la sesión)
  7. Rk ha caducado si el usuario cierra explícitamente la bóveda o finaliza la sesión al cerrar sesión

La pregunta

¿Qué tan segura sería esta solución? ¿Alguna advertencia obvia que me esté perdiendo? ¿Cuál sería el enfoque ideal para solucionarlo?

Notas adicionales

Para su comprensión, aquí hay un breve resumen de cómo planeo satisfacer mis necesidades:

  1. El usuario crea un nuevo MP
  2. MP está encriptado con un algoritmo de estiramiento de claves para producir MP ′
  3. MP ′ se usa como una clave para cifrar un valor conocido V para obtener Vh (obviamente V ≠ MP o MP ′)
  4. Vh se almacena en el servidor contra el registro del usuario

Vh sirve 2 propósitos:

  1. Indica que el usuario ya ha creado un MP. Si aún no está allí, puedo pedirle al usuario que cree uno nuevo
  2. Cuando el usuario ingresa a MP para abrir la bóveda, puedo recuperar Vh del servidor e intentar descifrarlo con MP ′. Si el descifrado es exitoso, asumo que el usuario ingresó el MP correcto

Como puedes imaginar, así es como debería funcionar el resto:

Siempre que el usuario desee almacenar / recuperar información confidencial:

  1. Se conectan con P y abren su bóveda con MP
  2. El cliente produce MP ′ como se mencionó anteriormente
  3. La información confidencial se encripta utilizando MP ′ antes de enviarse y almacenarse en el servidor
  4. Según la necesidad del usuario, la información confidencial encriptada se recupera del servidor (como está)
  5. El cliente usa MP ′ para descifrar los datos
pregunta Tanvir 21.06.2017 - 00:54
fuente

2 respuestas

2

Hay varios problemas con su enfoque:

1) Secreto hacia adelante. Supongamos que el atacante puede supervisar la comunicación (a través de un proxy https corporativo pirateado o de otra forma). En algún momento posterior, el usuario borra la cuenta y revela MP como él cree que es inútil. Usando los datos registrados y el MP, toda la información puede ser restaurada por el atacante porque está cifrando la bóveda con el MP '.

2) No está claro cómo defiendes contra comprometer a P. Capturando P (que pasa a través de la red) el atacante puede iniciar sesión, adquirir Rk y descifrar MP ", a menos que Rk se regenere en todos los inicios de sesión, lo que significa que el usuario será efectivamente desconectado si cierra el navegador (puede que esté bien y esté destinado, no sé). De todos modos, es mejor no enviar P (ver ideas abajo).

3) El cifrado le dará una mejora de seguridad limitada. Si el atacante puede acceder a LocalStorage, es probable que tenga acceso físico y / o comprometa su máquina, por lo que está condenado de todos modos (se enfrenta a keyloggers, inyecciones de scripts locales, lo que sea). El cifrado lo ayudará si el disco duro es robado o si el atacante puede falsificar su dominio (por ejemplo, envenenamiento de caché de DNS). Es mejor no almacenar la contraseña en primer lugar.

Varias ideas:

  • para mitigar (1) use claves de sesión únicas para cifrar todos los mensajes. Por ejemplo, puede usar criptografía asimétrica para enviar al servidor una clave de sesión aleatoria (cifrada con la clave pública del servidor). Alternativamente, es posible que desee hacer cumplir las sesiones SSL adecuadas (informando y educando a sus usuarios), ya que SSL tiene un secreto bastante bueno.

  • para (2) en lugar de usar P para autenticarse, use algún método avanzado, por ejemplo. OAuth, preferiblemente 2FA.

  • puede considerar usar sessionStorage en lugar de localStorage, que se garantiza que se eliminará al reiniciar el navegador (otras formas son muy similares a las cookies sin conexión de red). No estoy seguro de que todas las implementaciones (o alguna) puedan eliminar de forma segura todos los rastros del almacenamiento en la salida, por lo que el cifrado aún podría ser una buena idea.

respondido por el goteguru 02.08.2017 - 22:15
fuente
0

Creo que podría valer la pena reevaluar su premisa. Es de suponer que desea cifrar las cosas del lado del cliente para que el servidor no tenga acceso a datos no cifrados, pero este no es realmente el caso, y creo que termina siendo un teatro de seguridad más que la seguridad real.

Este es de 2011, pero creo que el problema principal sigue siendo relevante, si no puede confiar en que el servidor maneje el cifrado de datos correctamente (es decir, cifrelo, luego olvide el texto plano y la contraseña), entonces, ¿cómo puede confiar en que se entregará ¿El código que debe manejar el lado del cliente de cifrado?

Parece que esto podría ser beneficioso en el caso de un compromiso que le permita al atacante leer las solicitudes sin modificarlas, pero aún confía tanto en el servidor que no estoy convencido de que valga la pena.

    
respondido por el AndrolGenhald 02.08.2017 - 23:01
fuente

Lea otras preguntas en las etiquetas