WPF PasswordBox 到底有多安全?

How secure is the WPF PasswordBox, really?

我最近已经问了几个关于 PasswordBox 的问题,但我的问题的核心是,我需要一种极其安全的方式来将非常敏感的信息输入到我的 .Net 应用程序中。

开箱即用,WPF PasswordBox 是获取密码或其他敏感信息的首选控件。为了安全起见,它通过 SecurePassword 属性 提供了一个 SecureString 对象,就我而言,这足以满足我的需要。但是,我发现此控件存在一个主要缺陷——它有一个 Password 属性,这是用户在不安全的 .Net 字符串中输入的内容。

我想假设如果我从不在我的应用程序中访问 Password 属性,我的敏感信息的不安全版本将永远不会生成并且必须被垃圾收集。没事。但是,由于字符串的安全形式的要点是保护值免受可以读取 .Net 内存的窥探进程(我假设)的影响,相同的窥探恶意代码是否可以简单地寻找 PasswordBox在内存中徘徊并找到某种方法来访问 Password 字段,从而使 SecureString 值的使用基本上无用?

我承认,我不知道这些攻击是如何执行的。但是,如果问题是某些应用程序可能正在嗅探您在 .Net 内存 manager/garbage 收集器中的变量,那么在我看来他们所要做的就是访问 PasswordBox 控制对象似乎是合理的,而不是内存中的字符串对象并简单地访问 Password 属性。在这个谜题中我可能遗漏了什么?如果 PasswordBox 包含明文形式的 Password 属性,它又如何安全?

PasswordBox.Password 属性 从 SecurePassword 属性 创建 .NET 字符串,它不会在内部将其存储为字符串。使用 SecureString 的全部意义在于 减少 内存中存在的敏感数据的时间量,并减少该敏感数据的副本数量。您可以在 documentation.

中阅读有关 SecureString 的更多信息

SecureString 是加密的(如果可能的话,通常是这样),所以如果有人只能读取原始内存(比如有人窃取你的内存转储)——他将无法从它。如果您的应用程序受到如此大的破坏,以至于攻击者可以将他自己的 dll 注入您的进程并在那里插入 运行 任意代码 - 那么无论如何您都会遇到更大的问题(并且仍然很有可能密码不会出现在内存中)。

也就是说,在一般情况下使用 PasswordBoxSecureString 时,您仍然可以遵循一些合理的准则。

  1. 如果您需要访问 PasswordBox.SecurePassword 的结果,请始终处理它:

    using (var pwd = myBox.SecurePassword) {
        // do stuff
    }
    

这可能看起来很奇怪(处理 属性 返回的东西),但应该这样做,因为这个 属性 returns SecureString 的副本并且应该有而是一种方法,但由于某种原因是 属性.

  1. 尽可能少地访问Password属性,最好只在真正需要时访问一次。您不希望密码副本在内存中保留的时间超过需要的时间。

  2. 总是在完成后调用 yourBox.Clear()。这会将密码设置为空字符串并清除内部 SecureString 内存。

你不必猜测,你可以look it up

密码框没有字段Password。它有一个保存密码的字段PasswordTextContainer

这意味着文档是正确的

Remarks

When you get the Password property value, you expose the password as plain text in memory. To avoid this potential security risk, use the SecurePassword property to get the password as a SecureString.

如果您不以明文形式阅读它并在您的应用程序中将其作为明文保存,它将不会是明文。

但同样,不要相信互联网上随机的人(包括我!),just look at it yourself