【问题标题】:Security internals of new operator and delegates in .NET.NET 中新操作员和委托的安全内部结构
【发布时间】:2015-06-14 13:33:27
【问题描述】:

前段时间,我阅读了有关 C/C++ 的各种安全建议。之后,我开始考虑它们是否适用于 .NET,我找到了一些答案,但不是全部,所以这是我的问题。

建议使用HeapAlloc 方法而不是VirtualAlloc 来分配内存。我知道 VirtualAlloc 存在 2 个潜在问题。首先,在 Windows 8 之前,此函数分配的地址不会被 ASLR(地址空间布局随机化)随机化。其次,VirtualAlloc 允许使用固定基址分配内存,这也是不建议的,因为这样可以更轻松地编写漏洞利用程序。有关详细信息,另请参阅article

问题是 new 操作符是如何工作的?它是使用 HeapAllocVirtualAlloc 还是别的什么?

还建议不要直接使用函数指针,而是在需要时使用EncodePointer/DecodePointer functions 对它们进行混淆和去混淆。这是一个类似于 ASRL 的概念。这种技术的目标是使预测指针值变得困难并覆盖它,以便它指向一些恶意代码。我们在 .NET 中有委托,但我认为在 .NET 内部必须在某些时候使用函数指针。

问题是 .NET 内部使用的函数指针的地址是否被混淆了?

【问题讨论】:

    标签: .net security .net-internals


    【解决方案1】:

    细节相当模糊,我不会花很多时间寻找攻击 .NET 进程的方法 :) 我所知道的已经到位:

    • .NET 程序集已打开 /DYNAMICBASE 选项,与本机程序用于启用 ASLR 的选项相同。
    • .NET 程序集默认打开 /HIGHENTROPYVA 选项。 C# 编译器公开了 /highentropyva 编译器选项来控制它。
    • CLR 使用 VirtualAlloc() 独占分配。它通过随机化应用程序域的加载器堆(jitted 代码、静态、类型等)和 GC 堆段的地址来实现自己的 ASLR 品牌。每次运行程序都会发生这种情况。线程堆栈也是随机的,可能是因为之前的选项。
    • 异常过滤器通过表查找定位,而不是堆栈上的指针。与 /SAFESEH 相同
    • 自 .NET 4.0 以来,.NET 程序(抖动、CLR、CRT)中的本机代码已打开 /GS,检测堆栈粉碎尝试。

    没有 EncodePointer() 调用,我怀疑它们是否可以工作。我从未听说过对 .NET 程序的成功攻击,用恶意数据感染托管代码是一项艰巨的任务。但谁知道呢。多年来有相当多的安全更新,所以有人想出了一些东西 :)

    【讨论】:

      【解决方案2】:

      所有这些仅适用于您使用不安全代码或 PInvoke(也需要完全信任)的情况。对于安全托管代码,此问题不适用,因为指定 CLR 的方式不会破坏内存安全。因此,没有什么可以通过随机化地址来防止的。地址不会暴露在安全的托管代码中(以任何可用的方式)。

      托管代码new(相对于本机new)使用托管堆。堆内存是通过使用VirtualAlloc 从操作系统获取的。我不知道它的位置是否是随机的。并非每个new 调用都会导致新的操作系统分配。许多对象适合一个操作系统分配。

      delegate 确实是底层的函数指针。它没有被混淆(可能是出于性能原因)。大多数代表指向代码堆上的 jitted 代码,大概是使用 VirtualAlloc 分配的(或者在使用 NGEN 时通过 LoadLibrary 加载)。

      .NET 假定您的进程没有被能够写入任意字节的攻击者“入侵”。如果是这样的话,所有的安全保证都在窗外。

      因此,我认为您提出的问题并不特别令人担忧。这是一个深度安全性问题,很好但不是必需的。

      【讨论】:

      • 我发现你们的 cmets 在安全方面非常幼稚。 .NET 假设您没有受到攻击?有很多方法可以从内存中写入或读取任意字节。一个典型的例子是“Shatter Attack”,它使用 Windows 编辑控件发布消息,这会导致您自己的程序在内部攻击自己。这已在 Vista 及更高版本中得到修复,但 .NET 在 Windows 2003 上仍受支持,例如...
      • .NET 对诸如粉碎攻击之类的攻击无能为力。只有纵深防御(这是一件好事,但还远远不够)。并且安全托管代码不能以任何方式读取或写入任意字节。在这个答案中,我清楚地区分了安全代码的正确性和不安全代码的正确性。如果您不同意更具体的评论。
      • 我认为您无意中误导了该声明。由于没有 .NET 代码是孤岛。它必须调用框架和库函数,其中许多在底层是不安全的。例如,jpeg 图像压缩库和 zip 压缩库中存在导致缓冲区溢出漏洞的缺陷,以及 .net 框架函数的 cve 缓冲区溢出漏洞。如果它所依赖的代码可以,我写的代码不能读写任意字节有关系吗?
      • 这些都是有效的漏洞利用,但 .NET 只能对此进行深度防御。你的意思是什么?纵深防守很重要吗?没错,但是 .NET 可以针对攻击者的任意内存写入做的事情非常有限。
      • 您的意思是,除了遵循微软已经确定的问题所指的指导方针之外,但没有这样做?我希望 Roslyn 和 RyuJIT 在这方面做得更好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      相关资源
      最近更新 更多