带有 XMLSerialization 的明文密码
Cleartext Password with XMLSerialization
我正在使用 XML 与第三方 Web 服务通信。一切正常,除了我们的安全扫描器报告了一些 CWE-216 缺陷。
密码确实存储在内存中 LoginDetails
class 类似于下面(为了示例而简化)
[Serializable()]
public class LoginDetails
{
public string Login { get; set; }
public string Password { get; set; }
}
第三方要求以明文形式发送密码。所以不幸的是,我在这里的问题上别无选择。我想做的是确保该字段安全存储and/or 在使用后尽快从内存中删除。
在补救方面,我尝试同时使用 SecureString
- 出于显而易见的原因 - 并使用 StringBuilder
因为这否定了不变性。我还尝试在 LoginDetails
class 上实现 IDisposable
。这包括将两个属性设置为空。然后我引发了各种讨论 (particularly this one),指出它并没有真正带来多大好处。
问题是,当将 Password
字段类型更改为 SecureString
或 StringBuilder
时 - 它们未正确序列化 - 因此第三方请求失败。有什么办法可以覆盖 XMLSerializer
以不同方式处理这些类型 - 因此它们在我们这边的内存中存储得更安全,但以明文形式传输给第三方 - 或者整个尝试毫无意义是因为双方都不会实施这些安全尝试?
或者有什么我完全忽略的吗?
非常感谢
为了解决这个问题,我创建了一个名为 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);
}
}
序列化发生在 WriteXml
函数中 IXmlSerializable
的实现中。它使用WriteString
写出私有字符串的值属性(Value)...
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Value);
}
为了处理 SecureString 值,我在 IDisposable
模式中实现了 Dispose
方法并调用了 Content.Dispose()
用法
我可以创建一个 LoginDetails
class 的实例(如问题中引用的那样)...
LoginDetails loginDetails = new LoginDetails
{
Login = "MyUsername",
Password = new SerializableSecureString(WebConfigurationManager.AppSettings["MyPassword"])
};
密码存储在 web.config 文件的加密部分 - 因此使用 WebConfigurationManager
.
使用后,可以像下面这样在finally
块中处理数据
finally
{
LoginDetails.Password.Dispose();
}
我正在使用 XML 与第三方 Web 服务通信。一切正常,除了我们的安全扫描器报告了一些 CWE-216 缺陷。
密码确实存储在内存中 LoginDetails
class 类似于下面(为了示例而简化)
[Serializable()]
public class LoginDetails
{
public string Login { get; set; }
public string Password { get; set; }
}
第三方要求以明文形式发送密码。所以不幸的是,我在这里的问题上别无选择。我想做的是确保该字段安全存储and/or 在使用后尽快从内存中删除。
在补救方面,我尝试同时使用 SecureString
- 出于显而易见的原因 - 并使用 StringBuilder
因为这否定了不变性。我还尝试在 LoginDetails
class 上实现 IDisposable
。这包括将两个属性设置为空。然后我引发了各种讨论 (particularly this one),指出它并没有真正带来多大好处。
问题是,当将 Password
字段类型更改为 SecureString
或 StringBuilder
时 - 它们未正确序列化 - 因此第三方请求失败。有什么办法可以覆盖 XMLSerializer
以不同方式处理这些类型 - 因此它们在我们这边的内存中存储得更安全,但以明文形式传输给第三方 - 或者整个尝试毫无意义是因为双方都不会实施这些安全尝试?
或者有什么我完全忽略的吗?
非常感谢
为了解决这个问题,我创建了一个名为 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);
}
}
序列化发生在 WriteXml
函数中 IXmlSerializable
的实现中。它使用WriteString
写出私有字符串的值属性(Value)...
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Value);
}
为了处理 SecureString 值,我在 IDisposable
模式中实现了 Dispose
方法并调用了 Content.Dispose()
用法
我可以创建一个 LoginDetails
class 的实例(如问题中引用的那样)...
LoginDetails loginDetails = new LoginDetails
{
Login = "MyUsername",
Password = new SerializableSecureString(WebConfigurationManager.AppSettings["MyPassword"])
};
密码存储在 web.config 文件的加密部分 - 因此使用 WebConfigurationManager
.
使用后,可以像下面这样在finally
块中处理数据
finally
{
LoginDetails.Password.Dispose();
}