A few times over the last couple of days discussion about a tool on the Internet which can attach to your process and dump out the contents of your SecureStrings has come up. If this tool can exist, then what benefit does SecureString really provide?
The fact that this tool can exist is not a hole in the SecureString feature. Presumably at some point you’ll want to be able to access the data you’re storing in your string (after all, if you didn’t want to ever access that data again, why store it in the first place?). If you’re going to want to access it, then the process that did the encryption on the string data will need a way to decrypt the data again. So it’s not a failure that code in your process can decrypt the SecureString contents, it’s by design. (Note that to access the Marshal APIs which do decrypt the string, you need to be have SecurityPermission/UnmanagedCode — or essentially be fully trusted. This means that arbitrary partial trust code in your process cannot in fact access the plaintext contents of your string).
Back in my original post about SecureString I mentioned several problems with storing sensitive data, such as a password in a standard System.String. SecureString solves these problems. Namely:
- The string is not stored in the managed heap while standard strings are. This means that a string can be moved around by the GC, leaving multiple copies of the sensitive data in memory. Your code will not know that this has happened, and even if it could figure out that the string was moved, you have no way to clear out the other copies. Instead you have to wait for the CLR to allocate another object where the sensitive data is so that the memory gets erased.
- SecureStrings are stored in an encrypted form. While they will have to be decrypted during the periods of time that they are used, this period can be kept as small as possible. If your process is swapped out to disk while the string is encrypted, the plaintext will not end up in the swap file.
- The keys used to encrypt the string are tied to the user, logon session, and process. This means that any minidumps taken of the process will contain secure strings which are not decryptable. If Watson sends dumps off to Microsoft or if you have to have a client send you a minidump of a crashing application, they can rest assured that you cannot access the sensitive data in the strings.
- SecureStrings are securely zeroed out when they’re disposed of. System.Strings are immutable and cannot be cleared when you’ve finished with the sensitive data.
While the SecureString class does not prevent fully trusted code which is running in your process from decrypting the contents of the string and doing whatever it wants to do with it, it does provide several other features. It’s all about risk management — keeping the sensitive data as inaccessible as possible when it’s not being used, and being able to erase your records of it when it is no longer needed.