27

I am creating a .NET core webapp in C# that takes in a user password and hashes it to be stored on a server. I'm using Rfc2898DeriveBytes along with a randomly generated salt. I've read, however, that I should avoid using strings in the entire process since strings cannot be removed from memory. I know that .NET core has a PasswordBox that keeps the password as a SecureString, but SecureStrings cannot be converted to a byte array to be passed to Rfc2898DeriveBytes's constructor without a great deal of shenanigans.

Since the webapp is only going to run on my server, can I just convert the SecureString back to a string as soon as it has been passed into my webapp? If an attacker manages to access the server's RAM to search for an undeleted string, there's probably very little I can do to protect anything to begin with.

If I should still go through with using SecureStrings, what are the best practices for hashing it to be stored?

2 Answers 2

33

Using SecureString correctly is difficult, and protects against a threat surface that is unlikely for most use cases. As you say, if an attacker can read your memory, you have other problems. I would advise to use normal strings instead of SecureString, unless you are worried by attackers carrying liquid nitrogen with physical access to your server.

If you really want to use SecureStrings, you should P/Invoke the Windows crypto API so that you have control over memory. I have an example in my blog post Comparing secure strings in .NET.

3
  • 10
    No liquid nitrogen needed: there software (Heartbleed) vulnerabilities that allow reading parts of RAM, and hardware vulnerabilities like Spectre can be exploited in a cloud environment. But I agree that it's rather unlikely and not something most web apps should be concerned with.
    – aland
    Aug 20, 2019 at 16:10
  • What's the thing about liquid nitrogen?
    – IEatBagels
    Aug 22, 2019 at 15:52
  • 1
    In a cold boot attack, memory can be cooled with liquid nitrogen so that data persists while moving the DRAM modules to another computer to read the data.
    – Sjoerd
    Aug 22, 2019 at 19:18
48

The .NET Core team specifically recommends against using SecureString for new development. See the SecureString documentation:

We don't recommend that you use the SecureString class for new development. For more information, see SecureString shouldn't be used on GitHub.

as well as the team's reasoning on GitHub:

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.
6
  • 2
    Very interesting, great first answer! It should be noted that process memory in general is only really an attack surface if an attacker is able to get access to it - something that is generally not part of the threat model of a web application, unless on a shared host.
    – user163495
    Aug 19, 2019 at 11:11
  • @MechMK1 That is mentioned in the other answer already, I just wanted to add the official recommendation, too.
    – Vivelin
    Aug 19, 2019 at 11:18
  • The quoted part says nothing about recommending against using SecureString. Could you please quote (or bold) the relevant parts. Aug 19, 2019 at 19:33
  • 2
    @AndrewSavinykh It's in the first link and doesn't really say more than that they don't recommend it for new development and contains a link to the quoted part.
    – Vivelin
    Aug 20, 2019 at 4:45
  • 1
    Maybe because you can ask the debugger (WinDbg + SOS) or profiler for objects of type SecureString, which makes password discovery even easier than using regular strings. With some IL injection, it's a one-liner to decode the password. Aug 20, 2019 at 21:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .