2
votes

The System.Data.SqlClient.SqlCredential class has a two argument constructor which accepts a username (System.String) and password (System.Security.SecureString).

After calling this constructor, is it safe to dispose the SecureString storing the password? I expect that the SqlCredential class should perform a one-way hash on the password according to the SQL server authentication scheme and not require continued access to the parameter... but perhaps this cannot be done until the connection is opened and a challenge is issued (a nonce may be involved in the HMAC calculation to prevent replay attacks). If SqlCredential does independently keep the needed information, then naturally I want to expedite erasure of the SecureString storage which is reversible.

I have been unable to find any statement in the documentation specifying whether the password SecureString object passed in must remain valid after the SqlCredential constructor returns.

1
in ref to github src github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/… it's assigned to a private field after checking whether it is set to ReadOnly. From docs.microsoft.com/en-us/dotnet/api/… there is an indication to immutable behavior after it is made readonly. But it would be nice to gain some insight and clarity on this. - Brett Caswell
actually.. I may have misinterpreted the doc on the premise of immutability in respect to create new instances. In fact, I think the doc indicates it will not create new instances - therefore you probably should not dispose it and expect an instance of SqlCredentials to independently work... probably can confirm this with a quick test either way - Brett Caswell
@BrettCaswell: Oh I definitely do cause an ObjectDisposedException if I dispose the password. But I don't think that is how it should work. SecureString is supposed to be disposed when no longer needed, and if I can't dispose it (because I share an instance with SqlCredential) and SqlCredential can't dispose it (because it shares with me) then the sensitive data is going to stay around until the garbage collector decides to invoke the finalizer which finally zeroes it out. - Ben Voigt
probably another reason why it's recommended to not use it. and also to avoid credentials. github.com/dotnet/platform-compat/blob/master/docs/… .. but, I think you can provide an answer to this question with the observation of that exception being raised after disposing. It seems to be in line with docs as it relates to SecureString having a single instance. - Brett Caswell

1 Answers

1
votes

SqlCredential doesn't actually process or store any password-derived data; it's just a convenience structure to hold the credential-related parameters associated with an SqlConnection.

The password SecureString instance needs to stay valid until the call to SqlConnection.Open() or that function will throw an ObjectDisposedException. If like mine, your application has any automatic reconnection logic, you'll need to keep the SecureString (or the ability to recreate it) indefinitely. At least on the .NET Framework with Win32, SecureString keeps its contents encrypted when at rest, so a process memory dump won't expose the secret.