Morpheus: A Vulnerability-Tolerant Secure Architecture Based on Ensembles of Moving Target Defenses with Churn 阅读笔记

今天基本上读完了《Morpheus: A Vulnerability-Tolerant Secure Architecture Based on Ensembles of Moving Target Defenses with Churn》这篇论文。

这篇论文的作者们还搞了个“大新闻”: https://www.solidot.org/story?sid=60517

首先,这篇文章的其中一位作者是Todd Austin,他曾经和Andrew S. Tanenbaum写过《Structured Computer Organization》一书,看起来比较厉害。

这篇论文一开始用一个栈上缓冲区溢出的例子来说明他们观察到的现象:正常的程序利用的是良好定义的程序级的语义,而恶意代码(比如通过栈上缓冲区溢出来执行代码)严重依赖于未定义的语义(或是机器级语义)。

栈上的缓冲区溢出

例如,对于栈上缓冲区溢出的例子,可能需要利用C语言中如下未定义行为:越界的数组访问是未定义的、返回地址存放的位置是未定义的以及代码的位置是未定义的。

这些未定义的语义通常情况下是静态的(twd2的理解是,编译成为机器代码之后就确定了的),于是造成了风险,让有漏洞的程序能够被攻击者利用。这篇论文提出的系统就期望频繁地改变未定义语义的实际表现,从而阻挠攻击者。

这篇论文提出了Morpheus系统,基于开源的RISC-V指令集,结合了“移动目标防御”(MTD, moving target defenses)和搅拌器(churn),来实现上述思想。

上图体现了该系统的大致工作流程,横轴是时间轴:

  • 第一行是传统的攻击流程,首先找到攻击所需的数据,比如gadget的地址,然后进行攻击。
  • 第二行是加入移动目标防御后的攻击流程,找到攻击所需数据的时间增加了。
  • 第三行是再加入搅拌器后的攻击流程,当攻击开始,攻击检测器能够发现有人正在试图攻击(具体如何发现,在后文描述了),并增加搅拌器的工作频率,这样,攻击者每次找到攻击所需数据之前,这些数据已经发生了变化,攻击者必须从头重新开始找。

在介绍系统具体实现以及性能情况之前,假设攻击者有如下能力:

  1. 不能在物理上威胁系统;
  2. 不能修改系统的启动流程;不能预测随机数发生器产生的值;
  3. 通过网络或者键盘等接口与系统进行交互;
  4. 不能修改原始二进制程序;
  5. 可以定位一个内存破坏,或者发现一个可利用的漏洞。

系统具体实现包括标签机制、攻击检测器、两个移动目标防御以及搅拌器。系统架构如下图所示:

Morpheus系统将内存中的数据分为四个不同的“域”,并分别打上标签,对应标签为:代码(C)、代码指针(CP)、数据指针(DP)以及其他数据(D)。

初始标签由编译器得出;通过修改流水线(他们是在一个四级流水线的RISC-V实现上进行的实验),让流水线能够传播标签信息;微架构也进行了修改,来支持标签的存储。

为了获得初始标签,作者实现了两个LLVM的pass。一个pass分析静态初始化的全局变量等,为它们添加标签;另一个pass分析用于初始化栈、堆和.bss段等动态创建的内存的指令并给指令打上标签(twd2的理解是,这样就可以在执行指令时,给对应的动态创建的内存打上标签了)。标签信息存在一个文件中。

对于微架构的修改是给所有寄存器增加了2位的标签,内存中每64位的字也增加了2位的标签(64位的RISC-V的指令是32位的,为此,编译时需要加入合适的nop指令,来使得任意64位的字对应内存都有两条指令)。同样,数据缓存也要相应增加2位的标签。此外,增加了标签缓存,用于优化性能。

这样的标签机制使得所有对于指针的运算,其结果都是指针。twd2的问题是,对于良好定义的指针减法,结果也是指针吗?

