c# securestring to string
Clear C#String de la memoria (4)
Además de la respuesta estándar "Estás entrando en territorio inseguro", que espero que se explique, considera lo siguiente:
El CLR no garantiza que solo haya una instancia de una cadena en un punto dado, y no garantiza que las cadenas serán basura. Si tuviera que hacer lo siguiente:
var input = "somestring";
input += "sensitive info";
//do something with input
clearString(input, false);
¿Cuál es el resultado de esto? (Supongamos que no estoy usando literales de cadena, y estos son en cambio entradas de algún tipo de entorno)
Se crea una cadena con el contenido de "somestring". Se crea otra cadena con contenido de "información confidencial" y se crea otra cadena con contenido de "información somestringsensitive". Solo se borra la última cadena: "información confidencial" no lo está. Puede o no ser recolectada inmediatamente.
Incluso si tiene cuidado de asegurarse de que siempre borre cualquier cadena con información confidencial, la CLR aún no garantiza que exista una sola instancia de una cadena.
editar: Con respecto a su edición, simplemente fijar la cadena de inmediato puede tener el efecto deseado, sin necesidad de copiar la cadena a otra ubicación ni a nada. Debe hacerlo inmediatamente después de recibir dicha cadena, y todavía hay otros problemas de seguridad de los que preocuparse. No puede garantizar que, por ejemplo, la fuente de la cadena no tenga una copia en la memoria ITS, sin entender claramente la fuente y cómo exactamente hace las cosas.
Tampoco podrás mutar esta cuerda por razones obvias (a menos que la cuerda mutada sea exactamente del mismo tamaño que la cuerda), y debes tener mucho cuidado de que nada de lo que estás haciendo pueda pisotear la memoria que no es parte de esa cadena.
Además, si pasa a otras funciones que no escribió usted mismo, puede que esa función la copie o no.
Estoy tratando de borrar el contenido de la memoria de una cadena C # por razones de seguridad. Soy consciente de la clase SecureString
, pero desafortunadamente no puedo usar SecureString
lugar de String
en mi aplicación. Las cadenas que deben borrarse se crean dinámicamente en tiempo de ejecución (p. Ej., No estoy tratando de borrar literales de cadena).
La mayoría de los resultados de búsqueda que encontré básicamente establecían que no es posible borrar el contenido de una String
(ya que la cadena es inmutable) y se debe usar SecureString
.
Por lo tanto, presenté mi propia solución (usando código inseguro) a continuación. Las pruebas muestran que las soluciones funcionan, pero todavía no estoy seguro de si hay algún problema con la solución. ¿Hay mejores?
static unsafe bool clearString(string s, bool clearInternedString=false)
{
if (clearInternedString || string.IsInterned(s) == null)
{
fixed (char* c = s)
{
for (int i = 0; i < s.Length; i++)
c[i] = ''/0'';
}
return true;
}
return false;
}
EDITAR: Debido a los comentarios en el GC moviendo la cadena antes de clearString
: ¿qué pasa con el siguiente fragmento?
string s = new string(''/0'', len);
fixed (char* c = s)
{
// copy data from secure location to s
c[0] = ...;
c[1] = ...;
...
// do stuff with the string
// clear the string
for (int i = 0; i < s.Length; i++)
c[i] = ''/0'';
}
Es imposible decir cuántas funciones CLR y no CLR atraviesa su cuerda antes de que llegue a su función donde está tratando de despejarla. Estas funciones (administradas y no administradas) pueden crear copias de la cadena por varias razones (posiblemente múltiples copias).
No es posible que conozca todos estos lugares y los borre de manera tan realista que no puede garantizar que su contraseña se elimine de la memoria. Debería usar SecureString
en SecureString
lugar, pero debe comprender que lo anterior sigue siendo válido: en algún punto de su programa recibirá la contraseña y tendrá que tenerla en la memoria (incluso si solo es de corta duración mientras se muda en una cuerda segura). Esto significa que su cadena aún pasará por cadenas de llamadas a función que usted no controla.
Tu problema con esto es que las cadenas se pueden mover. Si el GC se ejecuta, puede mover el contenido a una nueva ubicación, pero no pondrá a cero el anterior. Si cerró la cadena en cero, no tiene garantía de que no exista una copia en otra parte de la memoria.
Aquí hay un enlace al .NET Garbage Collector, y habla de compactación.
EDITAR: aquí está tu problema con la actualización:
// do stuff with the string
El problema es que una vez que deja su control, pierde la capacidad de asegurarse de que sea seguro. Si estuviera completamente bajo tu control, entonces no tendrías la limitación de usar solo un tipo de cadena. En pocas palabras, este problema ha existido durante mucho tiempo, y nadie ha encontrado una forma segura de manejar esto. Si desea mantenerlo seguro, lo mejor es manejarlo por otros medios. La eliminación de la cadena está destinada a evitar que alguien pueda encontrarla a través de un volcado de memoria. La mejor manera de detener esto si no puede usar una cadena segura es limitar el acceso a la máquina en la que se está ejecutando el código.
Si realmente no puede usar SecureString
y está dispuesto a escribir un código inseguro, entonces podría escribir su propia clase de cadena simple que utiliza memoria no administrada y asegura que toda la memoria se ponga a cero antes de la desasignación.
Sin embargo, nunca puede asegurarse de que sus datos estén seguros, ya que nunca tiene control total sobre ellos. Por ejemplo, un virus incrustado lo suficientemente profundo podría leer esa memoria mientras el programa se está ejecutando, y también existe la posibilidad de que el proceso finalice, en cuyo caso el código del destructor no se ejecutará, dejando los datos en la memoria no asignada, lo que podría ser asignado a otro proceso, y aún contendría inicialmente sus datos confidenciales; alguien podría usar fácilmente una herramienta como Visual Studio para monitorear la memoria de un proceso depurado, o escribir un programa que asigna memoria y busca datos confidenciales.