【问题标题】:How to destroy and clear string variable contents from memory?如何从内存中销毁和清除字符串变量内容?
【发布时间】:2016-02-07 05:37:15
【问题描述】:

什么是从内存中删除字符串变量的所有痕迹的安全方法? 我已经知道SecureString 类的用法,但有时需要从外部源导入或处理数据,并且它们中的大多数都在使用字符串;这是一个例子:

    Dim decrypted_data() As Byte = Decrypt(...)
    Dim temp As String = System.Text.UTF8Encoding.UTF8.GetString(decrypted_data)
    Dim sec As SecureString = GetSecureString(temp)
    ' Now I should remove temp contents from memory

或者在我的示例中更好的解决方案是直接将加密数据写入 SecureString 的想法,但我不知道这怎么可能。

【问题讨论】:

  • 您要求一个“安全”的解决方案,但没有说明该解决方案必须能够抵御何种攻击。谁在攻击,他们在攻击什么,为什么粉碎内存是一种缓解措施?
  • @EricLippert 想象一下有人可以访问我的应用程序。有一些黑客工具可以在列表中显示应用程序字符串。所以我不希望在该列表中看到我的应用程序decrypted_data。我想在将敏感信息转换为SecureStringencrypted_bytes_of_data 等更安全的类型后清除所有敏感信息痕迹。
  • 运行这些工具的人,他们是您的应用程序的用户吗?或者他们是一个人攻击你的应用程序的用户?如果您试图保护应用程序免受您自己的用户的攻击,那么我向您提交您的用户信任模型已损坏;用户是必须信任您的软件的人,反之亦然!你的软件是用户的仆人,而不是它的主人。如果攻击者正在攻击用户,那么我认为攻击者必须已经拥有对用户计算机的管理员访问权限,并且用户已经丢失了。
  • 我注意到我在上一条评论中的分析包含一个重要的 - 故意的 - 错误。你看到了吗?假设具有管理员访问权限的攻击者是用户的自动损失,因此针对给定攻击的缓解措施是无用的,这是没有保证的。例如,管理员永远不需要用户密码的纯文本,因此明智的做法是粉碎密码,这样即使是敌对的管理员也无法轻易获得纯文本。 (恶意管理员当然可以安装一个键盘记录器,但这依赖于用户输入密码。)
  • 也就是说,假设攻击者已经拥有系统的攻击仍然存在,这些通常不是需要防范的有趣攻击。最好首先集中精力防止攻击者将权限提升为管理员。

标签: c# vb.net string security memory-management


【解决方案1】:

我终于做到了:

<System.Runtime.CompilerServices.Extension()> _
Public Sub ZeroFree(ByRef str As String)
    If String.IsNullOrEmpty(str) Then
        Return
    End If
    If String.IsInterned(str) IsNot Nothing Then
        ' Throw New Exception("Interned strings are not supported!")
        Return
    End If
    Dim gch As GCHandle = GCHandle.Alloc(str, GCHandleType.Pinned)
    ZeroMemory(gch.AddrOfPinnedObject, str.Length * 2 - 1)
    gch.Free()
    str = Nothing
End Sub

Public Sub ZeroMemory(ByVal location As IntPtr, ByVal size As Integer)
    For i As Integer = 0 To size
        Marshal.WriteByte(IntPtr.Add(location, i), 0)
    Next
End Sub

来自 cmets:

注意:这是我能找到的解决这个问题的最佳解决方案,但它不是通用或 100% 的解决方案,它在特殊情况下不起作用,例如它不能清除相同的副本如果它之前被垃圾收集器自动复制,则为字符串。
更棒的想法或有用的建议总是受欢迎的!

【讨论】:

  • 这当然行不通。 完全有可能来自这个字符串的数据在调用这个方法后仍然存在并且可以访问。当埃里克说你已经输了的时候,他并没有轻描淡写。
  • 哦,如果您曾经在实习字符串上使用此方法,那么您将完全占用实习池,这非常糟糕。
  • @Servy 否我已经测试并尝试从内存地址中检索字符串,并按预期清除。在没有测试和证明的情况下如何评价?!
  • @Servy 我认为 String.IsInterned() 是保护这种情况发生的方法。
  • 你做不到的事实并不意味着它不可能。该字符串很可能会存在于任何数量的地方。如果有任何 GC 集合,GC 很可能已经复制了很多次,并且当它完成这些旧副本时,它不会费心清除它们,等等。
猜你喜欢
  • 2015-11-22
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
相关资源
最近更新 更多