有了标签机制,容易实现攻击检测器,只需要在流水线的合适位置(twd2:比如译码阶段?)加入对操作数标签的检查。该系统的攻击检测器会返回两种动作:终止(abort),或搅拌(churn)。标签检查规则和对应动作如下表所示。

值得注意的是,即使搅拌动作对应的规则出现了误报,仅仅多几次搅拌操作,而不会导致良性程序无法执行。这比前人一些工作要好。

两个移动目标防御包括指针偏移以及域加密。

指针偏移将代码和数据分为两个地址空间,DASC和DASD,指向它们的指针分别加上dCODE和dDATA的偏移,如下图所示。

在程序的整个生命周期中,程序看到的指针都是经过移位的,包括寄存器、缓存和内存中的指针。对于微架构的修改是在计算有效地址的偏移的阶段,减去数据指针的偏移dDATA,在计算跳转目标地址时,类似地减去代码指针的偏移dCODE

论文指出,这样的偏移不会损害程序的局部性,没有性能惩罚。论文还指出,这样的偏移能够有完全的60位的熵(偏移量是16字节对齐的,即最低4位为0,这是出于一些考虑)。ASLR等机制由于实际虚拟地址长度的限制以及页对齐的限制,熵没有这么多。

twd2的问题是,现在的共享库都会假设其代码和数据的偏移是固定已知的,从而使用PC相对寻址,那么如果在这个机制中,数据指针偏移和代码指针偏移所用的偏移量不同,那么就破坏了这个假设,为了使得共享库正常工作,就需要做很多(很繁琐的)配套工作。

在处理器跨越L1缓存和L2缓存的边界进行写操作的时候,域加密机制对被保护的数据进行加密,在处理器取指令或读操作的时候进行解密,这样确保了流水线和L1缓存之外的数据是密文,即L2以及DRAM中的数据是密文。可以抵御通过IO、DMA、RDMA或冷启动等方式发起的攻击。

其中,被保护的数据及其对应的密钥包括:代码(KC)、代码指针(KCP)以及数据指针(KDP)。此外,密钥还可以根据用户态和特权态(内核态)分为两组。加密时根据标签和运行状态选择相应的密钥。数据不被加密。

加密算法使用QARMA7-64-σ1,这是一个用于ARM的指针认证技术的加密器,它用电路实现后,延迟较小。加密时,被加密器加密的是地址,然后与数据进行异或来加密数据。这样有两个好处,首先,这样能够使得不同地址的相同数据被加密为不同的密文,此外,这样使得加密器和L2缓存访问可以同时进行,不会增加电路的延迟。

域加密机制

twd2在此处有一个问题,现代的操作系统都会用共享库来优化内存使用,那么引入了这个域加密机制之后,不同的地址空间(也就是进程)要共享相同的一段代码,是否就需要相同的加密密钥了呢?否则,它们就不能共享这段物理内存了。

下面,开始介绍激动人心的搅拌器。

搅拌器通过定期重新随机化相关数据,包括指针偏移的偏移量以及域加密的密钥,来达到其目的。

在搅拌的过程中,一部分数据被处理过,使用了新的偏移量以及密钥,这样的数据的状态叫做“clean”;剩下未被处理过的数据,即使用原来的偏移量以及密钥的数据,其状态叫做“stale”。

搅拌过程如上图所示,分为四个阶段:

  1. 清空流水线,暂停取指令;
  2. 生成新密钥,更新寄存器;
  3. 恢复取指令,搅拌器开始从低地址到高地址一页一页地更新内存,同时维护阈值寄存器;
  4. 搅拌结束。

在第3个阶段,容易发现,搅拌器和程序执行是并行的。事实上,程序访问内存时根据地址和阈值寄存器,选择不同的密钥和移位量。这是因为搅拌器维护了这样四个不变式:

  1. 流水线中的数据(例如寄存器和锁存器中的指令和指针)的状态都是“clean”;
  2. 低于阈值寄存器的地址中的数据的状态是“clean”;
  3. 高于阈值寄存器的地址中的数据的状态是“stale”;
  4. 恰好处于阈值寄存器的地址中的数据,正在被搅拌器处理。

