c# - ¿Cómo se "encripta" SecureString y aún se puede usar?
.net security (4)
Cito de un artículo sobre el DPAPI que se utiliza para derivar la clave. Esto debería responder la mayoría de las preguntas que tenga sobre SecureString.
Y sí, SecureString tiene inconvenientes y no es completamente seguro; existen formas de acceder a los datos; por ejemplo, la inclusión de Hawkeye en el proceso se menciona en MSDN como una forma de extraer SecureString. No he verificado personalmente esta afirmación.
Gestión de claves DAPI
DAPI es una técnica de cifrado basada en simétrica, lo que significa que utiliza la misma clave para cifrar y descifrar datos. Antes de llegar a algunos ejemplos de cómo usar DAPI, vale la pena cubrir cómo DAPI administra su clave. En su mayor parte, el proceso de administración de claves DAPI es invisible y, en general, no necesita preocuparse por ello, que es la razón principal por la que DAPI es un buen enfoque.
En la introducción, escribí que la clave maestra se genera a partir de la contraseña de inicio de sesión del usuario. Esta no es la imagen completa. Lo que realmente sucede es que Windows usa la contraseña de inicio de sesión del usuario para generar una clave maestra. Esta clave maestra está protegida con la contraseña del usuario y luego se almacena junto con el perfil del usuario. Esta clave maestra luego se usa para derivar una cantidad de otras claves y son estas otras claves las que se usan para proteger los datos.
La razón por la cual Windows hace esto es porque permite a las aplicaciones agregar información adicional, llamada entropía, al proceso de generación de las claves individuales. Verá si cada aplicación que se ejecuta en la cuenta de inicio de sesión del usuario utiliza la misma clave, entonces cada aplicación podría desproteger los datos protegidos DAPI. En ocasiones, es posible que desee que las aplicaciones puedan compartir datos protegidos con DAPI; Sin embargo, a veces no lo harás. Al permitir que la aplicación contribuya con entropía a la generación de una clave, esa clave se convierte en específica de la aplicación y cualquier dato que esté protegido por esa aplicación solo se puede desproteger nuevamente si conocen la entropía.
Aunque generar una clave maestra y, luego, usar esa clave maestra para generar otras claves para hacer el cifrado real, puede parecer un enfoque largo, tiene una gran ventaja. Dado que hay un nivel adicional de abstracción entre la clave maestra protegida por contraseña del usuario y las claves reales utilizadas para proteger los datos, significa que cuando el usuario cambia su contraseña, solo la clave maestra necesita ser re-protegida; ninguno de los datos protegidos necesita ser re-protegido. Como la clave maestra es mucho más pequeña que los datos, se realiza un importante ahorro de rendimiento.
Cuando la contraseña del usuario cambia, por supuesto, se genera una nueva clave maestra. Esta nueva clave maestra se usa para generar nuevas claves individuales. Sin embargo, dado que todas las claves individuales generadas anteriormente se derivaron de la antigua clave maestra, Windows necesita almacenar todas las claves maestras anteriores, lo que hace. Windows nunca olvida una clave maestra y todos los datos protegidos están marcados con un GUID que indica qué clave maestra se utilizó para proteger los datos. Entonces, en términos de adaptabilidad, DAPI puede hacer frente a los cambios en las contraseñas de los usuarios, al tiempo que garantiza a) que los datos protegidos no necesitan ser re-protegidos, yb) que las claves utilizadas para proteger previamente los datos todavía están disponibles, yc ) hace todo esto automáticamente para ti.
A menos que la computadora sea miembro de un dominio, DAPI solo puede proteger los datos desprotegidos en la misma máquina que se usó para protegerlo.
Además de permitir la protección del nivel de usuario, dado que las claves maestras se basan en contraseñas de usuario y los datos protegidos para un usuario no pueden ser desprotegidos por otro usuario, DAPI también proporciona protección a nivel de máquina, en que las claves maestras se basan en información específica de la máquina. Las claves maestras de nivel de máquina permiten a las aplicaciones almacenar datos protegidos para que puedan ser desprotegidos por todos los usuarios de la aplicación. La única diferencia en el proceso ya descrito es que la clave maestra se genera a partir de información específica de la máquina y no de información específica del usuario.
Según MSDN SecureString contenido se codifica para mayor seguridad, de modo que si el programa se intercambia en el disco, no se puede SecureString contenido de la cadena.
¿Cómo es posible tal encriptación, me pregunto? El algoritmo sería fijo y, por lo tanto, bien conocido o deducible (digamos uno de los siete algoritmos ampliamente utilizados en la industria) y debe haber una clave en algún lugar del programa. Entonces, el atacante podría buscar la cadena encriptada, buscar la clave y descifrar los datos.
¿Cómo puede ser útil tal encriptación?
Como otros ya han respondido, los contenidos de SecureString
se cifran utilizando DPAPI, por lo que las claves no se almacenan en su aplicación, son parte del sistema operativo. No soy 100% positivo, pero supongo que SecureString
utiliza una clave específica del usuario, por lo que incluso si otro proceso obtiene acceso al bloque de memoria, debería ejecutarse con las mismas credenciales para simplemente descifrar el contenido usando el DPAPI. Incluso si no, la clave de la máquina (en teoría) evita que la cadena se descifre fácilmente si se transfiere a otro sistema.
Más importante con SecureString
es cómo y cuándo lo usa. Se debe usar para almacenar datos de cadena que deben conservarse en la memoria durante períodos de tiempo "extendidos", pero que no se necesitan con frecuencia en su forma descifrada. En algún momento, tendrá que descifrarlo en un System.String
antiguo normal o un System.Char[]
. Esto es cuando es más vulnerable en la memoria. Si lo hace con demasiada frecuencia, tiene varias copias de la cadena descifrada flotando en la memoria a la espera de ser recopilada.
Como regla general, si estoy leyendo datos encriptados (por ejemplo, credenciales de inicio de sesión) que debo conservar para uso poco frecuente (interacción PayPal o API de Amazon, por ejemplo), entonces SecureString
/ SecureString
esas credenciales como SecureString
, luego las SecureString
como -necesario solo el tiempo suficiente para realizar las llamadas al servicio web, y garantizar que la vida útil de cualquier copia descifrada sea de solo unas pocas líneas de código.
Probablemente también sea aconsejable usar bloques críticos o similares para indicar al CLR que no debe cambiar de contexto mientras se está utilizando la cadena desencriptada, para mejorar las posibilidades de que se recopilen las copias descifradas antes de que la memoria se guarde en caché o se intercambie.
Por la magia de DPAPI:
Esta clase almacena sus datos utilizando el modelo de memoria protegida API de protección de datos (DPAPI). En otras palabras, los datos siempre están encriptados mientras están almacenados dentro de un SecureString. La clave de encriptación es administrada por el subsistema de autoridad de seguridad local (LSASS.EXE) y, a través de DPAPI, los datos pueden descifrarse a través de la comunicación entre procesos.
Miré un punto en el código y usa el advapi32
de Windows para hacer su trabajo sucio. Entonces, la clave no está almacenada en la memoria de la aplicación.
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static int SystemFunction040([In, Out] SafeBSTRHandle pDataIn, [In] uint cbDataIn, [In] uint dwFlag)
Que es mejor conocido como RtlEncryptMemory.
Se descifra con RtlDecryptMemory
( SystemFunction041
).
Estoy seguro de que el compilador también hace algo con SecurityCriticalAttribute
.
editar esto se reflejó usando 4.0. otras versiones pueden ser diferentes.