Almacenar contraseñas en forma reversible - un caso de uso genuino

21

¿Qué te pasa, loco loco , se supone que no puedes recuperar una contraseña en texto sin formato?

Lo sé. Escúchame.

Supongamos que tengo un servicio que es similar a Mint.com. Para aquellos que no están familiarizados con Mint, funciona así:

  1. El usuario se registra en Mint.com como lo haría con cualquier otro servicio en línea, al proporcionar una dirección de correo electrónico & contraseña.
  2. Aquí es donde las cosas se ponen interesantes. Luego, el usuario selecciona su nombre de banco de un menú desplegable y proporciona su nombre de usuario y contraseña de banca en línea a Mint.
  3. Aquí es donde las cosas se ponen realmente interesantes. Mint almacena estas credenciales y las usa para recuperar la lista de transacciones de tarjetas de crédito / débito realizadas por el usuario automáticamente, en diferentes momentos del día. Para ello, inician sesión automáticamente en el sitio de banca en línea, utilizando las credenciales de los usuarios (presumiblemente a través de un emulador de todo tipo).

Ahora necesito una forma segura de proteger las credenciales bancarias en línea de mis clientes.

Aquí está la gran pregunta: ¿Cómo lo harías TÚ?

Sí, ya he leído esta pregunta y éste . Todas las respuestas sugieren el uso de un método de comunicación más seguro con la tercera parte (ya sea autenticándose con las claves de la API o pasando parámetros hash). En mi opinión, y es solo eso, una opinión, me parece un caso de uso genuino en el que tengo información increíblemente sensible que NECESITA que esté disponible en texto sin formato, al menos periódicamente a lo largo del día.

Dato interesante: Mint.com tiene más de 10 millones de usuarios

    
pregunta FloatingRock 09.03.2014 - 21:33
fuente

3 respuestas

28

En el caso que ha descrito, está almacenando información en nombre del usuario y no la está utilizando para autenticar al usuario. Por lo tanto, si bien el contenido de lo que está almacenando incluye contraseñas (casi exclusivamente), no está realmente "almacenando contraseñas" en el sentido tradicional. Estás almacenando secretos .

Ajusta tu estrategia en consecuencia.

Ambos de estos problemas están resueltos; Solo necesitas aplicar la solución correcta. Al "almacenar contraseñas" (es decir, autenticar al usuario), se realiza el hashing, la sal, la extensión de la clave, etc., con los que está familiarizado. Pero ¿qué pasa con el almacenamiento de secretos .

En primer lugar, evita el problema si es posible . Es por esto que existen conceptos como tokens de acceso a la API. No necesitas mi contraseña de Facebook porque no puedes usarla. Necesitas un token de acceso que Facebook esté dispuesto a darte con mi permiso.

La siguiente mejor solución es vincular el acceso al inicio de sesión del usuario . La información se cifra mediante una clave derivada de la contraseña que utiliza para iniciar sesión, que no sé y no almaceno. Por lo tanto, yo (el propietario del servidor) no puedo acceder a sus datos a menos que escriba su contraseña.

Esto es popular porque es poderoso. De hecho, Windows ha estado haciendo esto durante mucho tiempo, por lo que cambiar su contraseña puede hacer que los archivos cifrados se vuelvan inaccesibles. También es la razón por la que su contraseña de Windows se almacena en texto sin formato en la memoria mientras está conectado. Un error de implementación que le recomendaría evitar.

A continuación, en nuestra lista, puede separar sus procesos , de modo que los datos sin cifrar nunca estén disponibles en las máquinas que se encuentran en el exterior. Puntos extra si hay un HSM involucrado. Lo esencial aquí es que el usuario proporciona sus secretos al servidor web, que se encriptan rápidamente mediante la clave pública de un dispositivo criptográfico secreto que es totalmente inaccesible porque no está conectado. Los secretos simples se olvidan de inmediato, y los datos encriptados se envían a algún lugar de almacenamiento en frío en algún lugar.

Finalmente, los secretos se descifran en otro lugar con la ayuda de ese dispositivo de cifrado y se utilizan. Sólo, el punto donde esto sucede NO TIENE ACCESO A INTERNET. O al menos no hay camino desde el exterior hacia adentro.

Finalmente, puedes probar la solución anterior, pero fallar miserablemente. Solo menciono esto porque en realidad todas las demás soluciones son simplemente malas variantes de las anteriores: cifrado en la base de datos, usando una contraseña de aplicación , almacenando la contraseña en otro servidor, almacenando los datos en otro servidor, compartiendo su clave de cifrado con [ idea tonta aquí ], y así sucesivamente.

Y finalmente, mi advertencia estándar para preguntas como esta se aplica. Lo escribiré realmente grande:

  

El hecho de que esté haciendo esta pregunta significa que no debe hacerlo

