¿Cuándo necesitaría una cuerda segura? in.NET?


Estoy tratando de grok el propósito de Secureving.NET. De MSDN:

Una instancia del Sistema.La clase String es inmutable y, cuando ya no se necesita, no se puede programar programáticamente para la recolección de elementos no utilizados; es decir, la instancia es de solo lectura después de creada y no es posible predecir cuándo se eliminará la instancia de la memoria del equipo. En consecuencia, si un objeto String contiene información confidencial como una contraseña, un número de tarjeta de crédito o datos personales, existe el riesgo de que la información pueda ser revelada después de que se utiliza porque su aplicación no puede eliminar los datos de la memoria del ordenador.

Un objeto Secureling es similar a un objeto String en el sentido de que tiene un valor de texto. Sin embargo, el valor de un objeto Secureving se cifra automáticamente, se puede modificar hasta que la aplicación lo marque como de solo lectura y se puede eliminar de la memoria del equipo mediante la aplicación o el recolector de elementos no utilizados de.NET Framework.

El valor de una instancia de Secureling se encripta automáticamente cuando se inicializa la instancia o cuando se modifica el valor. Su aplicación puede hacer que la instancia sea inmutable e impedir nuevas modificaciones invocando el método MakeReadOnly.

Es el cifrado automático la gran recompensa?

Y por qué no puedo simplemente decir:

SecureString password = new SecureString("password");

En lugar de

SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
    pass.AppendChar(c);

¿Qué aspecto de Securevista me estoy perdiendo?

Author: GEOCHET, 2008-09-26

11 answers

Algunas partes del framework que actualmente usan SecureString:

  • El control de WPF System.Windows.Controls.PasswordBox mantiene la contraseña como una cadena de seguridad internamente (expuesta como una copia a través de PasswordBox::SecurePassword)
  • La propiedad System.Diagnostics.ProcessStartInfo::Password es un SecureString
  • El constructor de X509Certificate2 toma un SecureString para la contraseña

El propósito principal es reducir la superficie de ataque, en lugar de eliminarla. SecureStrings están "anclados" en la RAM para que el Recolector de basura no lo mueva ni haga copias de él. También hace seguro que el texto plano no se escribirá en el archivo Swap o en los volcados de núcleo. El cifrado es más como ofuscación y no detendrá a un hacker determinado, que sería capaz de encontrar la clave simétrica utilizada para cifrarla y descifrarla.

Como otros han dicho, la razón por la que tienes que crear un SecureString carácter por carácter es debido al primer defecto obvio de hacer lo contrario: presumiblemente ya tienes el valor secreto como una cadena simple, así que ¿cuál es el punto?

SecureStrings son los el primer paso para resolver un problema de Gallina y Huevo, así que aunque la mayoría de los escenarios actuales requieren convertirlos de nuevo en cadenas regulares para hacer cualquier uso de ellos en absoluto, su existencia en el marco ahora significa un mejor soporte para ellos en el futuro, al menos hasta un punto donde su programa no tiene que ser el eslabón débil.

 104
Author: Chris Wenham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-06 11:37:23

Un montón de grandes respuestas; aquí hay una breve sinopsis de lo que se ha discutido.

Microsoft ha implementado la clase SecureString en un esfuerzo por proporcionar una mejor seguridad con información confidencial (como tarjetas de crédito, contraseñas, etc.).). Proporciona automáticamente:

  • cifrado (en caso de volcados de memoria o página de almacenamiento en caché)
  • fijación en la memoria
  • capacidad de marcar como de solo lectura (para evitar cualquier modificación adicional)
  • construcción segura al NO permitir una cadena constante a pasar en

Actualmente, Secustring es de uso limitado, pero se espera una mejor adopción en el futuro.

Basado en esta información, el constructor de la cadena de seguridad no solo debe tomar una cadena y dividirla en una matriz char, ya que tener la cadena deletreada frustra el propósito de la cadena de seguridad.

Información adicional:

  • A post de la Seguridad. NET blog hablando de lo mismo que cubierto aquí.
  • Y otro uno revisitando y mencionando una herramienta que PUEDE volcar el contenido de la SecureString.

Editar: Me resultó difícil elegir la mejor respuesta, ya que hay buena información en muchos; lástima que no haya opciones de respuesta asistida.

 34
Author: Richard Morgan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 12:29:46

Hay muy pocos escenarios en los que se puede utilizar de forma sensata Secureling en la versión actual del Framework. En realidad, solo es útil para interactuar con API no administradas:puede combinarlo con Marshal.SecureStringToGlobalAllocUnicode.

Tan pronto como lo convierta a/desde un sistema.String, has derrotado su propósito.

El ejemplo de MSDN genera la cadena de seguridad un carácter a la vez desde la entrada de la consola y pasa la cadena segura a una API no administrada. Es bastante complicado y poco realista.

