views:

2223

answers:

9

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?

+3  A: 

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.

OregonGhost
+6  A: 

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.

JoshReedSchramm
+4  A: 

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.

Kevin
+5  A: 

I'm curious about the purpose of this too. Although the idea of a "secure" string class is a good one, in order to do anything (at all) with this string, you have to cast it to a regular old System.String. Likewise, when you're about to insert some text value into the secure string (something deserialized from a file or input from a user), it's a System.String that you create the SecureString from.

This seems like the illusion of data protection, rather than actual protection.

DannySmurf
It's not really whether your string is protected or not, it's the amount of protection your string has. If it's stored in memory, it's never 100% safe, but SecureString takes some steps to make this information more difficult to access.That said, you're right in that most routines require a System.String, not a SecureString. I wrote a SecureStringToStringMarshaler class to make this process *safer*.http://stackoverflow.com/questions/1800695/c-securestring-question/3567531#3567531
Doug
+2  A: 

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.

Mark Bessey
If they are limiting the construction from a constant string, then the line foreach (char c in "password".ToCharArray()) would defeat that, no? It should be pass.AppendChar('p'); pass.AppendChar('a');etc?
Richard Morgan
Yes, you can easily enough throw away what little protection SecureString gives you. They're trying to make it hard to completely shoot yourself in the foot. Obviously there has to be some way to get the value into and out of a SecureString, or you couldn't use it for anything.
Mark Bessey
+2  A: 

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.

Jason Z
+2  A: 

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.

Joe
+21  A: 

Some parts of the framework that currently use SecureString:

  • WPF's PasswordBox control keeps the password as a SecureString internally.
  • System.Diagnostics.ProcessInfo's Password property is a SecureString.
  • The constructor for X509Certificate2 takes a SecureString for the password.

The main purpose is to reduce the attack surface, rather than eliminate it. SecureStrings are "pinned" in RAM so the Garbage Collector doesn't move it around or make copies of it. It also 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, 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.

C. Lawrence Wenham
I ran across it looking at ProcessStartInfo's Password property; not even paying attention to the type, I just set it to a regular string until the compiler barked at me.
Richard Morgan
It wont be easy to find the symmetric encryption key, since SecureString is based on DPAPI, which doesnt exactly store a key in plaintext...
AviD
Also, it's not so much the chicken-and-egg problem, since it's not a replacement for encryption in storage - but its a workaround for immutable, managed .NET strings.
AviD
+10  A: 

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.

Richard Morgan