C# 内存堆安全:字符串垃圾收集

C# 内存堆安全:字符串垃圾收集,c#,.net,security,garbage-collection,clr,C#,.net,Security,Garbage Collection,Clr,我最近一直在为我的公司做一个安全代码审查,并使用了一个名为Fortify360的工具。它将识别代码中的许多问题并描述这些问题。它提出了一个有趣的问题,我没有找到任何其他信息,如下所示: “敏感数据(如密码)如果存储在托管字符串对象中,则内存中的存储可能会泄漏。字符串对象没有固定,因此垃圾收集器可以随意重新定位这些对象,并在内存中保留多个副本。默认情况下,这些对象不加密,因此任何可以读取进程内存的人都可以看到内容。此外,如果进程的内存被交换到磁盘,字符串的未加密内容将被写入交换文件。最后,由于字符

我最近一直在为我的公司做一个安全代码审查,并使用了一个名为Fortify360的工具。它将识别代码中的许多问题并描述这些问题。它提出了一个有趣的问题,我没有找到任何其他信息,如下所示:

“敏感数据(如密码)如果存储在托管字符串对象中,则内存中的存储可能会泄漏。字符串对象没有固定,因此垃圾收集器可以随意重新定位这些对象,并在内存中保留多个副本。默认情况下,这些对象不加密,因此任何可以读取进程内存的人都可以看到内容。此外,如果进程的内存被交换到磁盘,字符串的未加密内容将被写入交换文件。最后,由于字符串对象是不可变的,因此从内存中删除字符串的值只能由CLR垃圾收集器完成。除非CLR内存不足,否则无需运行垃圾收集器,因此无法保证关于何时进行垃圾收集。在应用程序崩溃的情况下,应用程序的内存转储可能会显示敏感数据。”

所有这些我都明白是有道理的,在我对这个问题的研究中是相当标准的

问题是:我如何解决这个问题?假设有问题的一个或多个类无法从iDisposable继承(非常大的应用程序,并且该类需要在有问题的字符串后面很久)。是否有另一种手动内存管理方法,可以在不调用垃圾收集器GC.Collect()的情况下处理特定字符串

提前感谢你的帮助


Alex

如果要避免此问题,您需要使用
IDisposable
来保存敏感数据,仅在所需的最短时间内保存此数据

具有讽刺意味的是,MSDN示例代码没有显式地或通过
使用
封装来
处理
实例。

老实说,解决这个“问题”将比它的价值更麻烦

在使用诸如ASP.NET之类的技术时,无法阻止将用户提交的密码保存在字符串中,除非您在发送字符串之前要在客户端对其进行加密,因为ASP.NET将它们作为字符串存储在表单集合等中

如果您确实使用JS加密,请注意,任何潜在的攻击者也可以解密他从您的应用程序中恢复的字符串

但是,如果有人闯入了web服务器,很可能会破坏整个数据库。这是一个比从web服务器堆中收集一些密码更糟糕的问题

现在,如果这不是一个ASP.NET应用程序,并且您可以完全控制密码在代码中的处理方式,那么您可以查看一下。但您可能仍然会发现,最小的好处超过了增加的代码复杂性。这实际上取决于密码泄漏的严重程度,以及您的计算机在一开始就容易受到攻击的程度。如果您不担心某些远程攻击者会调试您的进程并获取内存快照,那么这确实不是问题


总之:如果攻击者有权从内存或交换中提取这些字符串,他也有权做更糟糕的事情

OP明确表示他不能这样做。不,他没有。他说他不能使应用程序的特定类IDisposable,并不是说他不能使用其他IDisposable框架类。使其安全的不是Dispose()方法。不是调用
Dispose()
通过
CriticalFinalizerObject
父对象进行终结的先决条件?我认为System.SecureString正是我想要的。没错,但减少攻击面可能是值得的。OP表示,敏感字符串的生存期当然是有限的。但修复所需的风险和努力应该得到适当的评估,而不是依赖于产生“可怕”结果的诊断工具。如果一个坏蛋在某个点上可以访问内存,那么游戏就结束了。他可以安装屏幕刮板、键盘记录器和特洛伊木马。在这一点上,有人扫描内存是您最不担心的。该应用程序不是基于ASP.NET或web的,并且不具有财务性质,因此尝试以各种方式减少攻击面都会有所帮助。@Alex,我怀疑您尚未了解使用SecureString有多困难,以及它提供的额外保护有多少。例如,见。从安全字符串中获取值会立即使安全性失效。