Puede esperar que las futuras versiones de. NET tengan más soporte para Secureling que lo hará más útil, por ejemplo:

  • Consola SecureString.ReadLineSecure () o similar a read console input en una cadena de seguridad sin todo el código enrevesado de la muestra.

  • Reemplazo del cuadro de texto de WinForms que almacena su cuadro de texto.Propiedad Text como cadena segura para que se puedan introducir contraseñas firmemente.

  • Extensiones a las API relacionadas con la seguridad para permitir que las contraseñas se pasen como SecureString.

Sin lo anterior, Secureling tendrá un valor limitado.

 13
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:02:03

Creo que la razón por la que tienes que hacer adición de caracteres en lugar de una instanciación plana es porque en el fondo pasar "contraseña" al constructor de Secureling pone esa cadena "contraseña" en la memoria derrotando el propósito de la cadena segura.

Al añadir solo se está poniendo un carácter a la vez en la memoria que es likley no ser adyacente entre sí físicamente por lo que es mucho más difícil de reconstruir la cadena original. Podría estar equivocado aquí, pero así es como me lo explicaron.

El propósito de la clase es evitar que los datos seguros se expongan a través de un volcado de memoria o una herramienta similar.

 11
Author: JoshReedSchramm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 18:47:52

MS encontró que en ciertas instancias de causar que el servidor (escritorio, lo que sea) se bloquee, hubo momentos en que el entorno de tiempo de ejecución haría un volcado de memoria exponiendo el contenido de lo que está en memoria. Secure String lo cifra en memoria para evitar que el atacante pueda recuperar el contenido de la cadena.

 11
Author: kemiller2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 18:49:13

Respuesta corta

¿Por qué no puedo decir:{[21]]}

SecureString password = new SecureString("password");

Porque ahora tienes password en memoria; sin forma de borrarlo - que es exactamente el punto de Secureling.

Respuesta larga

La razón por la que existe Secustring es porque no puede usar ZeroMemory para borrar datos confidenciales cuando haya terminado con ellos. Existe para resolver un problema que existe porque del CLR.

En un aplicación nativa que llamarías SecureZeroMemory:

Llena un bloque de memoria con ceros.

Nota : SecureZeroMemory es es idéntica a ZeroMemory, excepto que el compilador no lo optimizará.

El problema es que no puede llamar a ZeroMemory o SecureZeroMemory dentro de. NET. Y en. NET las cadenas son inmutables; ni siquiera puede sobrescribir el contenido de la cadena como puede hacer en otros idiomas:

//Wipe out the password
for (int i=0; i<password.Length; i++)
   password[i] = \0;

Entonces, ¿qué puedes hacer? ¿Cómo proporcionamos la capacidad en. NET para borrar una contraseña o un número de tarjeta de crédito de la memoria cuando hemos terminado con ella?

La única forma de hacerlo sería colocar la cadena en algún bloque de memoria nativo, donde puede luego llamar ZeroMemory. Un objeto de memoria nativo como:

  • a BSTR
  • un HGLOBAL
  • CoTaskMem memoria no administrada

SecureString da la habilidad perdida volver

En. NET, las cadenas no se pueden borrar cuando haya terminado con ellas:

  • son inmutables; no se puede sobrescribir su contenido{[69]]}
  • no puedes Dispose de ellos
  • su limpieza está a merced del recolector de basura{[69]]}

Secureling existe como una forma de pasar la seguridad de las cadenas, y ser capaz de garantizar su limpieza cuando sea necesario.

Usted hizo la pregunta:

¿Por qué no puedo simplemente diga:

SecureString password = new SecureString("password");

Porque ahora tienes password en memoria; sin forma de borrarlo. Está atascado allí hasta que el CLR decide reutilizar esa memoria. Nos has puesto justo donde empezamos; una aplicación en ejecución con una contraseña de la que no podemos deshacernos, y donde un volcado de memoria (o Monitor de Proceso) puede ver la contraseña.

Secustring utiliza la API de protección de datos para almacenar la cadena cifrada en la memoria; de esa manera la cadena no existirá en swapfiles, volcados de bloqueo o incluso en la ventana de variables locales con un colega mirando por encima de su deber.

¿Cómo leo la contraseña?

Entonces está la pregunta: ¿cómo interactúo con la cadena? Usted absolutamente no quiere un método como:

String connectionString = secureConnectionString.ToString()

Porque ahora estás de vuelta donde empezaste - una contraseña de la que no puedes deshacerte. Desea forzar a los desarrolladores a manejar la cadena sensible correctamente, de modo que pueda borrarse de la memoria.

Que es por eso que. NET proporciona tres útiles funciones de ayuda para ordenar una cadena de seguridad en una memoria no administrada:

Usted convierte la cadena en un blob de memoria no administrado, manejarlo y luego borrarlo de nuevo.

Algunas API aceptan SecureStrings. Por ejemplo en ADO.net 4.5 el SqlConnection.Credencial toma un conjunto SqlCredential:

SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();

También puede cambiar la contraseña dentro de una cadena de conexión:

SqlConnection.ChangePassword(connectionString, cred, newPassword);

