论文分享 | Meltdown: Reading Kernel Memory from User Space

渗透技巧 2年前 (2022) admin
536 0 0

论文分享 | Meltdown: Reading Kernel Memory from User Space

论文分享 | Meltdown: Reading Kernel Memory from User Space

论文分享 | Meltdown: Reading Kernel Memory from User Space


此次分享的是发表在USENIX’18的题为《Meltdown: Reading Kernel Memory from User Space》的论文。


论文分享 | Meltdown: Reading Kernel Memory from User Space



论文分享 | Meltdown: Reading Kernel Memory from User Space
一 Introduction


论文分享 | Meltdown: Reading Kernel Memory from User Space

Meltdown攻击允许任何用户进程读取执行机器上的整个内核内存,包括映射到内核区域的所有物理内存,从而完全攻克内存隔离。Meltdown不利用任何软件漏洞,所以它几乎能够在所有主流的操作系统上起作用。相反,它利用了大多数现代处理器上的旁路通道信息。

虽然旁路通道攻击需要目标应用程序非常具体的相关信息,并且还要针对泄露的隐私数据进行特化处理,但Meltdown能让那些能够在有漏洞的处理器上执行代码的黑客获取整个内核地址空间的转储,包括任何映射的物理内存。Meltdown简易且强悍的根本原因正是乱序执行所带来的副作用。


论文分享 | Meltdown: Reading Kernel Memory from User Space




论文分享 | Meltdown: Reading Kernel Memory from User Space
二 Building Blocks of the Attack


论文分享 | Meltdown: Reading Kernel Memory from User Space

Executing Transient Instructions:

Meltdown的第一个模块块就是执行瞬态指令。瞬态指令基本上每时每刻都在发生,因为CPU会在当前指令之前连续运行,以尽量减少等待执行的延迟,从而最大限度地提高性能。如果瞬态指令的操作依赖于秘密值,则会引入可利用的旁路。文章主要关注那些映射到攻击者进程内的地址,即用户可访问的用户空间地址以及用户不可访问的内核空间地址。

访问用户不可访问的页面(例如内核页面)通常会触发一个终止该应用程序的异常。如果攻击者以用户不可访问的地址为目标,那么他们必须应对这个异常。文章提出了两种方法:通过异常处理(Exception handling),在执行完瞬态指令序列之后捕捉到有效的异常;通过异常抑制(Exception suppression),完全阻止异常发生,而在执行完瞬态指令序列之后重定向控制流。



Building a Covert Channel :

Meltdown的第二个模块是通过瞬态指令序列将微架构状态转换为架构状态(参见Figure1)。瞬态指令序列可以看作微架构隐蔽通道的发送端。隐蔽通道的接收端接收微架构状态变化,并从此状态推导保密值。值得注意的是,接收器不是瞬态指令序列的一部分,它可以是不同的线程,甚至是不同的进程,例如fork-and-crash方法中的父进程。


论文分享 | Meltdown: Reading Kernel Memory from User Space

Figure 1:Meltdown使用异常处理或抑制运行瞬态指令


文章利用的技术来自于缓存攻击,因为缓存状态是一种微架构状态,可以使用各种技术将其可靠地转换为架构状态。具体而言,文章使用了Flush+Reload方法,因为它允许建立一个快速、低噪声的隐蔽通道。

在瞬态指令序列访问一个可访问地址(隐蔽通道的发送器)之后,该地址被缓存用于随后的访问。之后接收器通过测量地址的访问时间来监视地址是否已经加载到缓存中。因此,发送器可以通过访问被加载到所监视的高速缓存中的地址来发送“1”位,并且通过不访问这样的地址来发送“0”位。

使用多个不同的缓存行,可以一次传输多个位数据。对于256个不同字节值中的每一个,发送器都访问不同的缓存行。通过对所有256个可能的缓存行执行Flush+Reload攻击,接收者可以恢复一个完整的字节而不是一个位。然而,由于Flush+Reload攻击比瞬态指令序列花费更长的时间(通常为几百个循环),所以一次仅发送一个位就更有效率。攻击者可以简单地通过对保密值进行相应地移位和掩码来做到这一点。


论文分享 | Meltdown: Reading Kernel Memory from User Space




论文分享 | Meltdown: Reading Kernel Memory from User Space
三 Exception handling


论文分享 | Meltdown: Reading Kernel Memory from User Space

