漏洞利用开发的现状,第1部分

admin 2022年10月17日00:43:22漏洞利用开发的现状,第1部分已关闭评论112 views字数 7715阅读25分43秒阅读模式

原文地址:https://www.crowdstrike.com/blog/state-of-exploit-development-part-1/

翻译:梦幻的彼岸

漏洞利用开发的现状,第1部分

内存损坏漏洞历来是一个优秀的红色团队工具箱中最强大的配件之一。它们为进攻性安全工程师和攻击者带来了一个轻松的胜利,因为它们允许攻击者在不依赖任何用户互动的情况下执行payload。

对防御者来说,是幸运的,但对研究人员和攻击来说,是不幸的,这些类型的漏洞已经变得越来越难以执行,这主要是由于大量的操作系统缓解措施已经直接在我们每天使用的系统中实施。这种大量的缓解措施使得以前微不足道的漏洞在更现代的硬件和软件上变得昂贵和艰难。

这篇由两部分组成的博客系列介绍了Windows系统上漏洞利用开发和漏洞研究的演变。它讨论的问题包括:"这对未来的漏洞情况有何影响?"以及 "开发一个可靠的、可移植的和有效的二进制漏洞的代价是否仍然值得?"

我们是如何走到这一步的?

计算机从一开始就引起了人们的好奇心,这最终导致了 "计算机漏洞 "的发现,或由于用户互动而产生的系统非预期行为。这反过来又导致了具有恶意的坏人利用这些漏洞,并开启了二进制利用的时代。从那时起,安全研究人员、红队成员和攻击者都没有回头。

二进制利用的出现导致供应商,最明显的是 MicrosoftApple (特别要提到的是Linux上的 grsecurity 他在20多年前就发起了这项工作。), 通过各种缓解措施来阻止这些攻击。这些漏洞缓解措施,其中许多是默认启用的,已经减少了现代漏洞的影响。

就像活动目录在企业环境中的大量使用,迫使红队研究把重点放在微软产品上一样,由于Windows在企业和非企业环境中的广泛使用,攻击者和研究人员已经把它作为焦点。因此,本博客将以Windows为中心,关注用户模式和内核模式的缓解措施。

漏洞分类:过去和现在

在谈到二进制利用时,研究人员和攻击者总是不得不回答一个古老的问题。"如何才能在没有任何用户互动的情况下在目标上执行代码?" 答案是以各种漏洞类别的形式出现的。虽然不是一个详尽的清单,但一些常见的漏洞包括:

  1. 经典的栈溢出(是的,即使在2020年)。这是覆盖栈上现有内容的能力,并使用受控制的写入来定位和破坏一个函数的返回地址,以跳转到一个任意位置。
  2. 释放后使用(Use-after-free)。在用户模式下,对象被分配到堆的内存中(或内核模式的池内存中)。这个对象的过早“释放”发生了,尽管对这个被释放对象的引用/句柄仍然存在。使用另一个基元(primitive),在被释放的对象的位置上创建了一个新的对象,对旧对象的引用被用来执行或以其他方式修改新的对象,该对象正在代替旧的对象发挥作用。预期这些对新对象的意外改变会以某种方式导致权限提升或其他恶意能力。
  3. 任意写入。这是将数据(例如一个或多个指针)任意写入任意位置的能力。 这也可能是另一个漏洞类别的结果。 任意写入基元也可以用作任意读取基元,具体取决于对写入基元的准确度。
  4. 类型混淆。一个对象是一种类型,但后来该类型被引用为另一种类型。由于各种数据类型在内存中的布局,这可能导致意外的行为。

微软的Matt Miller在2019年的BlueHat IL上发表了一篇演讲,概述了自2016年以来的顶级漏洞类别:越界读取、释放后使用、类型混淆和未初始化使用。这些漏洞类别已经并仍在被攻击者和安全研究人员所利用。

