Search code examples
c#xmlserializationasmx

Cleartext Password with XMLSerialization


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


Solution

  • 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();
    }