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?

schroeder
  • 123,438
  • 55
  • 284
  • 319
Jeff
  • 373
  • 3
  • 6

2 Answers2

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.
eis
  • 105
  • 5
Vivelin
  • 530
  • 3
  • 8
  • 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. –  Aug 19 '19 at 11:11
  • @MechMK1 That is mentioned in the other answer already, I just wanted to add the official recommendation, too. – Vivelin Aug 19 '19 at 11:18
  • The quoted part says nothing about recommending against using SecureString. Could you please quote (or bold) the relevant parts. – Andrew Savinykh Aug 19 '19 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 '19 at 04:45
  • @AndrewSavinykh I assume because it's a huge pain to work with, and in the end it has to end up in plaintext anyways, so there is little use to it –  Aug 20 '19 at 10:11
  • 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](https://stackoverflow.com/a/25751722/480982) to decode the password. – Thomas Weller Aug 20 '19 at 21:18
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.

Sjoerd
  • 28,707
  • 12
  • 74
  • 102
  • 9
    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 '19 at 16:10
  • What's the thing about liquid nitrogen? – IEatBagels Aug 22 '19 at 15:52
  • In a [cold boot attack](https://en.wikipedia.org/wiki/Cold_boot_attack#Technical_details), 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 '19 at 19:18