简介
Rowhammer表明,基于非物理硬件的攻击可能具有破坏性。在最近的一篇论文中,Cai等人提出,可以在基于MLC NAND闪存的SSD上执行类似的攻击,并且具有潜在的破坏性。在本文中,我们将讨论在SSD上成功地进行全系统的本地权限提升的攻击的要求,并展示基于文件系统的攻击方法,我们将对此进行演示。 特别地,我们展示了攻击者可以通过使用单元与单元之间的干扰获得攻击原语,因此需要在OS层进行精心的设计。
前言
在开发软件时,通常会抽象出硬件,并将诸如资源隔离等安全保护视为理所当然。 简而言之,现代软件编程几乎不需要知道底层硬件的复杂性。
Rowhammer 把硬件的内部运作引入到我们的注意力中。 Rowhammer利用内存管理更深层次的缺陷来破坏敏感的内存区域。最近的工作表明,这样一个非显而易见的复杂漏洞可以被利用来通过Javascript注入错误[8],实现手机上的权限升级[22]或者破坏共同托管的虚拟机。
但是,DRAM并不是唯一拥有敏感数据的地方,这些敏感数据对在软件中实施正确的安全保护是必不可少的。通过文件系统组织的持久性存储,根据存储在磁盘上的元数据授予对数据的访问权限。在现代计算机中,闪存已经在很大程度上取代了旋转磁盘作为主要的永久性存储介质。
Cai等人最近发表的论文中提出在固态硬盘上可能出现类似rowhammer的攻击,但不会出现实际的攻击,我们从系统角度研究这类攻击SSD的可行性。 特别是,我们表明,在对闪存设备行为和文件系统使用的真实假设下,利用闪存弱点来升级本地权限是可能的(虽然很具有挑战性)。 我们演示的攻击不是”全系统”,因为我们仅仅演示了文件系统层的攻击,并假定底层闪存介质的损坏是可能的。 但是,我们还描述了这种攻击如何扩展到全系统攻击,我们打算在未来的工作中展示这种攻击。
更准确地说,我们利用对SSD(包括ECC)中现有可靠性机制的了解,证明攻击者从MLC NAND闪存的缺陷中获得的attack primitive是粗粒度的损坏:不像在rowhammer中,攻击者可以翻转单个bit,在这种攻击的情况下,攻击者只能破坏一个数据块。然后我们证明,这个较弱的attack primitive(与翻转单个位相比,这为攻击者提供了更高级别的控制)足以导致提升本地权限的攻击。
模型:我们假设被攻击系统在基于MLC NAND闪存的SSD上运行文件系统,并假设攻击者不具有特权,即被攻击系统的非root访问。该访问使攻击者可以通过文件系统对系统存储器进行受控写入访问。一个典型的场景是非特权用户的登录shell。我们不讨论对被攻击统的物理访问。
贡献:本文的主要贡献如下:
(1)我们首次详细介绍了如何进行完整系统地,基于闪存缺陷的、提升本地特权的攻击。
(2)我们将此攻击在文件系统级别进行了实施并演示。
(3)我们讨论了该攻击的泛化和限制。
背景介绍
2.1基于硬件的攻击
表1展示了基于硬件攻击的分类。首先,我们区分两个主要类别:物理和非物理攻击。对于物理攻击,需要直接访问系统的硬件。这种攻击的例子是探测电压电平或刮掉硅芯片上的镀层来对其逻辑进行逆向工程。少数相关的例子使用冷却剂喷雾和冷启动来从系统的记忆库中泄露敏感信息。另一方面,非物理攻击仍然利用系统的硬件,但不需要直接访问,因此可能更强大。例如,定时旁路攻击可以针对云中的服务器远程执行。
在正交层面上,我们区分危害系统机密性和完整性的攻击。危害机密性的攻击通常需要读取原语来公开敏感信息,例如高速缓存旁道攻击中的关键材料。另一方面,对系统完整性的攻击需要写入原语来主动修改和破坏系统的各个方面以改变其行为。一个非常突出的例子是drammer [22],它使用rowhammer [10,19]内存写入原语在Android上执行特权升级攻击 。
本文中显示的攻击属于同一类非物理硬件完整性攻击。
2.2 闪存的缺陷
MLC NAND闪存表现出与介质和器件特性相关的可靠性问题。首先,MLC NAND Flash上的重复编程擦除(P / E)周期会加重器件的负载并逐渐使其可靠性变差[23]。其次,单元间干扰(CCI)是闪存页面写入期间发生的另一个不利影响,并影响NAND器件的可靠性。由于存储器阵列中相邻单元之间的电容耦合[12],施加于当前正在编程的页面单元的编程电压对相邻页面单元造成干扰。第三,由于只读操作的反复执行而导致的阈值电压不稳定,从而造成干扰,导致位错误数量的显着增加[21]。第四,最近的研究已经表明,在部分编程的MLC NAND块中,在页面编程完成之前,会进行大量的读取,剩下的页面的误码率会显著增加[14]。
攻击者可以利用CCI来更改被攻击者闪存页面中的信息。这可以通过使用对被攻击的闪存页面产生最大干扰的特殊数据模式对相邻的被攻击者页面进行编程来实现。由于CCI的性质,只有少数单元可以进行状态转换。 具体而言,CCI可以导致单元状态仅转换到较大的阈值电压。使用CCI,攻击者可以写入具有最大干扰模式的攻击闪存页,以概率的方式对相邻受害者页面的所有或不同字段的单元进行不受控制的随机修改。
2.3 闪存可靠性的方法
在闪存控制器级别,使用两种机制来提高可靠性:扰码和纠错码(ECC)。由于某些位模式更可能导致错误,因此数据不会按原样写入,而是由扰码器编码以减少错误的方式写入[20]。 通常情况下,数据可以通过与块地址相关的位模式简单异或。关于ECC,写入闪存页的数据被编码:将冗余位添加到用户数据中,以确保从闪存读取的二进制序列中存在的错误可通过解码进行纠正。闪存存储系统中使用的编码字长度通常在512B到2KB之间。虽然两种使用最广泛的编码是Bose-Chaudhuri-Hocquenghem(BCH)编码和低密度奇偶校验(LDPC)编码,但编码设计的确切细节是制造商决定的。
全系统攻击
利用闪存缺陷的本地权限提升的全系统攻击需要解决存储层次结构上不同层面的多重挑战。即从最低层到最高层:
(1)闪存芯片:单元间干扰。
(2)闪存控制器:扰码器和ECC。
(3)SSD控制器:磨损均衡和块放置算法。
(4)操作系统:文件系统缓存和错误检测。
(5)用户:权限提升。
第1层是攻击的基础。正如第2节所述,以前的工作表明可以在具有特定访问模式的闪存页中引起位翻转,特别是使用单元间干扰。
Flash社区早已知道并研究了NAND错误,并且在SSD可靠性问题的背景下,制造商设计了闪存和SSD控制器,以降低在实际使用中发生此类错误的概率。 实质上,第2层和第3层旨在向操作系统提供没有可靠性问题的块设备的抽象,并以存储设备的寻址粒度完美隔离访问。通常在系统安全性方面,这种抽象可能显示出漏洞。接下来我们解释攻击者可能从这个漏洞抽象中得到什么攻击原语。
剩下的挑战(第4层到第5层)主要在于找到一个基于文件系统的攻击矢量,它利用了这个弱攻击原语,这是本文的主要贡献。 这种攻击的总体思路是破坏文件系统的数据结构,并准备新的文件系统并选择结构,这可能导致权限的提升(在这种情况下,创建SUID根目录的 shell二进制文件)。
我们已经探索了多种可能性,并在第4节中介绍了我们发现的最佳攻击方案(就成功概率而言)。
3.1 Attack primitives
系统中ECC编码/解码的存在决定了攻击者所期望的最好的情况是对flash页面/块的不受控制的随机修改。为了理解这一点,让我们考虑一下不同的解码方法,即通过将原始位错误注入闪存页面可能会导致攻击行为。我们将假设用户数据已经使用BCH编码进行保护,BCH编码能够利用它的码字(C1)纠正t bit出错。T的值通常非常高(例如,t = 50)。 在引入错误时,可能会引发三种可能的事件:
(1)解码成功。如果引入的错误数小于或等于t,解码一定成功。
(2)检测到解码失败。如果注入错误的数量严格大于t并且得到的二进制向量不在另一个码字的解码半径内,则会发生此情况。通常,读取失败将由系统报告,系统将处理该失败操作。
(3)未检测到解码失败。 当注入错误的数量严格大于t并且所得到的矢量落入另一个码字(C2)的解码半径内时,会发生此情况。如果发生此情况,则不会报告读取失败并将损坏的数据返回给用户,就像读取成功一样。
图1说明了三种不同类型的解码事件。显然,成功的攻击只能利用未检测到的解码失败的事件。因此,攻击者必须注入足够的错误以将原始回读模式推入不正确码字的解码半径。 以这种方式,有可能导致真正的数据损坏,但是将这种损坏的模式控制到bit级是不可能的。可以诱发的损坏模式的集合由可通过经由CCI机制或以其他方式翻转写入模式中的比特而可达到的错误代码字的数量来确定。为了描述和总结这一点,从最强到最弱的可能攻击原语可能是:
(1)P1:在可控de 位置翻转单个bit
(2)P2:在块内不可控制地翻转单个bit
(3)P3:对块进行无控制的随机修改(高位翻转,导致无法检测的解码失败)
(4)P4:损坏一个块(读取该块时出错)
对于DRAM的rowhammer 是可以实现P1或P2的,但,由于闪存具备强大的ECC保护, P1和P2在这里不太可能实现。P4极不可能用于提升权限的攻击。 我们将攻击集中在P3上,这是唯一可能成功实现的攻击。
在实施攻击时,FTL操作(如磨损均衡和垃圾回收(GC)引起的闪存页面的写入)以及块放置算法必须考虑在内。传统地,FTL执行磨损均衡是试图使所有的块具有相同的P/E值[5]。由于磨损均衡通常是不经常的操作,因此攻击者可以通过多次重复攻击来缓解磨损均衡对攻击造成的潜在干扰。另一方面,FTL 的GC写入操作在稳定的写入工作负载下可能是用户写入数据的多倍[1,3],因此占总闪存页写入的很大一部分。为了避免GC写入操作对攻击造成干扰,攻击者可以等待足够的时间(通常为几十秒),以便GC操作在攻击开始之前以及完成。这是可能成功的,因为SSD通常在闲置时准备大量空闲以维持用户写入的突发。
为了在闪存芯片级别最大化并行性,SSD通常使用块放置算法,其将到来的写入操作动态地映射到不同的Flash芯片(例如,以循环方式)。 这些块放置算法可以阻止攻击者的攻击,因为写入被攻击页面后立即发生攻击页面写入,可能不会发生在与被攻击页面相同的闪存块中。为了缓解这一障碍,攻击者应该重复写入攻击者页面足够多的时间,最终使其写入到与被攻击者页面相同的闪存块中。
3.2 测试平台
我们的测试平台,如图2所示,包含:带有FPGA和DRAM的PCIe闪存开发板,通用CPU和MLC NAND闪存芯片。NAND闪存的编程,数据扰码器和纠错码(ECC)都在FPGA中完全实现。FTL运行在FPGA和CPU上。开发板连接到运行RHEL 6.7的x86-64服务器上。我们可以完全控制在开发板上运行的硬件和软件堆栈,以及与设备通信的Linux设备驱动程序。
在我们的测试平台中使用的MLC NAND芯片在可靠性方面的研究已经在之前的工作中有介绍到[14,15,16]。在这项工作的背景下,测试平台已被用于验证我们对MLC NAND闪存行为的理解
文件系统层攻击
我们现在详细描述攻击中与文件系统相关的部分(第4层到第5层)。演示本地权限提升的视频:https://www.youtube.com/watch?v=Mnzp1p9Nvw0。成功的攻击需要满足以下约束条件:
(1)R1:目标块的数据损坏应该不会(或以很低的概率)导致致命的文件系统错误,从而阻止攻击并需要管理员干预。
(2)R2:攻击目标应该是经常写的块(为了获得更大的成功机会)。理想情况下,写入应该由攻击者触发。这是为了允许对攻击的第1层到第3层的文件系统攻击进行计时。
(3)R3:目标块的数据损坏应该具有足够的可能性来创建可利用的条件。
(4)R4:新缓存应该被刷新以强制操作系统访问闪存盘中的损坏数据。
4.1 环境搭建
我们使用ext3文件系统在Linux上实施了攻击,并使用默认的安装选项进行安装。文件系统不需要是根文件系统。我们将在第5节讨论这些假设在多大程度上可以放宽和推广。
4.2 攻击
考虑到攻击的限制,我们选择了indirect block作为被攻击的块。
ext3 的indirect block是一个包含数据块指针的文件系统块大小区域,每个大小为4个字节。 因此,在4K块大小的文件系统中,indirect block包含1024个数据块指针(数据块包含文件内容)。 一旦文件大小超过12个块,就会(通过内核文件系统驱动程序)写入一个indirect block:因此这个写入非常容易为攻击者提供提供触发机会。
如果攻击的较低层(第1层到第3层)成功,则indirect block被破坏,对于indirect block中的1024个数据指针中的每一个,有三种可能的结果。
(1)32位数据指针可指向文件系统内部的一个”interesting block”(例如,inode table,root ssh私钥文件,root使用的重要二进制文件):这是唯一可利用的条件。
(2)32位数据指针可指向文件系统内的”uninteresting block “,例如已经属于攻击用户的文件中的数据块。
(3)32位数据指针可指向文件系统外部的块(即:块号≥文件系统上的块数)。 在这种情况下,攻击是不可利用的。 但是,幸运的是,文件系统内核驱动程序只会为相应的数据访问返回一个错误:后续使用相同indirect block的访问仍然可以成功。 如果1024个损坏块中的任何一个指向一个interesting block的块,驱动程序的这种行为对攻击是有效的,这大大增加了攻击的成功概率。
假设被损坏的指针指向一个inode表(可利用的条件)。 然后,攻击者可以通过简单地写入攻击文件(受攻击者控制)来创建(或修改)一个 root 用户所有的inode。 然后,攻击者将这个inode的数据块指针指向一个shell的数据块,最后通过执行攻击文件(现在是一个SUID-root shell,这需要SUID-root shell对应的inod从缓存中刷新)来提升权限,如图3所示。
我们已经证明了R1是符合要求的,因为随机地破坏indirect block不会导致致命的错误。 R2也是符合的,因为攻击者触发indirect block指针的写入(通过简单地向文件中写入足够的字节)。我们现在表明,R3约束(创造充分可利用的条件的概率)也得到了满足。
单个数据指针指向interesting block的概率是p1:
并且任何1/4的块大小的攻击指针指向interesting block的概率是p2:
假设只有inode表对于攻击者而言是”有趣的”,并且具有4 KB块大小的100 GB文件系统,每个inode(缺省值为/etc/mke2fs.conf)16384字节的inode比率为:
因此,假设攻击者在indirect inode成功地使一个数据块崩溃,权限提升攻击将将有9%的概率会成功。 因此,我们认为R3比较符合。
最后,我们展示缓存可以被攻击者刷新(R4)。攻击者需要在两个不同的时间刷新缓存:为了覆盖inode表内容,并执行新创建的SUID-root shell。在第一种情况下,应从缓存中剔除出的缓存数据是indirect block,在第二种情况下,是inode。攻击者自然可以采取两种策略:被动或主动攻击。被动地,攻击者可以等待文件系统被重新安装(例如,在重新启动时),或者系统上的并发活动导致足够的内存压力,以从缓存中驱逐间接块以及随后的inode。主动攻击者触发的路由包括创建内存压力:攻击者只是使用程序分配足够的内存,从而鼓励操作系统从缓存中逐出文件系统元数据。这是我们在演示中采用的方法。 (这种方法的有效性可能会因VFS和页面缓存设置的不同而不同,但在我们的攻击中,RHEL 6.7的默认设置是驱逐有效的)。
4.3 细节探索
我们现在讨论在实际过程中出现的一些细节,但不是攻击的核心。
首先,从上面的描述可以看出,攻击者需要知道一个root shell的数据块号。 尽管可以通过从inode表读取(通过被攻击文件)并识别shell(例如通过时间戳或文件大小)来查找,但这是不太可能的,因为inode表的可读部分不太可能包含root shell。 一个更简单的替代方案是攻击者首先通过在目标文件中创建一个shell的副本,从而让文件系统创建并设置数据块指针,然后设置SUID位并通过直接写入inode table的方式使文件为root所有。
其次,攻击者需要能够识别破坏是否成功,即indirect block指针指向inode table的某处而不是其他地方。 实际上,由于inode表的结构,这很容易实现(例如,具有默认权限的常规文件的标记每256个字节重复一次)。
第三,攻击者可以覆盖现有的inode或将要创建的文件的inode。 如果攻击者对其可以创建的文件数量没有限制(这通常是大多数Linux发行版的默认设置),我们可以假设我们始终处于前一种情况。 然后,攻击者不停创建文件,直到文件系统用完inode(所有inode表已满),然后在文件系统中搜索(例如,使用find)一个SUIDroot文件并执行它:这是在我们的演示中完成的一个攻击方式。 在攻击者可以创建的文件数量上有限制的情况下,虽然我们还没有尝试过,攻击仍然是可能的(通过删除文件,等待inode重新分配给其他用户并创建新文件,直到目标inode被分配给攻击者)。
最后,攻击者可能无法通过文件系统访问现有的inode(例如,它位于攻击者无法访问的子目录中)。在实践中,这仅仅意味着interesting block的数量低于等式3中计算的块数。
4.4 Improved attack using double indirect blocks
针对double indirect block的破坏而非indirect block的破坏可以执行非常类似的攻击。 尽管这种攻击稍微难以解释,但它成功的可能性更高和而且更灵活(对整个文件系统具有完全的读写能力:请注意,这仍然会通过创建SUID-root文件来提升权限)。
double indirect block中的每个4字节指针都指向一个indirect block。 因此,破坏double indirect block可能导致攻击者完全控制indirect block的内容。 通过选择indirect block中的指针,攻击者可以读写文件系统中的任意位置。
这里的可利用条件是double indirect block中的一个指针指向攻击者拥有的块。 例如,攻击者可以在文件系统上创建一个非常大的文件(跨越多个块),以增加某个受损指针受到攻击的可能性。 一旦发生破坏,攻击者可以通过用文件系统超级块的地址(固定块号和可识别的格式)填充大文件来验证他们是否拥有indirect block。 然后,攻击者可以通过读写目标文件来修改大文件的内容以访问文件系统上的任何块:通过写入大文件来控制写或读访问的位置(控制indirect block内容),通过访问目标文件来控制访问内容。
假设攻击者可以在一个块大小为4 KB的ext3文件系统中创建一个100 GB的文件(这是合理的假设),这种改进使攻击的成功概率为99.7%(通过使用公式2获得)。 这是因为interesting block的数量大大增加。
讨论
5.1 其他文件系统
尽管第4节中描述的攻击的很多部分可以被推广,但仍然依赖于使用indirect block的文件系统,如ext3,ext2和某些版本的Unix文件系统(UFS1)。ext4文件系统使用扩展(还要NTFS),从本质上将数据块描述为一个元组(起始文件块,起始磁盘块,块数)。 尽管在ext4中可能有一个”extent block”(超过3个extents,ext4开始在inode之外的新的块中存储extents,从而启动树结构),但我们相信攻击的成功的概率会很低,因为extents的结构更大(即,ext4解析器不会捕获到随机破坏的可能性很小):ext4通常使用48位的块编号空间,而不是ext3的32位)。 因此,这种攻击对其他文件系统是否仍然可行还有待观察。
5.2 元数据checksums
另外,某些文件系统(如ZFS和ext4(但不包括ext3))可以选择使用元数据校验和。 显然,文件系统元数据校验和,无论它们是否使用加密哈希,都可以通过内核文件系统驱动程序检测到文件系统元数据(例如,inode或范围)已被损坏从而显著降低攻击的成功概率。
最后,我们在indirect block损坏后运行e2fsck(一种检查(和更正)ext3文件系统元数据的工具)。如预期的那样,e2fsck成功检测到文件系统元数据已损坏,这将使得管理员检测到此攻击。 当然,e2fsck很少运行,为了阻止攻击,它需要在攻击者获得root权限并能够纠正文件系统元数据之前运行。
5.3 其他攻击
任何直接或间接访问SSD的程序(广义上讲)都可能成为在SSD上进行的非物理的完整性攻击的目标。 在本文中,我们考虑了文件系统,但其他攻击媒介也可能存在。
不幸的是,由于攻击者获得的P3的限制以及攻击的其他限制(R1至R4),我们无法找到另一个真实世界的很可能会被用于特权升级的程序。 然而,我们不能排除这种可能性的存在,需要在这方面进行进一步的研究。
最后,作为一个类似于rowhammer 和Gruss [8]等人的工作。值得考虑的是本文中提出的攻击是否也可以通过浏览器和javascript被远程利用。 由于浏览器确实允许通过Web内容的本地缓存、Cookie或使用HTML5存储API来对文件系统(尽管是间接的)进行写入和读取,因此将此处介绍的攻击媒介扩展到远程攻击可能是可行的。
5.4 加密和完整性
磁盘加密(如dm-crypt)的使用应该可以从根本上防止这里提出的攻击。 更准确地说,磁盘加密不会阻止攻击在第4层到第5层进行(因为攻击者正在覆盖将被操作系统透明加密/解密的元数据)。但是,这将使得攻击者不可能从第1层到第3层的缺陷来获得P3。事实上,正如第3节所述,为了绕过ECC,扰码器的组合和Flash页面只能在在一个方向上编程的限制来获取P3,攻击者需要控制写入磁盘的数据。 但是,通过使用磁盘加密,攻击者很难在不知道加密密钥的情况下这样做。
如前所述,元数据完整性会阻止我们提供的文件系统攻击。我们注意到,除ZFS外,目前的文件系统加密解决方案由于性能方面的考虑,通常不会实现(加密的)文件内容的完整性。
总结
在本文中,我们提出并解决了需要处理的问题,以便利用现实世界场景中的闪存缺陷。 最重要的是,我们展示了基于闪存缺陷的利用场景,利用其破坏文件系统元数据的能力。结合这两个方面形成了一个完整系统的攻击方法,理论的成功率在实践中是足够合理的;
在未来的工作中,我们计划解决克服ECC的步骤,以完成我们的全系统攻击的实施。
全部0条评论
快来发表一下你的评论吧 !