gpt4 book ai didi

c# - SecureString 在 C# 应用程序中实用吗?

转载 作者:IT王子 更新时间:2023-10-29 03:29:24 24 4
gpt4 key购买 nike

如果我的假设在这里有误,请随时纠正我,但让我解释一下我为什么要问。

摘自 MSDN,一个 SecureString :

Represents text that should be kept confidential. The text is encrypted for privacy when being used, and deleted from computer memory when no longer needed.



我明白了,将密码或其他私有(private)信息存储在 SecureString 中是完全有意义的。在 System.String ,因为您可以控制它实际存储在内存中的方式和时间,因为 System.String :

is both immutable and, when no longer needed, cannot be programmatically scheduled for garbage collection; that is, the instance is read-only after it is created and it is not possible to predict when the instance will be deleted from computer memory. Consequently, if a String object contains sensitive information such as a password, credit card number, or personal data, there is a risk the information could be revealed after it is used because your application cannot delete the data from computer memory.



但是,对于 GUI 应用程序(例如,ssh 客户端), SecureString必须由 System.String 构建.所有文本控件都使用字符串作为其基础数据类型。

因此,这意味着每次用户按下一个键时,旧字符串都会被丢弃,并且会构建一个新字符串来表示文本框中的值,即使使用密码掩码也是如此。我们无法控制何时或是否从内存中丢弃这些值中的任何一个。

现在是登录服务器的时候了。你猜怎么着?您需要通过连接传递一个字符串以进行身份​​验证。所以让我们转换我们的 SecureStringSystem.String .... 现在我们在堆上有一个字符串,无法强制它进行垃圾收集(或将 0 写入其缓冲区)。

我的观点是 :不管你做什么,在某个地方,那个 SecureString将被转换成 System.String ,这意味着它至少会在某个时候存在于堆上(没有任何垃圾收集保证)。

我的观点不是 :是否有办法绕过将字符串发送到 ssh 连接,或绕过让控件存储字符串(制作自定义控件)。对于这个问题,您可以将“ssh 连接”替换为“登录表单”、“注册表单”、“付款表单”、“foods-you-would-feed-your-puppy-but-not-your-children 表单”,等等。
  • 那么,在什么时候使用 SecureString实际上成为
    实际的?
  • 是否值得花费额外的开发时间来完全根除
    使用System.String目的?
  • SecureString的全点简单地减少时间 System.String是否在堆上(降低移动到物理交换文件的风险)?
  • 如果攻击者已经拥有进行堆检查的手段,那么他很可能 (A) 已经拥有读取击键的手段,或者 (B) 已经物理上拥有机器......使用 SecureString 也是如此。无论如何阻止他获取数据?
  • 这只是“通过默默无闻的安全”吗?

  • 对不起,如果我把问题问得太厚了,好奇心占了上风。随时回答我的任何或所有问题(或告诉我我的假设完全错误)。 :)

    最佳答案

    SecureString其实有很实用的用途.

    你知道我见过多少次这样的场景吗? (答案是:很多!):

  • 密码意外出现在日志文件中。
  • 在某处显示密码 - 一旦 GUI 确实显示了正在运行的应用程序的命令行,并且命令行由密码组成。 糟糕 .
  • 使用内存分析器与您的同事一起分析软件。同事在内存中看到您的密码。听起来不真实?一点也不。
  • 我曾经用过 RedGate可以在异常情况下捕获局部变量“值”的软件,非常有用。不过,我可以想象它会意外地记录“字符串密码”。
  • 包含字符串密码的故障转储。

  • 你知道如何避免所有这些问题吗? SecureString .它通常可以确保您不会犯这样的愚蠢错误。它是如何避免的?通过确保密码在非托管内存中加密,并且只有当您对自己在做什么有 90% 的把握时才能访问真正的值。

    从某种意义上说, SecureString工作很容易:

    1)一切都是加密的

    2) 用户调用 AppendChar
    3)解密UNMANAGED MEMORY中的所有内容并添加字符

    4) 再次加密 UNMANAGED MEMORY 中的所有内容。

    如果用户可以访问您的计算机怎么办?病毒是否能够访问所有 SecureStrings ?是的。您需要做的就是让自己陷入 RtlEncryptMemory当内存被解密时,你会得到未加密的内存地址的位置,并读出它。瞧!事实上,你可以制作一个病毒,它会不断扫描 SecureString 的使用情况。并用它记录所有事件。我并不是说这将是一项容易的任务,但它是可以完成的。如你所见, SecureString的“强大”一旦您的系统中有用户/病毒,它就完全消失了。

    你在你的帖子中有几点。当然,如果你使用一些在内部保存“字符串密码”的 UI 控件,使用实际的 SecureString是不是很有用。尽管如此,它仍然可以防止我上面列出的一些愚蠢行为。

    此外,正如其他人所指出的,WPF 支持使用 SecureString 的 PasswordBox。内部通过其 SecurePassword property.

    底线是;如果您有敏感数据(密码、信用卡等),请使用 SecureString .这就是 C# 框架所遵循的。例如, NetworkCredential类将密码存储为 SecureString .如果你看 this ,您可以在 SecureString 的 .NET 框架中看到超过 80 多种不同的用法。 .

    很多情况下必须要转换 SecureString到字符串,因为某些 API 需要它。

    通常的问题是:
  • API 是通用的。它不知道有敏感数据。
  • API 知道它正在处理敏感数据并使用“字符串”——这只是糟糕的设计。

  • 你提出了很好的观点:当 SecureString 时会发生什么转换为 string ?这只能因为第一点而发生。例如API 不知道它是敏感数据。我个人没有看到这种情况发生。从 SecureString 中取出字符串并不是那么简单。

    原因不简单 ;从来没有打算让用户将 SecureString 转换为字符串,正如您所说:GC 将启动。如果您看到自己这样做,您需要退后一步问问自己:我为什么要这样做,或者我真的需要这,为什么?

    我看到了一个有趣的案例。即WinApi函数LogonUser以LPTSTR为密码,即需要调用 SecureStringToGlobalAllocUnicode .这基本上为您提供了位于非托管内存中的未加密密码。完成后,您需要立即摆脱它:
    // Marshal the SecureString to unmanaged memory.
    IntPtr rawPassword = Marshal.SecureStringToGlobalAllocUnicode(password);
    try
    {
    //...snip...
    }
    finally
    {
    // Zero-out and free the unmanaged string reference.
    Marshal.ZeroFreeGlobalAllocUnicode(rawPassword);
    }

    您可以随时扩展 SecureString带有扩展方法的类,例如 ToEncryptedString(__SERVER__PUBLIC_KEY) ,这会给你一个 string SecureString 的实例使用服务器的公钥加密。只有服务器才能解密它。问题已解决:垃圾收集永远不会看到“原始”字符串,因为您永远不会在托管内存中公开它。这正是 PSRemotingCryptoHelper 中正在做的事情( EncryptSecureStringCore(SecureString secureString) )。

    以及几乎相关的东西: Mono SecureString 根本不加密 .该实现已被注释掉,因为..等待它.. "It somehow causes nunit test breakage" ,这就引出了我的最后一点:
    SecureString并非所有地方都支持。如果平台/架构不支持 SecureString ,你会得到一个异常(exception)。文档中提供了支持的平台列表。

    关于c# - SecureString 在 C# 应用程序中实用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26190938/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com