还值得注意的是,这些漏洞类别中的每一个都可以位于用户模式、内核模式,以及现在的管理程序中。用户模式的漏洞在历史上是被远程利用的,或者通过普通的桌面应用程序,如浏览器、办公生产力套件和PDF阅读器。然而,内核模式的漏洞主要是在本地被利用--一旦获得了对系统的访问权,以提升权限。通常情况下,这种漏洞与用户模式的漏洞相结合,实现了通常所说的本地远程。此外,还有一些情况,如 MS17-010 (commonly referred to as EternalBlue), CVE-2019-0708 (commonly referred to as BlueKeep), 和 CVE-2020-0796 (commonly referred to as SMBGhost) 其中内核远程代码执行是可能的。

由于漏洞的增加,供应商不得不提供一些方法来防止这些漏洞的执行。因此,漏洞缓解措施应运而生。

利用的缓解措施: 过去和现在

虽然安全研究人员和攻击者在通过漏洞传递payload的各种方法中历来占据上风,但供应商慢慢地开始通过实施各种缓解措施来公平竞争,希望能完全消除漏洞类别或打破常见的利用方法。至少,希望缓解措施能使该技术过于昂贵,或不可靠,无法在大众市场上使用,例如在drive-by 利用工具包中。

从Windows的早期开始,这里定义的漏洞缓解措施已经有了长足的进步。传统的缓解措施--最初在微软操作系统上发布的缓解措施--将被首先解决。当代的缓解措施,包括更普遍的和有记录的挫败漏洞的工具,将是本系列的第二个支柱。最后,记录较少、没有被广泛采用的缓解措施--在这里被称为 "现代 "或前沿的缓解措施--将作为本系列的总结。

传统的缓解措施#1:DEP,又称No-eXecute(NX)

数据执行预防(DEP),被称为No-eXecute(NX),是最早的缓解措施之一,迫使研究人员和攻击者采用额外的利用方法。DEP防止任意代码在内存的非可执行部分被执行。它在用户模式和内核模式中都被引入了Windows XP SP2,尽管只针对用户模式的堆和栈,以及内核模式的堆加上可分页的内核内存(分页池)。大多数内核模式的堆内存,包括常驻内存(非分页池),在更多的版本中,直到包括Windows 8,才变得不可执行。虽然被认为是一个 "老 "的缓解措施,但它仍然是所有漏洞研究人员和攻击者必须考虑的一个因素。

DEP在内核模式和用户模式下的实现非常相似,因为DEP是通过页表项在每页内存基础上执行的。页表项,或称PTE,是指用于虚拟内存转换的分页结构中最低级别的条目。PTEs,在一个非常高的水平上,包含了负责为给定的虚拟地址范围执行各种权限和属性的位。每块虚拟内存被称为一个页(通常为4KB),通过内核中的页表条目被标记为可执行或可写,但不能同时进行。

利用WinDbg中的!address和 "页 "命令可以更深入地了解DEP的实现。

漏洞利用开发的现状,第1部分

漏洞利用开发的现状,第1部分

在内核模式DEP扩展到Windows操作系统的常驻内核堆之前,这种分配的PTE被标记为RWX--指的是NonPagedPool--意味着这种类型的内核模式内存是可执行和可写入的。常驻内存指的是这种分配类型所拥有的内存永远不会被 "分页 "出来,这意味着这种类型的虚拟内存将永远被映射到一个有效的物理地址。

随着Windows 8的发布,NonPagedPoolNx池成为常驻内存分配的默认内核模式堆。这抓住了NonPagedPool的所有属性,但使其不可执行。就像用户模式地址一样,可执行位是由内核模式虚拟地址的页表条目强制执行的。

漏洞利用开发的现状,第1部分

可用常见的开发技术绕过Usermode DEP,如return-oriented的编程、call-oriented的编程和jump-oriented 的编程。这些 "代码重用 "技术被用来动态调用Windows API函数,如VirtualProtect()或WriteProcessMemory(),以改变内存页的权限为RWX,或使用运行时加载的不同模块的指针将壳代码写入已经存在的可执行内存区域。除了改变内存的权限外,还可以利用VirtualAlloc()或类似的程序来分配可执行内存。

