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

46

如果我理解正确,这是为了避免将纯文本存储在内存中,从而使应用程序免受针对内存、垃圾堆或分页到磁盘的奇特攻击,SecureString接收非托管字节并以一个非托管字节的方式消耗-然后将字符串从内存中擦除。(如果我理解错了,请纠正我!)

在ASP.NET中,密钥在Web表单中进行收集,然后通过HTTPS进行提交。但是,请求对象将表单中的所有请求值转换为名称-值对,并将它们放入一个集合中,例如Request["TxtPassword"]-因此,在我获取字符串之前,它已经被不安全地写入了内存。更糟糕的是,如果我在使用控件,则文本框的属性中将包含更多托管字符串的不安全表示。

要对此SecureString执行任何操作,我需要一个接受非托管字符串的API-因此,似乎我无法将SecureString用于存储过程参数或其他大部分操作。

我是做错了什么,还是试图使用SecureString而不将未安全的字符串副本泄漏到托管内存中是愚蠢的行为?

切换到OAuth或Windows身份验证不是选项。


我也有这个问题,我在考虑使用Ajax将一个字符一次发送到服务器。不过我还没有完成我的概念验证。 - devlord
5个回答

29

正如您正确推断的,并且其他人已经提到的,使用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.

你说“这没有多大意义”。在读取用户密码的情况下,难道不应该是“这毫无意义”吗?因为在asp.net中它没有达到其目的。SecureString声称可以防止信息泄露。但是在asp.net中它是否100%防止了信息泄露?我的问题在这里[http://stackoverflow.com/questions/23775907/is-securestring-in-net-really-useful-for-web-application?noredirect=1#comment36565085_23775907]被标记为重复,但我不明白。你能帮我理解一下吗? - Ashif Nataliya
1
@Akie,你可能在术语上读得太多了。“没有意义”已经够严厉的了,我使用了一个更温和的替代方案,但重点是一样的:如果安全敏感的数据来自于ASP.NET表单,使用SecureString来保护它不会带给你任何好处(或者用更 - Frédéric Hamidi
胡说八道。 - Matt Borja

7
SecureString最好用于为系统之间的直接调用分配网络凭证。在Web领域中,如果凭证是通过Web传输的,则可以肯定地说它在某个地方以明文形式存在,但是如果您必须通过标准的凭证调用(ftp、目录服务等)发送该凭证,则使用SecureString作为传递方法不会有任何损失。虽然您正确地指出字符串已经以纯文本形式存在于服务器系统中,但是您至少可以减少系统之间的占用空间。如果您只在本地使用此密码,则我同意SecureString可能并不是非常必要。
然而,良好的安全习惯从来都不是浪费时间。

6

我认为你已经掌握了基础知识。SecureString是从客户端的角度设计的。因此,对于WPF/Winforms应用程序(也许Silverlight中也有,我记不清了),它非常有价值。但对于服务器端应用程序来说,它的价值就不那么大了,因为它不是第一个处理字符串的。


2

我在进行安全代码审查时,唯一会标记缺少使用SecureString的情况是,当应用程序可能加密并重复使用数据时。

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

另一种选择是尽可能使用Windows Data Protection API

请注意,SecureString的目的是尽可能短地保留内存中的内容。


-1

1
问题不在于该值是一个字符串,而在于它以未加密的形式存储在内存中,因此内存转储将公开字节数组和字符串。由于假想的攻击者将使用服务器内存转储(例如发送给供应商进行故障排除),因此这样的攻击者无论如何都会在字节级别上进行操作。 - MatthewMartin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接