Coder Perfect

Is SecureString ever useful in a C# program?

Problem

Please tell me if my assumptions are incorrect, but first allow me to explain why I’m asking.

A SecureString: a SecureString: a SecureString: a SecureString: a SecureString: a

I see; it makes perfect sense to store a password or other sensitive data in a SecureString rather than a System. Because it’s a System, you can control how and when it’s actually kept in memory. String:

In the case of a GUI program (such as an ssh client), however, the SecureString must be constructed from a System.String. The fundamental data type for all text controls is string.

So, even if employing a password mask, this means that every time the user hits a key, the old string is deleted and a new string is produced to reflect the data inside the text box. And we have no way of knowing when or if any of those values will be erased from memory.

It’s now time to connect to the server. What’s more, guess what? For authentication, you must send a string over the connection. So, let’s make a System out of our SecureString. We now have a string on the heap with no mechanism to make it go through garbage collection (or write 0s to its buffer).

My point is that, no matter what you do, that SecureString will eventually be transformed into a System. String, implying that it will appear on the heap at some point (without any guarantee of garbage collection).

My point isn’t whether or not there are techniques to avoid delivering a string to an ssh connection or having a control keep a string (make a custom control). Replace “ssh connection” with “login form,” “registration form,” “payment form,” “foods-you-would-feed-your-puppy-but-not-your-children form,” and so on in this question.

Sorry if I’m bombarding you with questions; my curiosity has gotten the best of me. Please feel free to respond to any or all of my inquiries (or tell me that my assumptions are completely wrong). 🙂

Asked by Steven Jeffries

Solution #1

SecureString has a lot of practical applications.

Do you have any idea how many times I’ve witnessed circumstances like this? (The answer is a resounding yes!)

Are you aware of how to avoid all of these issues? SecureString. It normally ensures that you do not make any dumb errors. What does it do to avert it? By ensuring that the password is encrypted in unmanaged memory and that the real value can only be read when you’re 90 percent confident you’re doing the right thing.

SecureString is simple to use in this regard:

1) Everything is protected by encryption.

2) AppendChar is called by the user.

3) In UNMANAGED MEMORY, decrypt everything and add the character.

4) Encrypt everything in UNMANAGED MEMORY once more.

What if the user has physical access to your machine? Is it possible for a virus to gain access to all SecureStrings? Yes. All you have to do is hook into RtlEncryptMemory while the memory is being decrypted, and you’ll be able to read the location of the unencrypted memory address. Voila! In fact, you could create a virus that constantly scans for SecureString usage and logs all activity associated with it. I’m not suggesting it’ll be simple, but it’ll be possible. As you can see, once you have a user/virus on your system, SecureString’s “power” is completely gone.

In your post, you make a few points. Sure, utilizing genuine SecureString isn’t that useful if you use any of the UI features that save a “string password” inside. Even so, it can shield you against some of the above-mentioned folly.

WPF also offers PasswordBox, which uses SecureString internally through its SecurePassword field, as others have pointed out.

The bottom line is to use SecureString if you have sensitive data (passwords, credit cards, etc.). This is what the C# Framework does. The NetworkCredential class, for example, stores passwords as SecureString. You may notice over 80 different SecureString usages in the.NET framework if you look at this.

Many times, you’ll need to convert SecureString to string because an API requires it.

The most common issue is one of the following:

What happens when SecureString is converted to a string, as you mentioned? This is only possible due to the first point. For example, the API is unaware that it is dealing with sensitive information. That hasn’t happened in my experience. It’s not easy to extract a string from SecureString.

It’s not simple for a simple reason: it was never meant for the user to be able to convert SecureString to string, as you stated: GC will kick in. If you catch yourself doing anything like that, take a step back and ask yourself, “Why am I doing this?” or “Do I really need this?”

I came into an intriguing case. Because the WinApi method LogonUser accepts LPTSTR as a password, you must use SecureStringToGlobalAllocUnicode. This effectively provides you with an unencrypted password that is stored in unmanaged memory. As soon as you’re finished, get rid of that:

// Marshal the SecureString to unmanaged memory.
IntPtr rawPassword = Marshal.SecureStringToGlobalAllocUnicode(password);
try
{
   //...snip...
}
finally 
{
   // Zero-out and free the unmanaged string reference.
   Marshal.ZeroFreeGlobalAllocUnicode(rawPassword);
}

You may always add an extension method to the SecureString class, such as ToEncryptedString( SERVER PUBLIC KEY), which returns a string instance of SecureString encrypted with the server’s public key. The only person who can decrypt it is the server. The issue has been resolved: Because you never expose the “original” string in controlled memory, Garbage Collection will never see it. PSRemotingCryptoHelper (EncryptSecureStringCore(SecureString secureString)) is doing just that.

Mono SecureString, on the other hand, does not encrypt anything at all. Because…wait for it…the implementation has been commented out. “It causes nunit test failure in some way,” which gets me to my final point:

SecureString isn’t available everywhere. You’ll get an exception if the platform/architecture doesn’t support SecureString. The documentation includes a list of platforms that are supported.

Answered by Erti-Chris Eelmaa

Solution #2

Your assumptions have a few flaws.

To begin with, the SecureString class lacks a String constructor. To make one, first allocate an object, then append the characters.

You may easily send each pushed key to a secure string in the case of a GUI or a console.

The class is designed in such a way that you cannot access the saved value by accident. This implies you won’t be able to use the string as a password directly.

So, for example, if you want to use it to authenticate over the web, you’ll need to use secure classes.

There are a few classes in the.NET framework that you can use. SecureString

(more)

To summarize, the SecureString class is handy, but it necessitates more developer attention.

All of this is thoroughly detailed, with examples, in the SecureString article on MSDN.

Answered by Damian Leszczyński – Vash

Solution #3

If you want to use a SecureString, you should:

You’ve defeated its purpose if you ever convert it to a managed string.

ADDITIONAL INFORMATION IN RESPONSE TO A COMMENT

The unmanaged component that consumes the BSTR can zero the memory after it has been transformed to a BSTR. Memory that is not controlled is more secure since it can be reset in this manner.

SecureString is supported by a small number of APIs in the.NET Framework, so you’re true that it’s of limited utility today.

The most common application I can think of is in a client application where the user must enter a highly sensitive code or password. The user input may be utilized to generate a SecureString character per character, then provided to an unmanaged API that zeroes the BSTR it receives after use. The sensitive string will not be present in any subsequent memory dump.

That’s difficult to see how it would be useful in a server application.

UPDATE 2

This constructor for the X509Certificate class is an example of a.NET API that accepts a SecureString. If you use ILSpy or something similar, you’ll notice that the SecureString is internally transformed to an unmanaged buffer (Marshal.SecureStringToGlobalAllocUnicode), which is then zeroed once you’re done with it (Marshal.ZeroFreeGlobalAllocUnicode).

Answered by Joe

Solution #4

SecureString is not recommended for newer scripts, according to Microsoft.

From the SecureString Class documentation:

Which recommends:

Answered by SᴇM

Solution #5

SecureString, as you properly pointed out, has one distinct advantage over string: deterministic erasure. This fact is problematic in two ways:

So, when is it OK to utilize it? Only when you’re working with something that allows you to use SecureString for all of your purposes, and even then, keep in mind that this is only secure in certain situations.

Answered by Theodoros Chatzigiannakis

Post is based on https://stackoverflow.com/questions/26190938/is-securestring-ever-practical-in-a-c-sharp-application