Y hay muchos lugares dentro de. NET donde continúan aceptando una cadena simple para fines de compatibilidad, luego se dan la vuelta rápidamente y la ponen en una cuerda segura.

¿Cómo poner texto en la cadena de seguridad?

Esto todavía deja el problema:

¿Cómo obtengo una contraseña en la cadena de seguridad en primer lugar?

Este es el desafío, pero el punto es hacerte pensar en la seguridad.

A veces la funcionalidad ya se proporciona para usted. Por ejemplo, el control WPF PasswordBox puede devolver la contraseña introducida como Secureling directamente:

PasswordBox.SecurePassword Propiedad

Obtiene la contraseña actualmente retenida por el PasswordBoxcomo un Secureling.

Esto es útil porque en todas partes donde solía pasar una cadena raw, ahora tiene el sistema de tipos quejándose de que Secureling es incompatible con String. Desea ir el mayor tiempo posible antes de tener que convertir su Secureling de nuevo en cadena regular.

La conversión de una cadena de seguridad es bastante fácil:

  • SecureStringToBSTR
  • PtrToStringBSTR

Como en:

private static string CreateString(SecureString secureString)
{
    IntPtr intPtr = IntPtr.Zero;
    if (secureString == null || secureString.Length == 0)
    {
        return string.Empty;
    }
    string result;
    try
    {
        intPtr = Marshal.SecureStringToBSTR(secureString);
        result = Marshal.PtrToStringBSTR(intPtr);
    }
    finally
    {
        if (intPtr != IntPtr.Zero)
        {
            Marshal.ZeroFreeBSTR(intPtr);
        }
    }
    return result;
}

Realmente no quieren que lo hagas.

Pero, ¿cómo consigo una cadena en una Secureling? Bueno, lo que necesita hacer es dejar de tener una contraseña en una cadena en primer lugar. Necesitabas tenerlo en algo más. Incluso una matriz Char[] sería útil.

Ahí es cuando puedes añadir cada carácter y borra el texto plano cuando hayas terminado:

for (int i=0; i < PasswordArray.Length; i++)
{
   password.AppendChar(PasswordArray[i]);
   PasswordArray[i] = (Char)0;
}

Necesita que su contraseña se almacene en alguna memoria que pueda borrar. Cárgalo en la cuerda segura desde allí.


Tl;dr: SecureString existe para proporcionar el equivalente de ZeroMemory.

Algunas personas no ven el punto en borrar la contraseña del usuario de la memoria cuando un dispositivo está bloqueado, o borrar borrar las pulsaciones de teclas de la memoria después de ellos son autenticados . Esas personas no utilice SecureString.

 11
Author: Ian Boyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-16 21:35:10

Bueno, como indica la descripción, el valor se almacena cifrado, lo que significa que un volcado de memoria de su proceso no revelará el valor de la cadena (sin un trabajo bastante serio).

La razón por la que no puedes simplemente construir una cadena de seguridad a partir de una cadena constante es porque entonces tendría una versión sin cifrar de la cadena en la memoria. Limitarlo a crear la cadena en piezas reduce el riesgo de tener toda la cadena en memoria a la vez.

 4
Author: Mark Bessey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 18:51:33

Uno de los grandes beneficios de una secuencia de seguridad es que se supone que evita la posibilidad de que sus datos se almacenen en el disco debido al almacenamiento en caché de páginas. Si tiene una contraseña en memoria y luego carga un programa o conjunto de datos grande, su contraseña puede escribirse en el archivo de intercambio a medida que su programa se agota de memoria. Con una secuencia de seguridad, al menos los datos no estarán sentados indefinidamente en su disco en texto claro.

 4
Author: Jason Z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 18:55:32

Supongo que es porque la cadena está destinada a ser segura, es decir, un hacker no debería ser capaz de leerla. Si inicializa con una cadena, el hacker podría leer la cadena original.

 3
Author: OregonGhost,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 18:46:09

Dejaría de usar Secureving . Parece que los PG están dejando de apoyarlo. Posiblemente incluso tirarlo en el futuro - https://github.com/dotnet/apireviews/tree/master/2015-07-14-securestring .

Deberíamos eliminar el cifrado de Secureling en todas las plataformas en. NET Core - Deberíamos obsoleto Secureling-Probablemente no deberíamos exponer secureling en. NET Core

 3
Author: Joe Healy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-21 00:12:10

Otro caso de uso es cuando está trabajando con aplicaciones de pago (POS) y simplemente no puede usar estructuras de datos inmutables para almacenar datos confidenciales porque es un desarrollador cuidadoso. Por ejemplo: si voy a almacenar datos sensibles de la tarjeta o metadatos de autorización en una cadena inmutable, siempre se dará el caso de que estos datos estarán disponibles en la memoria durante una cantidad significativa de tiempo después de que se descartaron. No puedo simplemente sobrescribirlo. Otra gran ventaja donde estos datos confidenciales se guardan en memoria cifrada.

 1
Author: Halibut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-31 03:30:57