注意到第4点,为了避免竞争,处理器恰好访问到阈值寄存器所对应的内存区域时,流水线暂停。

在搅拌时,同样支持进程上下文切换。切换时,操作系统可以获得搅拌器的上下文信息(包括阈值寄存器、旧的偏移量和密钥、新的偏移量和密钥以及上次搅拌的时间戳)的密文,从而存放至对应进程控制块中。加密搅拌器上下文信息的密钥启动时产生。

Morpheus系统的实验评估在gem5模拟器的RISC-V版本下完成,用DRAMSim2来对内存系统建模,以及测量搅拌等操作的性能。搅拌单元实现为一个有限状态机(FSM),接在L1缓存和L2缓存之间的缓存一致性总线上。

Morpheus微架构配置

实验评估分为安全性分析和性能测试两部分。

第一个安全性测试检测了该系统能否阻止一些攻击手段,包括栈溢出、堆溢出、ROP、堆喷射、格式化字符串、整型溢出以及back-call-site攻击。所有这些攻击的目标都是覆盖返回地址或者某个函数指针。测试表明Morpheus系统可以阻止这些攻击手段,用到的防御如下表所示。

可以看出,更新的攻击需要获得更多信息来绕过之前的防御,所以更容易被Morpheus防住。此外,back-call-site是一个在Morpheus架构被设计好之后提出的攻击,也能够被防护,说明Morpheus能够潜在地防护未来的攻击。

第二个安全性测试估算了破解偏移量和密钥所需要的时间。估算时,搅拌器和攻击检测器被暂时关闭,偏移量和密钥也分别用了单独的一个值。具体而言,作者估算了如下四种情况时,破解偏移量(若有)和密钥(若有)所需要的时间:无任何防御(/E/P)、仅开启域加密机制(E/P)、仅开启指针偏移机制(/EP)以及两个防御同时开启(EP)。估算结果如下图所示:

开启域加密机制后,不能通过memchr()函数来搜索代码,只能使用盲代码搜索方法;开启了指针偏移机制后,需要用AnC地址去随机化方法来破解偏移量。

这两个防御都增加了破解的时间,可以想到,开启周期较短的搅拌器之后,攻击者会有很大麻烦。

接下来的测试是性能测试,测试使用MiBench以及SPEC’06。测试程序由开启O2优化的LLVM编译器编译在RV64IMA平台,链接了Morpheus版本的RISC-V下的musl C库。

首先,作者测试了搅拌周期对减速的影响,如下图所示(时间下面的数字是该搅拌周期比251秒快了多少倍)。

可以看出,随着搅拌周期的增加,速度变慢。特别地,作者认为50ms是一个正常的搅拌周期,在这个周期下,最高的减速是6.71%,对应SPEC’06的403.gcc测例,平均减速为0.84%。

下图是SPEC’06不同测例的结果。

柱子上面的数字是连续搅拌时所能达到的最短周期,因为对于不同的程序,搅拌所需时间也不同。作者分析了403.gcc这一测例,表示更大的减速是因为数据段更大、指针更多以及代码更大。

文章的尾声,作者总结回顾了之前的一些防御方法,并进行了对比,主要有如下三点:

  • 之前的工作使用的加密算法比较弱;
  • Morpheus系统使用了基于硬件的防御,减速低;
  • 之前的系统也采用了标签的方法,用规则来进行防御,但误报会导致良性的程序无法执行;对于Morpheus系统的攻击检测器,其产生误报仅仅会增加几次搅拌周期。
防御方法比较

总结而言,传统的防护手段是寻找并修复软件中的漏洞,而本文提出的系统通过不断地随机化攻击者达成利用所需信息来保护系统。虽然本文针对的是控制流的攻击,但是对于侧信道攻击、时序攻击、Rowhammer攻击以及缓存攻击等其他攻击,也可以找到攻击者所需的信息,并增加这些信息的不确定性来阻止攻击。

发表评论

注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

:wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)

本文链接:https://twd2.me/archives/12012QrCode