异常处理的一个简单的方法是在攻击程序访问终止进程的无效内存位置之前就对进程克隆,然后只访问子进程中的无效内存位置。CPU在崩溃之前执行子进程中的瞬态指令序列。然后父进程可以通过观察微架构状态(例如通过旁路通道)来回复保密值。

另一个方法则可以安装一个信号处理程序,如果发生某些异常,这个信号处理程序将被执行,在这个特定的情况下是分段错误。这允许攻击者发出指令序列并防止应用程序崩溃,从而减少了开销,因为这样不需要创建新的进程。


论文分享 | Meltdown: Reading Kernel Memory from User Space




论文分享 | Meltdown: Reading Kernel Memory from User Space
四 Exception suppression


论文分享 | Meltdown: Reading Kernel Memory from User Space

处理异常的另一种方法是在第一时间阻止它们抛出。事务性内存允许将内存访问划分成为一个伪原子操作,如果发生错误,可以选择回滚到以前的状态。如果在事务中发生异常,架构状态将被重置,程序继续运行而不会中断。

此外,由于分支预测错误,推测执行可能会在执行的代码路径上执行原本不会发生的指令。这类依赖于之前的条件分支的指令可以被推测性地执行。因此,无效的内存访问被放置在一个仅当之前的分支条件评估为真时才执行的推测指令序列内。通过保证分支条件在执行的代码路径中从不计算为真,就可以抑制将要发生的异常,因为内存访问只是推测性地执行。这种技术可能需要对分支预测器进行复杂的训练。


论文分享 | Meltdown: Reading Kernel Memory from User Space




论文分享 | Meltdown: Reading Kernel Memory from User Space
Attack Description


论文分享 | Meltdown: Reading Kernel Memory from User Space

攻击者使CPU执行一个瞬态指令序列,使用物理内存中某处存储的不可访问的保密值。瞬态指令序列充当隐蔽信道的发送器,最终将保密值泄露给攻击者。

Meltdown包括三个步骤:

  • 攻击者选择的原本无权访问的内存地址的内容将被加载到寄存器中;

  • 瞬态指令根据寄存器的保密内容访问高速缓存行;

  • 攻击者使用Flush + Reload来确定所访问的缓存行,从而确定存储在所选内存位置的保密值。

通过针对不同的内存位置重复这些步骤,攻击者可以转储内核内存,包括整个物理内存。

下面代码列出使用x86汇编指令的瞬态指令序列和隐蔽通道发送端的基本实现。


论文分享 | Meltdown: Reading Kernel Memory from User Space


论文分享 | Meltdown: Reading Kernel Memory from User Space




论文分享 | Meltdown: Reading Kernel Memory from User Space
六 Countermeasure


论文分享 | Meltdown: Reading Kernel Memory from User Space

由于硬件不易修补,因此需要软件解决方法直到新版硬件被部署。Gruss等人提出了KAISER方法,一个内核修改,使得内核不再映射到用户空间。这种修改原是为了防止打破KASLR的旁路攻击。但是,它也可以防止Meltdown,因为它可以确保在用户空间中不会存在内核空间或物理内存的有效映射。

尽管KAISER提供了针对Meltdown的基本保护,但它仍然有一些限制。由于x86架构的设计,需要在用户空间映射数个特权内存位置。这为Meltdown留下了残留攻击漏洞,即这些存储位置仍然可以从用户空间读取。即使这些内存位置不包含任何保密值,它们仍可能包含指针。泄漏一个指针完全足以再次破坏KASLR,因为可以从指针值计算随机量。

不过,KAISER仍是目前可用的最佳临时解决方案。即使在Meltdown攻击的情况下,KAISER也可以保证映射在可能泄露有关随机偏移量信息的用户空间上的内存地址上不会持有任何内核指针。这将需要每个内核指针的跳板地址,即中断处理程序不会直接调用内核代码,而是通过跳板访问。跳板功能必须只能在内核中映射。它必须以不同于其余内核的偏移来随机化。因此,攻击者只能泄漏指向跳板代码的指针,而不能泄露剩余内核的随机偏移量。每个内核内存都需要使用这种跳板代码,这些代码仍然需要映射到用户空间并包含内核地址。


论文分享 | Meltdown: Reading Kernel Memory from User Space

若有理解不当之处,还请批评指正。



论文分享 | Meltdown: Reading Kernel Memory from User Space
END





原文始发于微信公众号(COMPASS Lab):论文分享 | Meltdown: Reading Kernel Memory from User Space

版权声明:admin 发表于 2022年10月10日 上午11:07。
转载请注明:论文分享 | Meltdown: Reading Kernel Memory from User Space | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...