¿Cuál es la mejor manera de mantener contraseñas claras de manera segura?

7

Estoy trabajando en un proyecto web que se conectará a una base de datos. Para eso, tendré que almacenar el inicio de sesión / contraseña de ese usuario de la base de datos en forma clara (cifrada de manera simétrica) para poder volver a conectar cada acción (como crear una tabla, agregar entradas, etc.) sin tener que para solicitar esas credenciales cada vez.

Soy consciente de que almacenar la contraseña de forma clara es demasiado inseguro y está fuera de mis posibilidades.

Esto es lo que pensé, ¿podría decirme si sería correcto o si existe una posibilidad mejor? gracias :)

La aplicación se dividirá en dos partes independientes: el frontend y el backend.

Cuando el usuario inicie sesión a través de la interfaz, el inicio de sesión y la contraseña se enviarán sin cifrar (recomendaré el uso de HTTPS). El backend intentará conectarse a la base de datos, si tiene éxito, cifrará el inicio de sesión y la contraseña con Blowfish y los devolverá a la interfaz.

Para cualquier solicitud posterior, la interfaz tendrá que enviar el nombre de usuario / contraseña encriptado, sin saber nunca el claro, solo el cifrado.

Si alguien tiene acceso a los datos de este usuario (por ejemplo, XSS), solo podrá acceder a las credenciales cifradas, no a la clara.

Si un atacante puede hacer un MITM, solo el inicio de sesión inicial es riesgoso, todas las siguientes solicitudes serán con las credenciales cifradas.

Pensé en usar cookies / sesión, pero es lo mismo: los valores se almacenan en claro o codificados en base64. No es realmente seguro!

La idea de Blowfish proviene de cómo PhpMyAdmin lo usa (también conocido como el mismo). Además, incluso en PhpMyAdmin, la parte de inicio de sesión también se envía de forma clara.

¿Crees que mi implementación es correcta o tienes algo mejor que sugerir? Realmente me gustaría hacer algo lo más seguro posible. Hasta ahora, solo la parte de inicio de sesión me molesta: /

Gracias por tus ideas.

EDIT:

Aparentemente, mi pregunta no es lo suficientemente clara, voy a tratar de ser más explícita :

Quiero construir una alternativa a PhpMyAdmin. PhpMyAdmin es un middleware que se conecta a un servidor MySQL proporcionando el nombre de usuario / contraseña de cualquier usuario en esa base de datos. Las credenciales solicitadas en el formulario web son las que se utilizan para la base de datos MySQL.

Por lo tanto, durante toda la sesión después de que el usuario haya iniciado sesión correctamente, PhpMyAdmin almacena el inicio de sesión / contraseña en la sesión mediante el cifrado de la contraseña con Blowfish.

Esto NO PUEDE evitarse, porque cada vez que el usuario realiza una solicitud (como crear una tabla, insertar datos, actualizar o eliminar datos), PhpMyAdmin NECESITA volver a conectarse a esa base de datos utilizando las credenciales proporcionadas al iniciar sesión, y luego realice la acción que el usuario solicitó.

Por lo tanto, no es posible para PhpMyAdmin almacenar solo un hash de las credenciales, ya que no podrá volver a conectarse a la base de datos durante las solicitudes posteriores realizadas por ese mismo usuario.

Soy consciente de que almacenar la contraseña que se puede recuperar sin ningún problema es no es una buena solución , y esa es la razón de esta pregunta: no me lo dice el hashing es mejor, porque es absolutamente inútil en mi caso, pero para saber si hay una mejor alternativa que el cifrado simétrico + HTTPS para mantener una contraseña que se necesita para cada acción que realiza el usuario.

    
pregunta Cyril N. 27.07.2012 - 10:40
fuente

7 respuestas

4

Ahora que la pregunta ha sido revisada, entiendo lo que intentas hacer mucho mejor.

La respuesta corta es: Simplemente almacene la contraseña de la base de datos de forma clara, en el objeto de sesión (del lado del servidor) . No puedes hacerlo mejor.

