Safe use of SecureString for login form

KeithS picture KeithS · Jan 22, 2013 · Viewed 12.6k times · Source

So there's this class that seems very seldom used: SecureString. It's been around since 2.0 at least, and there are a few SO questions on it, but I thought I'd ask my own specific questions:

I have a LoginForm; simple WinForms dialog with username and (masked) password fields. When the user enters both and clicks "Login", the information is passed to an injected authentication class that does a layer of key-stretching, then hashes half of the stretched key for verification while the other half is the symmetric key for the encrypted user account data. When all this is through, the loginForm is closed, the authenticator class disposed, and the system moves on to loading the main form. Pretty standard stuff, maybe a little more involved than the standard hash-the-password-and-compare, but the simple hashed password would be defeated in my case by storing the user data in plaintext, because that data includes credentials for a third-party system (and we all know how people like to reuse passwords).

Here's the first question; how would I use SecureString to retrieve the password from the Password textbox, without it being exposed as an ordinary System.String through the Text property of the textbox? I assume there's a way to access the unmanaged GDI window for the Textbox that's being wrapped by the CLR classes, and pull the text data in using the Marshal class. I just don't know how, and I can't seem to find good information.

Here's the second question; once I have the password as a SecureString, how do I pass it to a hash provider from the System.Security.Crypto namespace? My guess is that I'd use Marshal.SecureStringToBSTR(), then Marshal.Copy() from the returned IntPtr back into a byte array. I can then call Marshal.ZeroBSTR() to clean up the unmanaged memory and I can zero out the managed array with Array.Clear() once I have the hash. If there's a cleaner way that allows me full control over the lifetime of any managed copy of the memory, do tell.

Third question; Is all this really necessary, or is the inherent insecurity of System.String in a managed-memory environment a little overblown? Anything used to store the password, encrypted or otherwise, should be out of scope and on its way to the garbage collector long before the OS would consider swapping the app into virtual memory (allowing the password to be sniffed from the swap-file after a hard shutdown of the computer). A cold-boot attack is a theoretical possibility, but really, how common is this? The bigger concern is the now-decrypted user data, which hangs around as part of the user for the entire application lifetime (and thus would be a prime candidate for using SecureStrings, as except for a couple of basic usages they stay pretty dormant).

Answer

usr picture usr · Jan 22, 2013

If you believe that you need SecureString you must believe that an attacker can read your process memory, too. If the latter is true he can read the password characters as they are typed, or read from the textbox internal character buffer directly, or read pixels off the screen.

This is an unrealistic scenario. Don't use SecureString. It helps little and steals your time.

Cold boot attacks are more real, yet extremely uncommon. They require physical machine access which usually totally owns the machine. Reading by the attacker is the least of your concerns in this case.

Basically, you have to contrive a case where your developer time is well spent using SecureString.