内核模式的DEP可以被绕过,使用一个任意的读/写基元来提取内存中特定页面的页表入口控制位,并将其修改为允许写入和执行访问。它也可以通过将执行流重定向到已经被标记为RWX的用户模式内存来绕过,因为在默认情况下,内核模式代码可以随意调用用户模式代码。

传统的缓解措施#2:ASLR/kASLR

随着DEP的加入,漏洞研究人员和攻击者迅速采用了代码重用技术。地址空间布局随机化(ASLR)和内核地址空间布局随机化(KASLR)的实现导致利用不那么直接。

ASLR及其内核模式的实现KASLR随机化了各种DLLs、模块和结构的基础地址。例如,这个特定版本的Windows 10在重启前,在虚拟内存地址ffff800`0fe00000处加载内核。

漏洞利用开发的现状,第1部分

重启后,内核被加载到一个不同的虚拟地址,ffff800`07000000。

漏洞利用开发的现状,第1部分

从历史上看,在实施ASLR之前,打败DEP就像将一个应用程序或DLL拆解成原始汇编指令一样简单,并利用这些指令的指针(在ASLR之前是静态的)来绕过DEP。然而,随着ASLR的实施,通常需要以下三种操作之一:

  1. 利用未用ASLR编译的DLLs和应用程序
  2. 利用越界漏洞或其他类型的信息/内存泄漏
  3. 对地址空间进行暴力攻击(在64位系统上不可行)。

在今天的现代开发环境中,信息泄露漏洞是绕过ASLR的标准。根据不同的情况,信息泄露通常可以被归类为另一个0-day漏洞,此外还有内存损坏的原始漏洞。这意味着现代漏洞可能需要两个0-day。

由于Windows只在每个启动的基础上执行ASLR,一旦系统启动,所有进程都共享相同的地址空间布局。因此,ASLR对于已经实现代码执行的本地攻击者来说是无效的。同样,由于内核为非特权用户提供了内省API,提供了内核内存地址,所以KASLR对这类攻击也不有效。由于这个原因,Windows上的ASLR和KASLR只是对远程利用载体的有效缓解措施。

然而,随着本地远程的兴起,人们认识到KASLR对首先实现用户RCE的远程攻击者是无效的,因为如前所述,某些Windows API函数,如EnumDeviceDrivers()或NtQuerySystemInformation(),可以被用来列举所有加载的内核模块的基础地址。

由于本地远程攻击者首先会从针对浏览器等的用户模式RCE开始。微软开始大力推行此类应用程序在沙盒环境中运行,并引入了强制性完整性控制(MIC),以及后来的AppContainer,作为降低这些应用程序权限的一种方式,除其他外,以低完整性级别运行它们。然后,在Windows 8.1中,它阻止了对中等完整性级别及以上进程的这种内省API功能的访问。

因此,一个低完整性级别的进程,如浏览器沙盒,将需要一个信息泄露的漏洞来规避KASLR。

漏洞利用开发的现状,第1部分

在Windows 10的各个版本中,其他几个泄露内核基本地址的基元已经得到了缓解。值得注意的是,硬件抽象层(HAL)堆,包含多个指向内核的指针,也位于一个固定位置。这是因为HAL堆在启动过程中很早就需要,甚至在实际的Windows内存管理器初始化之前。当时,最好的解决方案是在一个完全固定的位置为HAL堆保留内存。这一点在Windows 10创意者更新(RS2)构建中得到了缓解。

尽管ASLR几乎和DEP一样古老,而且它们都是最早实施的一些缓解措施,但在现代利用过程中必须考虑到它们。

当前缓解措施#1:CFG/kCFG

控制流保护(CWG)及其在内核中的实现,即kCFG,是微软的控制流完整性(CFI)的版本。CFG的工作原理是对用CFG编译的模块和应用程序内的间接函数调用进行检查。此外,从Windows 10 1703(RS2)版本开始,Windows内核已经用kCFG进行了编译。然而,请注意,为了启用kCFG,需要启用VBS(基于虚拟化的安全)。VBS将在本博客系列的第二部分中详细讨论。

