I'm communicating with a Third-Party Web Service using XML. Everything is working fine, except that our Security scanner is reporting a few CWE-216 flaws.
The password is indeed stored in memory within a LoginDetails
class similar to below (Simplified for examples sake)
[Serializable()]
public class LoginDetails
{
public string Login { get; set; }
public string Password { get; set; }
}
The third-party requires the password to be sent in clear-text. So unfortunately I have no choice in the matter here. What I want to do is ensure that the field is stored securely and/or removed from memory as soon as possible when it has been used.
In terms of remediation I have attempted the use of both SecureString
-for obvious reasons- and using StringBuilder
as this negates the immutability. I have also tried to implement IDisposable
on the LoginDetails
class. This consisted of setting the two properties to null. I was then lead to various discussions (particularly this one) stating that it's not really of much benefit.
The problem is, when changing the Password
fields type to SecureString
or StringBuilder
- They aren't serialized correctly - and therefore the request fails at the third-party. Is there any way I can override the XMLSerializer
to process these types differently - so they are stored somewhat more securely in memory on our side, but transmitted in clear-text to the third-party - Or is the whole attempt pointless on the basis that these attempts at security won't be implemented on both sides?
Alternatively is there anything I have completely overlooked?
Many Thanks
To get around this I created a custom type named SerializableSecureString
implementing both IXmlSerializable
and IDisposable
.
Hope the following helps someone out in the future!
Implementation
The type contains a private SecureString
member variable, and a private string
property which is used for the serialization.
private readonly SecureString Content = new SecureString();
private string Value { }
The get
for the private string property unwraps the private member variable as follows...
get
{
IntPtr bstr = Marshal.SecureStringToBSTR(Content);
string copiedText = Marshal.PtrToStringAuto(bstr);
Marshal.ZeroFreeBSTR(bstr);
return copiedText;
}
There are two constructors. An empty constructor used solely by .Net for Serialization...
public SerializableSecureString()
{
}
...and another for actual construction of the type. It takes a cleartext string and packages it up into the SecureString variable like so...
public SerializableSecureString(string clearText)
{
if (clearText != null)
{
foreach (char t in clearText)
Content.AppendChar(t);
}
}
The serialization happens in the implementation of IXmlSerializable
in the WriteXml
function. It uses WriteString
to write out the value of the private string property (Value)...
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Value);
}
To dispose the SecureString value, I implemented the Dispose
method within the IDisposable
pattern and called Content.Dispose()
Usage
I can create an instance of the LoginDetails
class (as quoted in the question) as follows...
LoginDetails loginDetails = new LoginDetails
{
Login = "MyUsername",
Password = new SerializableSecureString(WebConfigurationManager.AppSettings["MyPassword"])
};
The password is stored in an encrypted section of the web.config file - hence the use of WebConfigurationManager
.
After use, the data can be disposed within a finally
block like the following
finally
{
LoginDetails.Password.Dispose();
}