Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to protect strings without SecureString?

The use case is to protect strings in memory programming in c#. The use of the class SecureString (https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?view=netframework-4.7.2) is discouraged by Microsoft itself.

I was wondering if it could be a valid alternative to:

  • transform the string in a byte array and immediately set the string to null (and eventually call the garbage collector),
  • encrypt the byte array with the class ProtectedMemory.

Any suggestion?

like image 802
Francesca Merighi Avatar asked Apr 09 '19 10:04

Francesca Merighi


3 Answers

There is no alternative to the SecureString class. The 'alternative' Microsoft encourages is found here:

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.

So, if you really need the credentials and there is no other way: on .NET Framework, use SecureString. For .NET Core there is no alternative at the moment.

like image 91
Patrick Hofman Avatar answered Nov 14 '22 23:11

Patrick Hofman


I wouldn't say it's "discouraged by Microsoft" - that's an oversimplification. The actual reasons are given in this page ( https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md ) and the argument seems to be "it isn't worth the effort to use it in .NET Core", and not that it isn't secure overall.

I contend that SecureString is secure... but only for the .NET Framework on Windows. The page I linked to is from the .NET Core project which is cross-platform - so it makes sense to discourage or disallow the use of SecureString in .NET Core - but if your project is targeting .NET Framework (which is exclusive to Windows) or is targeting .NET Core for Windows - then you're fine. The quote is below (emphasis mine):

The contents of the array is unencrypted except on .NET Framework.

BTW, SecureString can be used securely to avoid cleartext in memory if you only read secrets directly into the SecureString directly by using its Append method. This is most useful when reading passwords from the console (pseudocode):

Console.WriteLine( "Enter your password" );
SecureString password = new SecureString();
while( Char c = Console.ReadKey() != '[Enter'] ) {
    password.Append( c );
}

...however if you need access to the cleartext version of the string afterwards then it's less secure (though the cleartext string would hopefully be collected by GC as a Generation 0 object).

Regarding your proposal:

  • transform the string in a byte array and immediately set the string to null (and eventually call the garbage collector)
  • encrypt the byte array with the class ProtectedMemory.

This is exactly how SecureString works already, and it still suffers from the same problems: the cleartext copy of the encrypted contents still exists in memory for a short period of time - that's the problem.

like image 26
Dai Avatar answered Nov 14 '22 23:11

Dai


So the basic question you are asking is "since Microsoft discourages the user of SecureString, can I roll my own?".

Well, apart from the fact that your implementation will likely be less secure than Microsoft's original version, it will also at least share the same problems, because they are not with the specific implementation, but with the concept.

If you want to use the concept, you could as well use SecureString. The solution is to not use the concept of encrypted credentials in memory, neither with Microsoft's classes, nor with your own homebrew.

like image 33
nvoigt Avatar answered Nov 14 '22 23:11

nvoigt