c# .net wpf security passwordvault

c# - Seguridad de PasswordVault cuando se usa desde la aplicación de escritorio



.net wpf (4)

(Esto es de lo que puedo entender de tu post)

No hay una manera real de evitar el acceso a los datos entre las aplicaciones de escritorio cuando se utiliza este tipo de API http://www.hanselman.com/blog/SavingAndRetrievingBrowserAndOtherPasswords.aspx le brinda más información. Probablemente solo querrá descifrar su información.

la restricción de acceso a la memoria es difícil, el código ejecutado por el usuario siempre es recuperable por el usuario, por lo que sería difícil restringirlo.

¿Ha considerado usar la API de protección de datos de Windows? DPAPI

DPAPI es un servicio fácil de usar que beneficiará a los desarrolladores que deben brindar protección a los datos confidenciales de la aplicación, como contraseñas y claves privadas.

WDPAPI usa claves generadas por el sistema operativo y Triple DES para cifrar / descifrar sus datos. Lo que significa que su aplicación no tiene que generar estas claves, lo que siempre es bueno.

También puede usar la clase Rfc2898DeriveBytes, esto utiliza un generador de números pseudoaleatorios para descifrar su contraseña. Es más seguro que la mayoría de los descifradores, ya que no hay una forma práctica de volver del resultado a la contraseña. Esto solo es realmente útil para verificar la contraseña de entrada y no recuperarla nuevamente. En realidad, nunca lo he usado para que no pueda ayudarte.

https://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes(v=vs.110).aspx

Véase también este post que da una explicación mucho mejor que yo. ¿Cómo guardar de forma segura el nombre de usuario / contraseña (local)?

Si malinterpreté la pregunta de alguna manera, dígame, intentaré actualizar la respuesta.

TENGA EN CUENTA que las aplicaciones modernas / metro no tienen este problema, aunque aún son accesibles de otras maneras.

Me gustaría usar Windows.Security.Credentials.PasswordVault en mi aplicación de escritorio (basada en WPF) para almacenar de forma segura la contraseña de un usuario. Logré acceder a esta API de Windows 10 utilizando este artículo de MSDN .

Hice algunos experimentos y parece que los datos escritos en PasswordVault desde una aplicación de escritorio (no una aplicación nativa de UWP) se pueden leer desde cualquier otra aplicación de escritorio. Incluso empaquetar mi aplicación de escritorio con la tecnología Desktop Bridge y, por lo tanto, tener una identidad de paquete no soluciona esta vulnerabilidad.

¿Alguna idea de cómo solucionarlo y poder almacenar los datos de la aplicación de forma segura desde otras aplicaciones?

ACTUALIZACIÓN: Parece que PasswordVault no agrega seguridad adicional sobre DPAPI . El caso se cierra con un resultado negativo.


La única alternativa es cifrar la contraseña con su propia clave privada almacenada en algún lugar de su código. (Alguien puede desmontar fácilmente su código y obtener la clave) y luego almacenar la contraseña encriptada dentro de PasswordVault, sin embargo, la única seguridad que tiene es que cualquier aplicación no tendrá acceso a la contraseña.

Esta es la seguridad dual, en caso de máquinas comprometidas, el atacante puede obtener acceso a PasswordVault pero no a su contraseña, ya que necesitarán una clave privada más para descifrar la contraseña y se ocultará en algún lugar de su código.

Para hacerlo más seguro, si deja su clave privada en su servidor y expone una API para cifrar y descifrar la contraseña antes de guardarla en Vault, la hará más segura. Creo que esta es la razón por la que la gente ha pasado a OAuth (almacenamiento del token de OAuth en PasswordVault), etc. en lugar de almacenar la contraseña en la bóveda.

Idealmente, recomendaría no almacenar la contraseña, en vez de eso, obtenga un token del servidor y guárdelo y use ese token para la autenticación. Y almacenar ese token en PasswordVault.


La dura verdad es que almacenar una contraseña en una aplicación de escritorio, 100% segura, simplemente no es posible. Sin embargo , puedes acercarte al 100%.

