When would I need a SecureString in .NET?

Viewed 43782

I'm trying to grok the purpose of .NET's SecureString. From MSDN:

An instance of the System.String class is both immutable and, when no longer needed, cannot be programmatically scheduled for garbage collection; that is, the instance is read-only after it is created and it is not possible to predict when the instance will be deleted from computer memory. Consequently, if a String object contains sensitive information such as a password, credit card number, or personal data, there is a risk the information could be revealed after it is used because your application cannot delete the data from computer memory.

A SecureString object is similar to a String object in that it has a text value. However, the value of a SecureString object is automatically encrypted, can be modified until your application marks it as read-only, and can be deleted from computer memory by either your application or the .NET Framework garbage collector.

The value of an instance of SecureString is automatically encrypted when the instance is initialized or when the value is modified. Your application can render the instance immutable and prevent further modification by invoking the MakeReadOnly method.

Is the automatic encryption the big payoff?

And why can't I just say:

SecureString password = new SecureString("password");

instead of

SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
    pass.AppendChar(c);

What aspect of SecureString am I missing?

11 Answers

Some parts of the framework that currently use SecureString:

The main purpose is to reduce the attack surface, rather than eliminate it. SecureStrings are "pinned" in RAM so the Garbage Collector won't move it around or make copies of it. It also makes sure the plain text won't get written to the Swap file or in core dumps. The encryption is more like obfuscation and won't stop a determined hacker, though, who would be able to find the symmetric key used to encrypt and decrypt it.

As others have said, the reason you have to create a SecureString character-by-character is because of the first obvious flaw of doing otherwise: you presumably have the secret value as a plain string already, so what's the point?

SecureStrings are the first step in solving a Chicken-and-Egg problem, so even though most current scenarios require converting them back into regular strings to make any use of them at all, their existence in the framework now means better support for them in the future - at least to a point where your program doesn't have to be the weak link.

Edit: Don't use SecureString

Current guidance now says the class should not be used. The details can be found at this link: https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md

From the article:

DE0001: SecureString shouldn't be used

Motivation

  • The purpose of SecureString is to avoid having secrets stored in the process memory as plain text.
  • However, even on Windows, SecureString doesn't exist as an OS concept.
    • It just makes the window getting the plain text shorter; it doesn't fully prevent it as .NET still has to convert the string to a plain text representation.
    • The benefit is that the plain text representation doesn't hang around as an instance of System.String -- the lifetime of the native buffer is shorter.
  • The contents of the array is unencrypted except on .NET Framework.
    • In .NET Framework, the contents of the internal char array is encrypted. .NET doesn't support encryption in all environments, either due to missing APIs or key management issues.

Recommendation

Don't use SecureString for new code. When porting code to .NET Core, consider that the contents of the array are not encrypted in memory.

The general approach of dealing with credentials is to avoid them and instead rely on other means to authenticate, such as certificates or Windows authentication.

End Edit : Original Summary below

Lots of great answers; here’s a quick synopsis of what has been discussed.

Microsoft has implemented the SecureString class in an effort to provide better security with sensitive information (like credit cards, passwords, etc.). It automatically provides:

  • encryption (in case of memory dumps or page caching)
  • pinning in memory
  • ability to mark as read-only (to prevent any further modifications)
  • safe construction by NOT allowing a constant string to be passed in

Currently, SecureString is limited in use but expect better adoption in the future.

Based on this information, the constructor of the SecureString should not just take a string and slice it up to char array as having the string spelled out defeats the purpose of SecureString.

Additional info:

  • A post from the .NET Security blog talking about much the same as covered here.
  • And another one revisiting it and mentioning a tool that CAN dump the contents of the SecureString.

Edit: I found it tough to pick the best answer as there's good information in many; too bad there is no assisted answer options.

There are very few scenarios where you can sensibly use SecureString in the current version of the Framework. It's really only useful for interacting with unmanaged APIs - you can marshal it using Marshal.SecureStringToGlobalAllocUnicode.

As soon as you convert it to/from a System.String, you've defeated its purpose.

The MSDN sample generates the SecureString a character at a time from console input and passes the secure string to an unmanaged API. It's rather convoluted and unrealistic.

You might expect future versions of .NET to have more support for SecureString that will make it more useful, e.g.:

  • SecureString Console.ReadLineSecure() or similar to read console input into a SecureString without all the convoluted code in the sample.

  • WinForms TextBox replacement that stores its TextBox.Text property as a secure string so that passwords can be entered securely.

  • Extensions to security-related APIs to allow passwords to be passed as SecureString.

Without the above, SecureString will be of limited value.

I believe the reason why you have to do character appending instead of one flat instantiation is because in the background passing "password" to the constructor of SecureString puts that "password" string in memory defeating the purpose of secure string.

By appending you are only putting a character at a time into memory which is likley not to be adjacent to each other physically making it much harder to reconstruct the original string. I could be wrong here but that's how it was explained to me.

The purpose of the class is to prevent secure data from being exposed via a memory dump or similar tool.

MS found that on certain instances of causing the server (desktop, whatever) to crash there were times when the runtime environment would do a memory dump exposing the contents of what's in memory. Secure String encrypts it in memory to prevent the attacker from being able to retrieve the contents of the string.

One of the big benefits of a SecureString is that it is supposed avoid the possibility of your data being stored to disk due to page caching. If you have a password in memory and then load a large program or data set, your password may get written to the swap file as your program is paged out of memory. With a SecureString, at least the data will not be sitting around indefinitely on your disk in clear text.

I guess it's because the string is meant to be secure, i.e. a hacker should not be able to read it. If you initialize it with a string, the hacker could read the original string.

Well, as the description states, the value is stored encrypted, with means that a memory dump of your process won't reveal the string's value (without some fairly serious work).

The reason you can't just construct a SecureString from a constant string is because then you would have an unencrypted version of the string in memory. Limiting you to creating the string in pieces reduces the risk of having the whole string in memory at once.

Another use case is when you are working with payment applications (POS) and you simply can't use immutable data structures in order to store sensitive data because you are careful developer. For instance: if I will store sensitive card data or authorisation metadata into immutable string there always would be the case when this data will be available in memory for significant amount of time after it was discarded. I cannot simply overwrite it. Another huge advantage where such sensitive data being kept in memory encrypted.

Related