在ASP.NET中使用SecureString有什么好处吗?

时间:2010-12-16 17:52:43

标签: c# asp.net securestring

如果我理解正确,这是为了保持纯文本内存不足,以便应用程序可以安全地防止对内存,垃圾堆或内存分页到磁盘的深奥攻击。 SecureString被提供非托管字节,并在时间消耗一个非托管字节 - 然后字符串从内存中删除。 (如果我离开,请纠正我!)

在ASP.NET中,秘密收集在webform中,后者以HTTPS格式发回。但是,然后Request对象将表单中的所有请求值转换为名称值对,并将它们放入集合中,例如,请求[“TxtPassword”] - 所以即使在我得到字符串之前,它已经被不安全地写入内存。更糟糕的是,如果我使用的是控件,那么不安全的表示将在TextBox的属性中拥有更多的托管字符串。

要对此SecureString执行任何操作,我需要一个采用非托管字符串的API - 因此我似乎无法使用安全字符串来存储proc参数或其他内容。

我这样做是错误的还是尝试使用SecureString并且不将不安全字符串的副本泄漏到托管内存中这是一个愚蠢的错误?

切换到OAuth或Windows身份验证不是一种选择。

5 个答案:

答案 0 :(得分:24)

正如您正确推断的那样,以及其他人已经提到的,使用SecureString来存储来自ASP.NET表单的安全敏感数据是没有意义的,因为该数据已经以明文形式存在于内存中

然而,还有其他情况,建议使用SecureString,因为敏感数据是由程序本身创建的,并且在完成后不应保留在内存中。例如,以编程方式创建SharePoint站点,或将身份验证凭据从一个系统传输到另一个系统。

回到过去的好时光,更容易确保敏感数据的生命周期尽可能短。它可以在堆栈上分配,并在程序完成后立即清除:

char secret[512];
generate_secret(secret, sizeof(secret));
do_something_with(secret);
memset(secret, 0, sizeof(secret));
// Secret data is now gone.

管理字符串无法实现这种方法,主要是因为:

  • 他们没有分配到堆栈上,
  • 他们是不可改变的,所以他们不能被清除,
  • 它们不是一次性的,所以无法保证GC释放数据的时间。它甚至可能永远不会被释放,具体取决于内存条件。

SecureString尝试通过可变和一次性来解决这个问题,这允许人们写:

using (SecureString secret = new SecureString()) {
    GenerateSecret(secret);
    secret.MakeReadOnly();
    DoSomethingWith(secret);
}
// Secret data is now gone.

答案 1 :(得分:7)

SecureString最适用于为系统之间的直接呼叫分配网络凭据。在网络领域中,如果凭证通过网络进入明文某处,但是如果您必须通过标准凭证调用(ftp,目录服务等)将该凭证发回,那么使用SecureString就可以了没有伤害作为传球方法。虽然您的文本字符串已经在纯文本服务器系统中是正确的,但您至少可以减少系统之间的占用空间。如果您只在本地使用此密码,那么我同意SecureString可能不是非常必要。

良好的安全习惯从来都不是浪费时间。

答案 2 :(得分:6)

我认为你有它的基础知识。 SecureString是从客户端的角度设计的。所以对于一个WPF / Winforms应用程序(也许是Silverlight,不记得它是否在那里),对于服务器端应用程序来说,它是值得的,而不是由于不是第一个处理该字符串。

答案 3 :(得分:2)

我执行安全代码审核时唯一标记SecureString缺失用法的情况是,数据可能会被应用程序加密并重复使用。

例如,当网站后端需要与第三方或需要凭据的其他内部资源进行通信时。由于无法对这些进行哈希处理,因此我需要在构建请求时使用SecureString(也应该通过TLS)。

另一种方法是尽可能使用Windows Data Protection API

请注意SecureString的目的是将内容保留在内存中尽可能短的时间。

答案 4 :(得分:-1)

如果我没有弄错,你可以使用以下解决方案来保持输入CLR的字符串管理: Web API: how to access multipart form values when using MultipartMemoryStreamProvider?

只能将ExecutePostProcessingAsync(..)方法中的FormData作为ReadAsByteArrayAsync()读取,并且它永远不会成为字符串。

您仍然需要https来确保输入安全。