为了提高用户的效率,受CFG保护的间接调用使用位图进行验证,用一组位来表示目标是否 "有效 "或目标是否 "无效"。一个目标被认为是 "有效的",如果它代表了进程中加载的模块中一个函数的起始位置。这意味着该位图代表了整个进程的地址空间。每个用CFG编译的模块在位图中都有自己的一组位,基于它在内存中加载的位置。正如ASLR部分所描述的,Windows只在每次启动时随机化地址空间,所以这个位图通常在所有进程中大部分是共享的,这就节省了大量的内存。

一般来说,在很高的水平上,间接的用户模式函数调用被传递给一个guard_check_icall函数(或在其他情况下guard_dispatch_icall)。这个函数然后解除对函数_guard_check_icall_fptr的定义,并执行跳转到指针,该指针是指向函数LdrpValidateUserCallTargetES(或其他情况下的LdrpValidateUserCallTarget)的指针。

漏洞利用开发的现状,第1部分

一系列的位操作和汇编函数被执行,其结果是检查位图以确定间接函数调用内的函数是否是位图内的有效函数。一个无效的函数将导致进程终止。

kCFG有一个非常类似的实现,即间接函数调用是由kCFG检查的。最值得注意的是,这 “破坏 ”了[nt!HalDispatchTable+0x8]基元,攻击者和研究人员通过调用nt!KeQueryIntervalProfile,在64位系统上对[nt!HalDispatchTable+0x8]进行间接函数调用,在内核的上下文中执行代码。

漏洞利用开发的现状,第1部分

kCFG使用了对CFG稍有不同的修改,即位图被存储在变量nt!guard_icall_bitmap内。此外,nt!_guard_dispatch_icall启动了验证目标的固定程序,不需要其他函数调用。

漏洞利用开发的现状,第1部分

CFG缓解了这样一个事实,即在漏洞利用开发生命周期的某个时刻,一个函数指针可能需要被覆盖以指向一个不同的函数指针,这可能对攻击者有利(如VirtualProtect)。

CFG是一个前向边缘CFI缓解措施。这意味着它不考虑ret指令,这是一个后向边缘情况。由于CFG不检查返回地址,CFG可以通过利用信息泄露来绕过,这可能允许解析线程环境块(TEB)等操作溢出栈。利用这些知识,就有可能在堆栈上覆盖一个函数的返回地址,从而达到恶意的目的。

随着时间的推移,人们发现CFG有一些不足之处。例如,请注意,模块利用导入地址表(IAT)进行导入,如Windows API函数。这些IAT表本质上是一个特定模块中的虚拟地址,指向Windows API函数。

漏洞利用开发的现状,第1部分

IAT默认是只读的,一般不能修改。由于其只读状态,微软认为这些函数是 "安全的",这意味着CFG/kCFG并不保护这些函数。如果攻击者能够修改,或在IAT中添加一个恶意条目,就有可能调用用户定义的指针。

此外,攻击者可以利用额外的操作系统功能来执行代码。根据设计,CFG/kCFG只验证一个函数是否在位图指示的位置开始,而不是验证一个函数是否是它所声称的。如果攻击者或研究人员能够在CFG/kCFG位图中找到更多标记为有效的函数,就有可能用另一个函数的指针覆盖一个函数的指针,以 "代理 "代码执行。例如,这可能导致类型混淆攻击,即一个不同的、意想不到的函数现在正用原来预期的函数的参数/对象运行。

如前所述,kCFG只有在启用VBS时才会启用。kCFG的一个有趣的特点是,即使VBS没有启用,kCFG调度函数和例程仍然存在,函数调用仍然通过它们传递。无论是否启用VBS,kCFG都会对虚拟地址的 "高层 "位进行逐位检查,以确定一个地址是否是符号扩展的(也被称为内核模式地址)。如果检测到一个用户模式的地址,无论HVCI是否被启用,kCFG都会导致KERNEL_SECURITY_CHECK_FAILURE的错误检查。这是防止内核模式代码被胁迫调用用户模式代码的一种缓解措施,我们看到这是一种绕过DEP的潜在技术。在下一节,我们将讨论监督者模式执行预防(SMEP),这也是针对这种攻击的一种当前缓解措施。