Si lo desea, puede cifrar la contraseña de la base de datos y almacenar la contraseña cifrada en el objeto de la sesión, pero realmente no tiene sentido, porque ¿dónde guardará la clave? No hay un lugar donde pueda almacenar la clave que es mucho más segura que el objeto de sesión. Puede almacenar la clave en un archivo de configuración o en una variable global, pero en realidad, no estoy seguro de que esto agregue seguridad contra cualquier amenaza realista. Es difícil ver por qué molestar, me parece un teatro de seguridad.

Entonces, simplemente haga que el usuario ingrese la contraseña de la base de datos al comienzo de la sesión, almacene la contraseña de la base de datos en el estado de la sesión y termine con ella. No hay nada mejor que puedas hacer.

Y, por el amor de Dios, use una buena práctica de programación de aplicaciones web. Echa un vistazo a los recursos OWASP. Asegúrese de estar familiarizado con las vulnerabilidades comunes de la web que se ven en el mundo web. Escriba su código cuidadosamente, usando buenas prácticas de seguridad. Y pídale a alguien que sepa algo sobre seguridad que haga una revisión de seguridad de su código. Si hay una vulnerabilidad de seguridad en su código, sucederán cosas malas.

    
respondido por el D.W. 30.07.2012 - 19:17
fuente
2

No debería tener que mantener las credenciales en un formato recuperable, incluso si están cifradas. Si su aplicación de back-end podría descifrar algo, entonces cualquiera podría piratear su aplicación de back-end. Realmente, debes asumir que, tarde o temprano, tu aplicación backend se verá comprometida y se diseñará con eso en mente.

El método más seguro probablemente sería almacenar las contraseñas con sal y hacer hash utilizando un algoritmo como bcrypt o PBKDF2 . En estos días, el hashing / salating regular con algo como MD5 o SHA1 no es lo suficientemente seguro. Los programas como hashcat pueden generar archivos de contraseñas de craqueo realmente rápido. Este artículo sobre hashcat es una excelente lectura .

Es bueno que te preocupe que alguien tenga acceso a la tienda de cookies. Las cookies son básicamente equivalentes de contraseñas, por lo tanto, si las almacena, probablemente también deberían tener hashes salados.

Y realmente, esto parece muy fácil pero hay muchos casos de esquina. Si el marco de trabajo de tu aplicación ya tiene una forma de administrar la sesión, probablemente deberías usarlo en lugar de rodar el tuyo.

Echa un vistazo a la Hoja de referencia para la gestión de sesiones de OWASP para ver algunas buenas recomendaciones.

    
respondido por el Shizzmo 28.07.2012 - 19:28
fuente
1

Primero: ¿Estás seguro? Primero, verifica si realmente necesitas almacenar las contraseñas en texto sin cifrar o en forma recuperable. Su pregunta no explica por qué esto es necesario. Si tiene una brecha de seguridad, todos estarán cuestionando su decisión, y si resulta que almacenó las contraseñas en un formato recuperable, su organización puede sufrir alguna pérdida de reputación. Por lo tanto, asegúrate de que esto sea realmente necesario.

Siguiente: define el problema. Entonces, ¿qué es exactamente lo que estás tratando de hacer? La pregunta no fue muy clara, así que voy a hacer algunas conjeturas. Si estas conjeturas no son precisas, edite la pregunta después de reflexionar un poco más sobre esto.

Supuesto: los usuarios inician sesión en su aplicación web, llamémosla CyrilApp, usando un nombre de usuario y contraseña para su aplicación. Desea que su código pueda acceder a alguna otra cuenta de ellos, por ejemplo, su correo electrónico a través de IMAP, por lo que le pide que ingrese su nombre de usuario y contraseña de correo electrónico para que su código de servidor lo use más adelante. Ahora desea saber cómo almacenar la contraseña del correo electrónico de la forma más segura posible. ¿Se trata de la idea?