En serio. ¿Almacenar las credenciales bancarias de las personas? Si no entiende a qué tipo de problemas se está metiendo, si está pidiendo a Internet sugerencias sobre cómo hacer esto, si todas las soluciones que mencioné no fueran YA YA lo más importante para usted como las únicas opciones viables, entonces no debería implementar esto .

La gente confía en que hagas esto bien. Y no vas a hacer esto bien. No porque no hiciste las preguntas correctas, sino porque no ha resuelto este problema con la frecuencia suficiente para comprender qué trampas ocultas habrá pasado por alto. Esto es difícil: no es difícil hacer , pero sí es difícil no cometer errores.

No traicione la confianza de sus clientes metiéndose de cabeza.

    
respondido por el tylerl 10.03.2014 - 09:16
fuente
4

Aunque no estoy de acuerdo con esta práctica, si tuviera que mantener información muy confidencial en mi servidor, esto es lo que haría:

  • Cree un pequeño demonio en el mismo servidor y solicite que un operador humano ingrese una contraseña / clave en el inicio.
    • Derive una clave de cifrado simétrica y un par de claves asimétricas a partir de ella.
  • Mantenga estas claves solo en la RAM, evite el intercambio .
  • Cuando un usuario desea enviar la información confidencial al servidor, pídale que la cifre en el navegador utilizando la clave pública (para que solo el demonio la pueda leer). Haga que el demonio lo cifre utilizando la clave simétrica y regrese al servidor web principal, que ahora puede almacenarlo.
  • Cuando el sistema quiera hacer algo con la información confidencial, pase los datos cifrados al demonio. Luego debe descifrarlo e idealmente usarlo de inmediato (por ejemplo, realizar la solicitud de un tercero, y no registrar nada en ningún lugar), borrar el texto sin formato y solo devolver la respuesta (es decir, el servidor web principal no "ve" el texto sin formato en cualquier momento).

Por supuesto, debe usar cualquier práctica de seguridad complementaria que pueda, pero el núcleo de esta técnica es que solo los atacantes con acceso a la máquina en vivo, capaces de leer el contenido de RAM de otro proceso, pueden recuperar los datos confidenciales en texto sin formato. O si los atacantes pueden inyectar su propio código en el servidor, de modo que en el próximo reinicio, el operador ingrese la contraseña para su daemon. Si pueden simplemente enviar comandos arbitrarios al demonio, podrán hacer todo lo que puede hacer el demonio (es decir, leer los datos obtenidos de esas credenciales, pero no las credenciales en sí, ni realizar acciones para las que el demonio no estaba programado) .

Dicho esto, si 10 millones de tontos no fueran personas de mentalidad de seguridad hicieron negocios conmigo, probablemente me permitiría contratar a los mejores profesionales de seguridad, en lugar de confiar solo en mi propio conocimiento (como hago ahora). Eso podría evitar que mi sistema sea el enlace más débil, a pesar de lo atractivo que puede llegar a ser para los atacantes. Solo ten esto en cuenta antes de hacer cosas ambiciosas que, si bien son potencialmente útiles, podrían meterte en problemas si cuando las cosas salen mal.

    
respondido por el mgibsonbr 10.03.2014 - 08:41
fuente
2

No lo haría, a menos que esté completamente seguro de que nadie podría entrar en mi base de datos, preferiría tener esa información almacenada en los dispositivos de los usuarios para que mi servicio no sea responsable por cualquier pérdida de datos. Pero si tuviera que hacerlo ...

Cuando un usuario crea una cuenta, generaría una clave AES-256 (llamémosla storage_key ), luego cifrar esa clave con una clave derivada de la contraseña del usuario (llamémosla user_key ) usando algunos KDF sólidos (scrypt, bcrypt, PBKDF2 ...) y guárdelos como encrypted_storage_key junto con la sal, las iteraciones y otros parámetros utilizados por el KDF para derivar el user_key en la cuenta del usuario.

Entonces el proceso para ingresar / leer los datos se vería así:

  1. El usuario ingresa una contraseña.
  2. El uso del KDF seleccionado y los parámetros almacenados derivan el user_key .
  3. Descifre el encrypted_storage_key almacenado con el user_key y obtenga el storage_key original.
  4. Use este storage_key para cifrar / descifrar los datos confidenciales.
  5. No guarde el storage_key en la memoria por más tiempo del que pueda necesitar y nunca lo guarde de esa forma.

Por supuesto, para que este esquema tenga alguna seguridad, es de suma importancia asegurar la 'línea' a través de la cual el usuario ingresa su contraseña (por ejemplo, SSL / TLS como mínimo si estamos hablando de un sitio web). ) - si alguien es capaz de obtener la contraseña original, todo el esquema se deshace.

    
respondido por el BeagleEagle 09.03.2014 - 22:04
fuente

Lea otras preguntas en las etiquetas