1

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

Community
  • 1
  • 1
grimdog_john
  • 675
  • 1
  • 7
  • 15
  • What do you mean by they aren't serialised correctly? – NMGod May 10 '17 at 12:49
  • Let me rephrase that bit. I'm assuming they are serialized "correctly" as according to their types. SecureString isn't serializable (understandable), whereas StringBuilder serializes as xxxx. What I need is something that holds secure (or more secure than what I have now) until the I use XMLSerializer - at which point the cleartext value of the Password property is transmitted to the Third-Party. – grimdog_john May 10 '17 at 13:56
  • Scratch that just remmeber StringBuilder is Non-Inherit. – NMGod May 10 '17 at 14:10
  • 1
    I guess you could write a wrapper class for the StringBuilder with a property bound to .ToString() just through ideas around, been a while since I dealt with this, don't remember how I solved it. – NMGod May 10 '17 at 14:28

1 Answers1

0

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();
}
grimdog_john
  • 675
  • 1
  • 7
  • 15