我正在使用XML与第三方Web服务进行通信。一切正常,但我们的安全扫描程序报告了一些CWE-216缺陷。
密码确实存储在类似于下面的LoginDetails
类的内存中(为简单起见,简化)
[Serializable()]
public class LoginDetails
{
public string Login { get; set; }
public string Password { get; set; }
}
第三方要求以明文形式发送密码。所以不幸的是我在这里没有选择。我想要做的是确保字段在使用时尽快安全存储和/或从内存中删除。
在补救方面,我尝试使用SecureString
- 显而易见的原因 - 并使用StringBuilder
因为这会抵消不变性。我还尝试在IDisposable
课程上实施LoginDetails
。这包括将两个属性设置为null。然后我开始进行各种讨论(particularly this one),说它并没有太大的好处。
问题是,将Password
字段类型更改为SecureString
或StringBuilder
时 - 它们未正确序列化 - 因此请求在第三方失败。有没有什么方法可以覆盖XMLSerializer
以不同的方式处理这些类型 - 所以它们在我们这方面更安全地存储在内存中,但是以明文形式传送给第三方 - 或者整个尝试是无意义的基于这些安全尝试不会在双方实施?
或者有什么我完全忽略了吗?
非常感谢
答案 0 :(得分:0)
为了解决这个问题,我创建了一个名为SerializableSecureString
的自定义类型,同时实现IXmlSerializable
和IDisposable
。
希望以后可以帮助某人出去!
<强>实施强>
该类型包含私有SecureString
成员变量,以及用于序列化的私有string
属性。
private readonly SecureString Content = new SecureString();
private string Value { }
私有字符串属性的get
解包私有成员变量,如下所示...
get
{
IntPtr bstr = Marshal.SecureStringToBSTR(Content);
string copiedText = Marshal.PtrToStringAuto(bstr);
Marshal.ZeroFreeBSTR(bstr);
return copiedText;
}
有两个构造函数。一个空构造函数,仅由.Net用于序列化...
public SerializableSecureString()
{
}
...和另一个用于实际构造的类型。它需要一个明文字符串并将其打包到SecureString变量中,如此...
public SerializableSecureString(string clearText)
{
if (clearText != null)
{
foreach (char t in clearText)
Content.AppendChar(t);
}
}
序列化发生在IXmlSerializable
函数中WriteXml
的实现中。它使用WriteString
写出私有字符串属性(值)...
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Value);
}
要处置SecureString值,我在Dispose
模式中实现了IDisposable
方法并调用了Content.Dispose()
<强>用法强>
我可以创建一个LoginDetails
类的实例(在问题中引用),如下所示......
LoginDetails loginDetails = new LoginDetails
{
Login = "MyUsername",
Password = new SerializableSecureString(WebConfigurationManager.AppSettings["MyPassword"])
};
密码存储在web.config文件的加密部分中 - 因此使用WebConfigurationManager
。
使用后,数据可以放在finally
块中,如下所示
finally
{
LoginDetails.Password.Dispose();
}