Javascript - Cifrado del lado del cliente / almacenamiento de claves

5

Me doy cuenta de que esto a menudo se describe como una mala idea. Así que, en primer lugar, indicaré la motivación. Siéntete libre de criticar esto.

Crear un producto para una industria que tiende a preocuparse demasiado por la seguridad. El producto necesita almacenar y devolver archivos de usuario, pero no es necesario que sean legibles por el servidor.

Siento que cifrar el lado del cliente reduciría la confianza requerida de los clientes. Sus datos confidenciales solo serían tocados por JavaScript que podrían inspeccionar y monitorear. También significa que cualquier lado del servidor de problemas de seguridad que permita el acceso a los datos almacenados no dará lugar a que los documentos del cliente estén disponibles (excepto si pueden modificar el JS servido).

Mi solución ideal sería -

- Key generated and injected to all clients users by clients IT team.
- JavaScript uses key to encrypt documents client side. These are then sent to the server and stored.
- On retrieval documents are decrypted again client side.

Parece que hay varias bibliotecas para admitir el cifrado del lado del cliente. Pero actualmente no veo ninguna manera de almacenar de forma persistente una clave para el usuario. Idealmente, esto sería similar a agregar certificados a la tienda de navegadores, es decir, se pueden inyectar una vez.

¿Alguien tiene alguna sugerencia?

    
pregunta Hector 13.09.2017 - 17:55
fuente

3 respuestas

2

(Para ser claro: esto solo protege a los usuarios en situaciones en las que el atacante solo obtiene acceso de solo lectura y protege a los usuarios que no han usado el sitio desde que un atacante reemplazó el javascript con una versión maliciosa. No protege a los usuarios de ser malicioso desde el principio, a menos que el usuario verifique / registre con esmero todo el javascript que su sitio les entrega. Si esa última parte es importante para usted, podría haber una manera de usar ServiceWorkers para alertar a los usuarios cada vez que una nueva versión del javascript de su sitio sea ejecutado, etc., pero eso es para otra pregunta.)

Puede almacenar las claves de cifrado localmente en el cliente con localStorage o IndexedDB. Las claves de cifrado podrían ser cadenas que utiliza el javascript de su cliente.

En los navegadores compatibles, para mayor seguridad, puede usar la API de criptografía web (+ IndexedDB) en su lugar. Con la Web Crypto API, puede generar claves en javascript y usarlas para el cifrado / descifrado, pero el código de javascript no puede obtener acceso al material de claves sin importar lo que pase. Eso significa que incluso si un atacante obtiene acceso a su servidor un día y reemplaza el javascript con una versión maliciosa, no puede reemplazarlo con una versión que filtre las claves de los usuarios. (Sin embargo, podrían reemplazarlo con una versión que permita a los clientes descargar sus archivos, descifrarlos y volver a cargarlos en el servidor en segundo plano la próxima vez que vayan al sitio. Esto llevaría tiempo y podría ser perceptible para los usuarios y / o usted, por lo que podría darle suficiente tiempo para solucionar el problema antes de que se filtren todos los datos del usuario.)

    
respondido por el Macil 14.09.2017 - 00:36
fuente
0

Si controla el código fuente del lado del servidor:

Mi sugerencia es que almacenes al menos 4 claves en el backend que giras y en el lado del servidor de encriptación simétrica del usuario, y luego en el lado del servidor de encriptación y descifrado.

Tuve un caso de uso similar en el que mi flujo de trabajo fue (con cifrado de fernet):

  • El usuario carga datos y luego se cifra con 1 de 10 claves (rotadas) luego almacenados en la base de datos

  • En la consulta después de que obtuve if de DB, descifre y envíela al frontend

Ventajas:

  • Más seguro que manejar cualquier clave en la interfaz

  • Si la base de datos se explotó a través de la inyección de SQL, no es texto sin formato

Desventajas:

  • Necesita más recursos del lado del servidor, ya que ralentiza el proceso

  • Las claves aún están en el lado del servidor de texto simple, por lo que si la máquina host no se vio comprometida allí, pero el atacante sigue siendo un paso más para obtener datos.

Si no controla el código del lado del servidor:

Lo mejor que puede hacer es almacenar la clave simétrica en la base de datos y generar un registro para cada usuario. Después de iniciar sesión, guárdelo en la cookie como sesión para ese usuario

Ventajas:

  • Fácil de implementar

  • Cada usuario tiene su propia clave simétrica. Si una cuenta de usuario se ve comprometida, los datos de otros usuarios no se pueden descifrar.

Desventajas:

  • La cookie puede ser robada por lo que no es necesario tener un encabezado iframe

  • Si no se usan los ataques de mitm HTTPS y HSTS, puede obtener fácilmente los datos

Pero no tomes mi sugerencia como espera del Santo Grial e investiga más fuentes, entonces tú decides. ;)

    
respondido por el Hrvoje Milković 13.09.2017 - 19:52
fuente
0
  

Siento que cifrar el lado del cliente reduciría la confianza requerida de los clientes. Sus datos confidenciales solo serían tocados por JavaScript que podrían inspeccionar y monitorear.

Esto no es realmente cierto. Ninguna persona normal puede inspeccionar y monitorear javascript que el navegador descarga desde un sitio, y si confío en el servidor / el servidor admin / los desarrolladores de software del servidor lo suficiente como para creer que no me envían javascript con una puerta trasera, también podría Confía en ellos para almacenar mis archivos.

Estoy de acuerdo en que es una capa adicional de seguridad, pero es una que se elimina tan fácilmente que parece casi inútil implementarla. Protege contra algunos escenarios de amenazas, por ejemplo, probablemente protege las copias de seguridad o los discos duros antiguos que no se eliminan al filtrar los datos del cliente, pero en realidad no reduce la confianza que los clientes tienen que depositar en el proveedor de servicios. / p>

  

Pero actualmente no veo forma de almacenar de forma persistente una clave para el usuario.

Si no desea almacenarlo en el almacenamiento del navegador del lado del cliente, podría

a) Haga que el usuario proporcione al cliente javascript una frase de contraseña, cifre simétricamente la clave con la frase de contraseña y un cifrado simétrico fuerte y envíe la clave al servidor para que se almacene allí

b) Visualice la clave como un código QR y haga que el usuario tome una foto con su móvil. Cuando necesite recuperar la clave, el usuario puede copiar y pegar la cadena de clave que el código QR resuelve en la aplicación javascript del lado del cliente. Sin embargo, eso es muy engorroso.

    
respondido por el Pascal 14.09.2017 - 00:16
fuente

Lea otras preguntas en las etiquetas