Si está codificando, muchos idiomas "no administrados" admiten (requieren) la capacidad de eliminar la memoria asignada dinámicamente. Si desea estar realmente seguro, generalmente también puede establecer el valor de dicha memoria en todos los ceros, o en algo que no sea útil para un atacante (datos aleatorios, "Todo funciona y no se reproduce ...", etc.).
En los tiempos de ejecución de memoria administrada, como JVM o CLR, no tiene este control; el recolector de basura comprueba si el código en ejecución todavía tiene alguna referencia al objeto, y si no, lo programa para su recolección. El proceso de marcado, y la liberación de memoria y la reorganización del montón resultantes, ocurren cuando el tiempo de ejecución considera que podría ser un buen momento para limpiar, no cuando se sabe que algo debe limpiarse. En estos entornos, generalmente hay una estructura provista específicamente para manejar datos confidenciales.
En .NET, el tipo primario para estas cosas se llama SecureString , y tiene varias ventajas sobre el System.String básico:
- SecureString es mutable, a diferencia de String que, aunque es un tipo de referencia, se trata como inmutable; Cada vez que se asigna una variable de cadena, se crea un nuevo objeto de cadena en el montón, lo que significa que cuando se trabaja con datos confidenciales, pueden existir muchas copias diferentes de dichos datos en el montón a la vez. SecureString maneja todas las manipulaciones de sí mismo dentro de un solo espacio de memoria en el montón.
- Los datos que se guardan en SecureString están cifrados en todo momento, por lo que incluso si se los deja tirados, el atacante también necesitará acceso al contenedor de claves almacenado en la memoria no administrada protegida.
-
El objeto se deriva de una familia de clases básica que lo identifica como que tiene un "finalizador crítico"; Mientras el CLR tenga voz en la materia, el finalizador, que en el caso de SecureString elimina todos los datos confidenciales de la memoria, se ejecutará cuando el objeto salga de su alcance.
-
El usuario puede borrar de forma síncrona el estado de los datos de SecureString llamando a Clear (). Esto también sucede si el usuario utiliza la interfaz IDisposable incorporada, o si el usuario no la limpia, cuando el recolector de basura finaliza el objeto, pero se recomienda al usuario que use Borrar () o Eliminar () para limpiar memoria exactamente en el momento en que el usuario está seguro de que no la volverá a necesitar.
En todos los casos, los datos confidenciales deben mantenerse como texto sin formato en la memoria por el menor tiempo posible menos antes de la eliminación. Si se puede mantener cifrado la mayor parte del tiempo, y solo se puede descifrar en texto plano cuando sea necesario (como lo permite SecureString), eso es genial.