Si ese es el problema, entonces tiene varios problemas a considerar: ¿cómo almacenar las contraseñas de correo electrónico? Al recuperar las contraseñas de correo electrónico, ¿cómo usarlo de forma segura? ¿Cómo restringir el acceso a la contraseña del correo electrónico?

Almacenamiento. Una opción es almacenar las contraseñas en un módulo de seguridad de hardware (HSM), o cifradas bajo una clave administrada por un HSM. Sin embargo, los HSM son muy caros, por lo que es posible que esto no sea factible.

Una solución más pragmática es crear un servicio separado, llamémoslo EmailPasswordStore, que realiza una función simple y estrecha, está cuidadosamente codificado y es confiable para almacenar las contraseñas de correo electrónico de forma segura. Puede ofrecer una API que permita que el código de CyrilApp almacene la contraseña de correo electrónico de un usuario (cuando la ingrese) y una API que permita que el código de CyrilApp solicite el uso de la contraseña (por ejemplo, EmailPasswordStore podría abrir una conexión IMAP para el servidor IMAP, envíe el nombre de usuario y la contraseña del correo electrónico del usuario, y luego transmita los bytes entre CyrilApp y el servidor IMAP.

En esta arquitectura, las contraseñas de correo electrónico nunca saldrían de EmailPasswordStore, y el trabajo de EmailPasswordStore es asegurarse de que este siga siendo el caso, incluso si CyrilApp está comprometido o el resto de sus servidores son atacados por un atacante, el EmailPasswordStore debe evitar que el atacante obtenga las contraseñas de correo electrónico. Puede ejecutar EmailPasswordStore en una máquina separada (o posiblemente en una máquina virtual separada), con una VPN entre CyrilApp y EmailPasswordStore, y hacer una revisión de seguridad cuidadosa del código de EmailPasswordStore.

Uso. No es suficiente almacenar las contraseñas de correo electrónico de forma segura, porque en algún momento querrá usarlas. Si solo almacena las contraseñas de correo electrónico de alguna forma encriptada, y luego las descifra cuando quiere usarlas, no está obteniendo muchos beneficios de seguridad: un atacante que comprometa su aplicación web podría quedarse en silencio y robar cada contraseña como se usa. , o posiblemente incluso descifrar todas las contraseñas en sí. Entonces, necesitas algunos controles de uso.

La arquitectura de EmailPasswordStore propuesta mencionada anteriormente proporciona estos controles. Utiliza la contraseña del correo electrónico en sí, y nunca revela la contraseña a su aplicación web CyrilApp. Intenta ver si puedes hacer algo así en tu entorno.

Restricción de acceso. Finalmente, es posible que desee limitar quién puede solicitar a EmailPasswordStore que use la contraseña. Un buen punto de partida es que EmailPasswordStore autentique el servicio que se está conectando a él; por ejemplo, puede configurar una VPN entre CyrilApp y EmailPasswordStore y asegurarse de que EmailPasswordStore rechace todos los demás intentos de conexión.

Una arquitectura más sofisticada puede verificar la identidad del usuario que ha iniciado sesión actualmente y restringir el acceso solo a esa contraseña de correo electrónico. Por ejemplo, EmailPasswordStore podría almacenar una lista de las contraseñas de hash que los usuarios utilizan para iniciar sesión en CyrilApp, y requerir que CyrilApp envíe la contraseña de inicio de sesión del usuario a EmailPasswordStore para su verificación antes de desbloquear la contraseña de correo electrónico del usuario. Sin embargo, esto puede ser innecesario en algunas configuraciones.

Lecturas adicionales. Vea también ¿Dónde almaceno de forma segura la clave de un sistema donde la fuente es visible? y dónde almacenar una clave para el cifrado .

    
respondido por el D.W. 29.07.2012 - 07:29
fuente
0
  • Cuando el usuario inicie sesión a través de la interfaz, el inicio de sesión y la contraseña se enviarán sin cifrar (recomendaré el uso de HTTPS). El backend intentará conectarse a la base de datos; si tiene éxito, cifrará el nombre de usuario y la contraseña con Blowfish y los devolverá a la interfaz.

En su lugar, deberías usar un hash salado.

  • Para cualquier solicitud posterior, la interfaz tendrá que enviar el nombre de usuario / contraseña cifrados, sin saber nunca el claro, solo el cifrado. Si alguien tiene acceso a los datos de este usuario (por ejemplo, XSS), solo podrá acceder a las credenciales cifradas, no a la clara.

¿Por la implementación de blowfish en javascript? Si un atacante conociera la contraseña cifrada, simplemente podría desactivar el javascript y enviarlo sin saber el original.

  • Si un atacante puede realizar un MITM, solo el inicio de sesión inicial es riesgoso, todas las siguientes solicitudes serán con las credenciales cifradas.

Si alguien trata de MITM HTTPS, recibirá una advertencia de certificado no válido (a menos que haya conseguido obtener su clave privada o la haya falsificado de alguna manera, esto es muy improbable), en cuyo caso simplemente deja de intentar cargar la página y no se produce ningún daño. hecho.

    
respondido por el user11101 27.07.2012 - 12:16
fuente
0

Su servidor de aplicaciones para el usuario debe lidiar con la autenticación y debe almacenar las contraseñas cifradas. La contraseña con hash se comparará con el hash en este servidor.

Asegúrese de que su contraseña cifrada esté salted . De esa manera, si se roban los datos, será más difícil descifrarlos y las tablas de arco iris serán menos efectivas.

El servidor de servicios de fondo contendrá las contraseñas de texto sin cifrar y solo aceptará conexiones desde su red interna. Cualquier cambio en la contraseña se actualizará aquí primero y luego se actualizará en el servidor front-end.

Asegúrese de escribir reglas de firewall estrictas para este servidor. Solo permita actualizaciones a este servidor, suelte todos otros paquetes.

Este servidor no debería poder acceder desde Internet y probablemente debería ser actualizado por sus servidores locales.

En cuanto a MITM, no hay nada efectivo para prevenir eso.

    
respondido por el ponsfonze 27.07.2012 - 17:34
fuente
0

He visto una configuración en la que las contraseñas se cifraron con rsa en la base de datos de backend junto con sus representaciones de hash y sal. La clave de descifrado se mantuvo en una máquina separada sin internet. Podría recuperar las contraseñas del backend descifrarlas y volverlas a cifrar. El servidor de back-end entonces podría empujar los hashes al servidor de front-end. El servidor frontend fue el único que enfrenta internet.

    
respondido por el Lucas Kauffman 28.07.2012 - 13:30
fuente
0

En primer lugar, NO . Generalmente hay una mejor manera.

Por ejemplo, almacena su contraseña como un hash, y cuando el usuario inicia sesión y se autentica exitosamente contra el hash, mantiene la contraseña en la memoria solo para la sesión, usándola para las conexiones necesarias y luego olvide la contraseña tan pronto como ya no la necesite. Nunca se almacena.

En segundo lugar, si necesita almacenar la contraseña para algún requisito absurdo, una buena manera de hacerla semi-irreversible es usar criptografía de clave pública (por ejemplo, RSA). El cifrado con una clave pública (para la cual no hay una clave privada) no es completamente diferente al hash. No es tan bueno como el hash, pero es mucho mejor que el cifrado simétrico (como blowfish, aes, etc.) porque la contraseña para descifrarlo no está presente. Lo que me recuerda: la clave privada NO DEBE ser accesible desde el entorno público, no en el mismo servidor, no en la misma red, etc. La clave privada solo debe usarse para cualquier emergencia tonta que requiera su diseño.

Pero tenga en cuenta que la criptografía de clave pública que se implementa comúnmente es en realidad criptografía simétrica con un envoltorio RSA. Sepa qué protocolos está utilizando realmente.

    
respondido por el tylerl 30.07.2012 - 11:26
fuente

Lea otras preguntas en las etiquetas