Con respecto a su enfoque original , PasswordVault utiliza el servicio de Bloqueo de credenciales que está integrado en Windows para almacenar datos de forma segura. Credential Locker está vinculado al perfil del usuario. Por lo tanto, almacenar sus datos a través de PasswordVault es esencialmente equivalente al enfoque de la contraseña maestra para proteger los datos, de lo que hablo en detalle más adelante. La única diferencia es que la contraseña maestra en ese caso son las credenciales del usuario. Esto permite que las aplicaciones que se ejecutan durante la sesión del usuario accedan a los datos.

Nota: Para ser claro, estoy hablando estrictamente de almacenarlo de una manera que le permita acceder al texto plano. Es decir, almacenarlo en una base de datos cifrada de cualquier tipo, o cifrarlo usted mismo y almacenar el texto cifrado en algún lugar. Este tipo de funcionalidad es necesaria en programas como los administradores de contraseñas, pero no en programas que solo requieren algún tipo de autenticación. Si esto no es una necesidad, entonces recomiendo encarecidamente el hash de la contraseña, idealmente según las instrucciones establecidas en this respuesta por zaph . (Un poco más de información en this excelente post de Thomas Pornin ).

Si es una necesidad, las cosas se complican un poco más: si desea evitar que otros programas (o los usuarios supongo) puedan ver la contraseña de texto simple, entonces su única opción real es cifrarla. El almacenamiento del texto cifrado dentro de PasswordVault es opcional ya que, si utiliza un buen cifrado, su único punto débil es que alguien descubra su clave. Por lo tanto, el propio texto cifrado se puede almacenar en cualquier lugar. Eso nos lleva a la clave misma.

Según la cantidad de contraseñas que realmente intenta almacenar para cada instancia de programa, es posible que no tenga que preocuparse por generar y almacenar de forma segura una clave. Si desea almacenar varias contraseñas, simplemente puede pedirle al usuario que ingrese una contraseña maestra , realice un análisis de sal, y utilice el resultado como clave de cifrado para todas las demás contraseñas. Cuando sea tiempo de descifrar, pídale al usuario que lo ingrese nuevamente. Si está almacenando varias contraseñas, le recomiendo encarecidamente que utilice este enfoque. Es el enfoque más seguro posible . Sin embargo, para el resto de mi publicación, asumiré que esta no es una opción viable.

En primer lugar, le insto a no tener la misma clave para cada instalación. Cree uno nuevo para cada instancia de su programa, basado en datos aleatorios generados de forma segura. Resista la tentación de "evitar tener que almacenar la clave" haciendo que se genere sobre la marcha cada vez que sea necesario, en función de la información sobre el sistema. Eso es tan seguro como la string superSecretKey = "12345"; en su programa. Los atacantes no tardarán mucho en descubrir el proceso.

Ahora, almacenarlo es la parte realmente difícil. Una regla general de infosec es la siguiente:

Nada es seguro una vez que tienes acceso físico

Así que, idealmente, nadie lo haría. El almacenamiento de las claves de cifrado en un servidor remoto con la seguridad adecuada minimiza las posibilidades de que los atacantes las recuperen. Se han escrito libros completos con respecto a la seguridad del lado del servidor, por lo que no discutiré esto aquí.

Otra buena opción es usar un HSM ( Módulo de seguridad de hardware ). Estos pequeños dispositivos ingeniosos están diseñados para el trabajo. Acceder a las claves almacenadas en un HSM es prácticamente imposible. Sin embargo, esta opción solo es viable si está seguro de que cada computadora de usuario tiene una de estas, como en un entorno empresarial.

.Net proporciona una solución de tipo, a través del sistema de configuración. Puede almacenar su clave en una sección encriptada de su app.config . Esto se usa a menudo para proteger cadenas de conexión. Hay muchos recursos disponibles sobre cómo hacer esto. Recomiendo this fantástica publicación de blog, que le dirá la mayor parte de lo que necesita saber.

La razón por la que dije antes de no ir simplemente generando la clave sobre la marcha es porque, como almacenarlo como una variable en su código, confía exclusivamente en la ofuscación para mantenerlo seguro. Lo que pasa con este enfoque es que generalmente no lo hace . Sin embargo, a veces no tienes otra opción. Introduzca la criptografía de caja blanca .