同样值得注意的是,kCFG位图受到HVCI的保护,即Hypervisor保护的代码完整性。HVCI将在本博客系列的第二部分中被提及。

当前缓解措施#2:SMEP

Supervisor Mode Execution Prevention是一个基于硬件的CPU缓解措施,是专门针对内核漏洞而实施的。

当NonPagedPoolNx被引入时,研究人员和攻击者不能再直接将shellcode写到内核模式并执行它。这导致了这样一个想法:像VirtualAlloc()这样的Windows API函数可以被用来在用户模式下分配shellcode,然后将返回的指针传递给shellcode回到内核模式。然后,内核将在内核的 "上下文 "中执行用户模式的代码,这意味着shellcode将以完全的内核权限运行。

SMEP通过不允许从内核执行用户模式代码来缓解这种攻击。更具体地说,基于x86的CPU有一个内部状态,称为代码权限级别(CPL)。这些CPU有四个不同的CPL,被称为环。Windows只利用其中的两个环:第3环,与驻留在用户模式的任何东西有关;第0环,与驻留在内核模式的任何东西有关。SMEP不允许属于CPL 3的代码在CPL 0的上下文中被执行。

SMEP是通过CR4控制寄存器的第20位启用的。控制寄存器是一个用来改变或启用CPU某些功能的寄存器,如通过分页实现虚拟内存等。尽管SMEP是通过CR4寄存器的第20位启用的,但它是通过内存地址的PTE来执行的。SMEP的执行是通过检查任何分页结构的PTE的用户与主管(U/S)位来实现的。如果该位被设置为U(ser),则该页被视为用户模式的页。如果该位被清除,意味着该位被表示为S(upervisor),则该页被视为监督者(内核模式)页。

正如Alex Ionescu在2015年Infiltrate大会上解释的那样,如果只有一个分页(paging)项被设置为 "S"--SMEP就不会导致崩溃。这一认识很重要,因为SMEP可以通过任意写入的方式 "欺骗 "CPU从用户模式执行shellcode而被绕过。

首先,在用户模式下找到分配的PTE,然后清除U/S位,使其被设置为S,当这种情况发生时,CPU将把这个用户模式的地址视为内核模式的页面--允许执行。

漏洞利用开发的现状,第1部分

绕过SMEP的一个旧技术是通过利用ROP在全系统范围内禁用它。攻击者可以利用内核模式下的ROP小工具,找到一个允许将CR4寄存器的值覆盖为第20位清零的值,从而使SMEP回到CR4寄存器中。

这种方法的缺点是,你必须使用内核模式的ROP小工具来保持在内核中执行,以便遵守SMEP的规则。此外,就像所有的代码重用攻击一样,小工具之间的偏移量在不同的Windows版本之间可能会发生变化,而堆栈的控制是ROP发挥作用的必要条件。一种被称为HyperGuard的保护措施,超出了本篇文章的范围,也可以防止现代系统上的CR4修改。

漏洞利用开发的现状,第1部分

总结

在这篇博客中,传统缓解措施与当代缓解措施(如CFG和SMEP)一起被重新审视,这些缓解措施旨在挑战漏洞研究人员并提高漏洞利用的门槛和质量。这些主题为更现代的缓解措施奠定了基础,如ACG、XFG、CET和VBS,这些措施增加了复杂性与利用的影响,并促使读者对当前利用开发的投资回报更加好奇。 请阅读“漏洞利用开发的现状,第2部分”,我们将讨论了更多当前的漏洞利用途径以及微软为应对这些途径而开发的许多缓解措施。

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月17日00:43:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   漏洞利用开发的现状,第1部分http://cn-sec.com/archives/1353427.html