La criptografía de caja blanca es esencialmente una ofuscación llevada al extremo. Está destinado a ser efectivo incluso en un escenario de caja blanca, donde el atacante tiene acceso y puede modificar el bytecode. Es el epítome de la seguridad a través de la oscuridad. A diferencia de la mera ocultación constante (infosec habla para el enfoque de la string superSecretKey ) o la generación de la clave cuando se necesita, la criptografía de caja blanca se basa esencialmente en generar el cifrado en la marcha.

Se han escrito papers completos en él. Es difícil llevar a cabo una implementación adecuada, y su millaje puede variar. Solo debes considerar esto si realmente realmente quieres hacer esto de la manera más segura posible.

La ofuscación sin embargo sigue siendo ofuscación. Todo lo que realmente puede hacer es frenar a los atacantes. La solución final que tengo para ofrecer puede parecer al revés, pero funciona: no oculte la clave de cifrado digitalmente. Escóndelo físicamente . Haga que el usuario inserte una unidad USB cuando sea el momento del cifrado, (de forma segura) genere una clave aleatoria, luego escríbala en la unidad USB. Luego, cada vez que es hora de descifrar, el usuario solo tiene que volver a colocar la unidad, y el programa lee la clave.

Esto es un poco similar al enfoque de contraseña maestra, ya que se lo deja al usuario para mantener la clave segura. Sin embargo, tiene algunas ventajas notables. Por ejemplo, este enfoque permite una clave de cifrado masiva . Una clave que puede caber en un simple archivo de 1 megabyte puede demorar literalmente miles de millones de años en romperse mediante un ataque de fuerza bruta. Además, si alguna vez se descubre la clave, el usuario solo tiene la culpa.

En resumen , vea si puede evitar tener que almacenar una clave de cifrado. Si no puede, evite almacenarlo localmente a toda costa. De lo contrario, su única opción es hacer que sea tan difícil para los hackers resolverlo como sea posible. No importa cómo decida hacer eso, asegúrese de que cada clave sea diferente, por lo que incluso si los atacantes encuentran una, las claves de los otros usuarios están a salvo.


Siempre es posible impulsar la seguridad, con varias estrategias de encriptación y almacenamiento. Hacer algo más difícil solo hace que la recuperación de datos sea más larga, nunca imposible. Por lo tanto, debe considerar el nivel de protección más adecuado considerando el costo de ejecución x tiempo (humano y máquina) y el costo de desarrollo x tiempo.

Si considero estrictamente su solicitud , simplemente agregaría una capa (clase, interfaz) para cifrar sus contraseñas. Mejor con encriptación asimétrica (y no RSA). Suponiendo que los otros softs no estén accediendo a los datos de su programa (programa, archivos O proceso), esto es suficiente. Puede usar SSH.NET ( https://github.com/sshnet/SSH.NET ) para lograr esto rápidamente.

Si desea impulsar la seguridad y otorgar un cierto nivel de protección contra la ingeniería inversa binaria (incluida la recuperación de claves privadas), recomiendo una máquina virtual cifrada pequeña (limitada al proceso) (como Docker, https://blogs.msdn.microsoft.com/mvpawardprogram/2015/12/15/getting-started-with-net-and-docker/ ) solución basada en Denuvo ( https://www.denuvo.com/ ). El cifrado es único por cliente y por máquina. Tendrá que encapsular su programa c # en un programa ac / c ++ (que actúa como un contenedor) que hará todo el cifrado-descifrado en memoria.

Puede implementar su propia estrategia, dependiendo del tipo de inversión y garantía que requiera.

En caso de que su programa sea un programa backend, puede elegir la mejor estrategia (la única que realmente recomiendo) de lo que es almacenar la clave privada en el lado del cliente, la clave pública en el backend y tener descifrado local, todas las contraseñas transmitidas por lo tanto estar encriptados. Me gustaría señalar que la contraseña y las claves son en realidad estrategias diferentes para lograr el mismo objetivo: verificar si el programa habla con la persona correcta sin conocer la identidad de la persona; Me refiero a esto: en lugar de almacenar contraseñas, mejor almacenar directamente las claves públicas.