随着社会信息化程度不断发展,人们已经习惯于借助计算机工作和处理日常事务。其中,一些机密数据和用户敏感信息如机密工作文档、网银账户和密码等,也都通过计算机进行处理。这些信息一旦泄漏,将造成个人财产的严重损失,甚至危害国家安全。在越来越复杂的网络环境中,木马、后门和恶意监控等安全问题层出不穷,使得防止敏感数据泄漏成为信息安全领域重点研究的问题之一。
在网络计算环境中,信息数据按照其存储介质和数据形态分为4种状态: 内存明文数据、内存密文数据、外设明文数据和外设密文数据。这里的外设也包括网络等数据传输设备。这4种数据形态在处理-存储过程中可以互相转换,如图1所示。实际环境中,因为密文数据不易直接阅读和加工,而且加解密过程需要一定时间开销,所以普通数据以明文形式进行存储或传输,而重要的敏感数据则以密文形式存储和传输。防止机密数据泄漏的重点是如何防止内存中的明文数据流入外部设备中。
机密数据的保护不仅要求这些应用程序对内存中的明文数据进行严格的控制,还依赖于操作系统的安全性。操作系统在为应用程序提供执行环境的同时,也具备控制和访问应用程序内存资源的能力。通用操作系统的大量后门和漏洞层出不穷,致使操作系统被置于可信基之外。
本文研究在应用程序可信、操作系统不可信的环境下,如何有效保护应用程序中的敏感数据。访问控制机制[1, 2]可以限制敏感信息从外设密文状态转化为内存密文状态; 各种加密算法和协议[3]可以限制敏感信息从内存密文状态转化为内存明文状态。这2类方法的结合,能够保证敏感信息只能由特定用户或进程进行操作或访问,但无法阻止敏感信息的明文由于系统和应用程序的漏洞进入外部设备。因此,解决这一问题的关键是防止敏感数据明文进入外部设备。信息流控制技术是解决这一问题的有效方案。已有的信息流控制方法分别在编程语言[4, 5]、 操作系统[6, 7]、 虚拟机[8, 9]和安全硬件[10, 11]等级别实现对内存明文的保护。其中,虚拟机提供了一种对操作系统内核进行限制和监控的手段。但现有的方案通常站在系统研发者的角度,意在通过虚拟机实现对操作系统内核的一种修补,试图设计一种无需修改应用程序即可保护应用敏感数据的方法,往往带来较大的性能损耗。
在实际场景中,处理敏感数据的应用程序通常被精心地编写和审查。如果能够达到更好地保护敏感数据的目的,一定程度的应用程序修改是非常值得的。
本文设计了一种基于虚拟机的运行时应用敏感内存管理(sensitive memory manager,SMM)系统,通过虚拟机为应用程序提供可信的内存空间,再利用虚拟机的影子页表机制,使这部分可信内存空间对操作系统内核不可见,从而达到保护应用敏感数据的目的。应用程序的参与使得敏感数据和普通数据区分更加准确,实现细粒度保护的同时降低对系统性能带来的副作用。
1 敏感数据保护架构 1.1 攻击模型与假设本文关心的场景为应用可信、操作系统不可信的情况,攻击者的目标为窃取应用程序中的敏感信息。本文假设攻击者并不能物理上接触到计算机,无法拆卸硬盘进行分析,也无法改变硬件连接方式以监听外设总线和内存总线。本文主要针对的攻击方式为: 攻击者通过操作系统后门或漏洞,修改或利用部分内核代码,访问正在运行的应用程序内存中的敏感数据。本文假设攻击者通过操作系统的后门或漏洞可以任意修改系统内核,但不考虑由于这些修改造成了系统内核的崩溃或拒绝服务,并没有造成敏感信息泄漏的情况。
图2中,有2种方式访问内存中的敏感数据: 路径A是直接由系统内核代码访问应用程序的内存空间; 路径B是在系统内核中修改应用程序的代码,再由系统内核控制跳转至修改过的代码执行,访问应用程序的内存空间。实际上系统内核的一些正常功能也通过上述2种行为实现,因此解决方案不能是简单地禁止这2种行为。
最后,本文假设硬件环境是可信的,不存在硬件层的后门和木马,从开机到虚拟机启动的过程能够受到可信基保护[12, 13]。这样,其上运行的虚拟机才可以被信任,完成保护敏感数据的任务。
1.2 SMM系统架构通过上述对问题假设及攻击模型的分析可以总结出,SMM要解决的关键问题有3个: 1) 定义敏感数据范围; 2) 阻止被入侵内核中的恶意代码访问敏感数据(路径A); 3) 阻止被内核污染的用户态恶意代码访问敏感数据(路径B)。为解决这3个问题,本文设计的SMM系统架构见图3,主要包括4个功能模块。
1) 请求处理模块。
本文采取应用程序定义敏感数据的方式: 由应用程序向SMM系统提出内存申请,SMM系统向应用程序提供被保护的内存空间(以下称为敏感内存),由应用程序负责将敏感数据存放在敏感内存中。应用程序的参与能够更精确地定义出哪些数据属于敏感数据,同时降低保护敏感数据所带来的性能损耗。
应用请求模块负责处理应用程序对敏感内存的请求,包括申请和释放这2个工作流程。由于申请和释放请求都是由应用程序提出的,提出请求时处理器还处于用户态,因此无需对敏感内存进行隐藏。
2) 状态监测模块。
为阻止攻击者利用内核发起的入侵,本文希望应用程序运行时能够访问敏感内存,在内核运行时则阻止其对敏感内存的访问。为此,首要任务是区分处理器正处在用户态还是内核态。
状态监测模块负责监测处理器运行的状态,并拦截处理器在用户态和内核态之间切换的过程。拦截到有状态切换发生时,分别交由内存隐藏模块和代码保护模块进行适当处理,再进行正常的状态切换。
3) 内存隐藏模块。
内存隐藏模块负责向内核隐藏敏感内存,阻止经由路径A的攻击。当处理器由用户态切换为内核态时,状态监测模块通知内核隐藏模块隐藏敏感内存,使之不可被访问; 当处理器由内核态切换为用户态时,状态监测模块通知内核隐藏模块恢复敏感内存,使之能够被访问。
路径A攻击会使得恶意代码访问到没有敏感数据的替身内存空间,可以保持应用程序持续执行。值得注意的是,如果内核试图直接跳转到应用的代码对敏感数据进行访问,此时处理机状态仍为内核态,也属于路径A攻击,同样会访问到替身内存。
这种内存隐藏同时带来的结果是,敏感内存将不能作为系统调用的参数交由内核进行处理。应用程序编写者应当注意该情况。
4) 代码保护模块。
代码保护模块负责保护应用程序的代码不被内核篡改,阻止经由路径B的攻击。重点关注2种情况: 1) 客户机内核通过修改返回到用户态的地址,执行访问敏感数据的代码; 2) 客户机直接修改返回到用户态的代码。
针对情况1,当处理器由用户态切换为内核态时,记录应用程序的执行位置; 当处理器由内核态切换为用户态时,检查返回应用程序的位置是否一致。针对情况2,需保障客户机在内核态不会修改应用程序的代码。与内存隐藏模块类似,可以将应用程序的代码对内核隐藏起来。
如果发现有返回地址不一致或修改应用代码的情况,则很有可能遭到了路径B攻击,SMM系统将立即关闭应用程序,并通知用户对内核进行检查。要使该方式不存在误报,须保证3个前提条件: 一是从用户态进入内核态时不会修改现有代码; 二是从用户态进入内核态时并不加载新的代码; 三是从内核态返回用户态时会回到用户态原代码位置。第1个条件对正常的系统内核来说是显然满足的; 针对第2个条件,应用程序需要在完成所有动态链接库的加载后再向SMM系统申请敏感内存,SMM系统仅对正在使用敏感内存的应用程序进行代码保护,这点并不难满足; 针对第3个条件,使用SMM系统的应用程序将不允许使用自定义信号处理,而当前的应用软件中实际上已经极少使用自定义信号处理了。
2 SMM系统实现尽管图3的系统架构中,SMM系统处于应用程序与操作系统内核之间的位置,拦截用户态与内核态之间的切换,但在内核之上进行拦截则与应用程序一样很容易受到来自内核的攻击。虚拟化技术提供了内核之下的软件层次,不易被受到来自内核的攻击,但也为拦截操作带来一定的问题。内存地址转换是其中的关键问题之一。
现有的内存虚拟化的地址转换主要有基于硬件和软件这2大类方法: 基于硬件的代表性方法包括Intel的扩展页表(extended page table)技术和AMD的嵌套页表(nested page table)技术。它们利用硬件机制,在客户机操作系统将客户机虚拟地址(guest virtual address,GVA)转换为客户机物理地址(guest physical address,GPA)后,再由宿主机负责将其转换为宿主机物理地址(host physical address,HPA)进行实际访问。基于软件的代表性方法是影子页表(shadow paging)技术。它基于软件模拟,直接将GVA变换为HPA,并通过拦截客户机修改页表时会使用的特权指令(如INVLPG和CR3读写操作等),在客户机系统试图修改页表时进行同步的修改操作,使得客户机的页表实际上不起作用。嵌套页表技术的实现简单,影子页表技术则更为灵活。DAV2M[14]通过大量基准测试发现这2种技术在不同的测试用例下各有优劣。
为了完全控制客户机内存,SMM原型系统采用影子页表技术,基于Qemu/KVM系统虚拟化方案实现。为方便评测,目前主要针对Linux客户机,且只考虑单虚拟处理器(vCPU)的情形,但该系统进行少量更改也可以用于Windows和Unix等其他类型的客户机。
2.1 内存申请与释放请求处理模块的关键问题是虚拟机管理器如何越过系统内核直接为应用程序提供内存申请与释放服务。为此,SMM系统通过虚拟机管理器提供的超调用(hypercall)机制为应用程序提供向SMM系统申请和释放内存的函数,分别为hymalloc()和hyfree()。
需要注意的是,hymalloc()并不能直接通过超调用将HPA存映射到被保护进程的GVA。这样做的后果是客户机内核并不知该进程的虚拟地址被占用。如果这时应用程序再调用其他的内存分配函数,则客户机系统内核可能再次分配该地址。尽管在影子页表机制下,客户机内核为GVA映射GPA的行为是无效的,但此后再次申请内存时返回的地址实际上是之前分配的敏感内存会造成应用程序的逻辑错误。
因此,hymalloc()的实现过程中须先向客户机内核申请内存空间,再使用超调用将这块内存空间映射为敏感内存。由于影子页表机制的内存管理粒度是页粒度,这就要求被保护的应用中向SMM系统申请保护的内存地址是页对齐的。为避免浪费虚拟地址空间,hymalloc()实现时使用了页对齐的客户机内存申请函数posix_memalign()。
反之,hyfree()函数则应先通过超调用向SMM系统提出释放请求,再向客户机内核提出释放请求。
2.2 上下文切换状态监测模块的关键问题是如何在虚拟机管理器中拦截用户态与内核态之间的切换。虚拟机管理器并未直接提供拦截这种切换的方法,SMM系统使用页式寻址中的不可执行(NX)位所引起的特殊缺页异常方式进行拦截。
在被保护的应用程序首次申请敏感内存时,处理器处于用户态,SMM系统通过CR3寄存器找到当前进程的页表,将其中内核态内存页设置为不可执行。内存页属于内核态还是用户态可以通过对应页表项中的U/S位来判断,也可以通过GVA来划分。将所有内核态页表项的NX位置1后,任何尝试跳转至内核态地址执行的行为都会产生缺页异常,虚拟机管理器可以捕获该缺页异常。SMM系统通过缺页异常的错误码进行判断,从而捕获从用户态到内核态的切换。
SMM系统的状态监控模块拦截到从用户态到内核态的切换后,再利用同样的原理,将用户态页表项的NX位置1,将内核态页表项的NX位置0,就能够捕获下一次从内核态到用户态的切换。
另外,SMM系统主要关注被保护的进程空间内部的用户态与内核态切换。一般性的进程切换也有可能造成上下文切换,并影响对用户态与内核态之间切换的判断,但实际系统中的进程切换只能在2个进程的内核态之间进行,因此进程切换对SMM拦截被保护进程的用户态与内核态之间的切换并没有影响。
2.3 内存页隐藏隐藏单个内存页是内存隐藏模块功能的基础。基本思想是通过拦截上下文切换,为用户态映射敏感数据页,为内核态的相同GVA映射替身页,使得客户机内核试图访问敏感数据的行为实际上会访问到替身页。
影子页表越过GPA,直接完成GVA到HPA的地址变换,也就使得客户机内核看到的GPA实际上是无效的。这为SMM系统的内存隐藏提供了便利,也是本文选择影子页表技术的原因之一。
在节2.1中,出于效率原因,SMM系统在应用程序使用hymalloc()申请敏感内存时,并不立即分配内存,仅记录已申请过的GVA,等待缺页异常时再进行映射。如果客户机内核在此之前尝试访问敏感内存,SMM系统就会根据引发缺页异常的位置进行判断。但一旦应用程序访问了敏感内存,SMM系统就完成了为GVA映射HPA的工作,此后客户机内核尝试访问敏感内存就不会造成缺页异常了。
在节2.2中,为完成拦截上下文切换的功能,SMM系统已经为用户态和内核态配置了2套页表。要使应用程序可以访问的内存不被客户机系统内核访问,只要在内核态的页表项中填上替身页即可。
上述几个关键问题的解决最终都依赖于对影子页表的设置和缺页异常的判断,形成了SMM系统缺页异常处理中复杂的代码逻辑。为便于理解,也便于代码编写和调试,本文借助了有限状态自动机工具。图4给出了SMM系统运行过程中的状态自动机,表1为图4中各状态的意义,其中由状态2到状态4的切换实际上是内核的一种攻击行为。根据状态自动机,图5则给出了缺页异常的判断流程,从中能够更清晰地看出上述关键问题的解决步骤。
代码保护模块的主要任务是保护应用程序代码不受客户机内核的恶意修改。虽然为每一段代码计算完整性校验值的方法更安全,但时间开销较大。SMM系统采取了如下的防护方案: SMM系统通过访问客户机的ESP寄存器,可以找到当前客户机进程的进程控制结构task_struct,其中包括内核管理应用内存与文件映射的相关结构mmap。mmap结构中记录了每一块与文件映射的内存区,其中包括应用程序及每个动态链接库的代码区和数据区,一般只读可执行的内存区为代码区,可读可写的内存区为数据区。
在应用进程加载和动态链接过程中,客户机系统只会生成mmap结构,并不实际分配内存,待到缺页异常发生时再进行内存分配和文件读取。
通过拦截上下文切换,在内核态向用户态切换时,SMM系统将检查内存/文件映射表并进行记录。如果出现代码区被修改为可写的情况,则提示发生路径B攻击。
缺页异常发生时,如果需要进行内存分配和文件读取,针对代码区SMM系统将只操作保存的2套页表中为用户态使用的页表,针对数据区SMM系统则正常对2套页表进行同步操作。
3 有效性评测本节利用Twrite、 Tmap和Tsignal这3个程序来验证SMM系统各主要模块的有效性。
3.1 TwriteTwrite程序首先利用hymalloc()向SMM申请一个页大小的敏感内存,将该页中的每个字节都设置为‘a’,再通过系统调用write()将该页中的内容写入文件。
执行结束后,发现写入的文件中内容都为0。
这是因为write系统调用通过copy_from_user()来访问敏感内存页,但SMM系统给内核映射的物理内存页并非敏感内存页,而是替身页。于是,写入文件的是替身页中的内容。
这一测试说明了SMM系统的内存隐藏模块可以发挥作用,可以有效阻止在系统内核中试图通过路径A攻击访问敏感内存数据的行为。
同时,也提示使用SMM系统编写应用时需要注意不能将敏感数据的指针作为系统调用的参数进行处理。符合SMM系统不让敏感数据进入外存的设计初衷。
3.2 TmapTmap是一个内核模块,它试图获取指定进程中的敏感内存。
测试前先启动一个类似Twrite的测试程序,并保证其申请一个敏感内存页后进入死循环。Tmap的攻击是通过目标进程的页表获取到堆中映射好的客户机物理内存页,再利用kmap_atomic()函数将该物理内存页映射到内核空间,从而读取其中的数据。
结果表明,Tmap读取到的数据内容为0。这是由于Tmap内核模块运行在内核态,只能访问SMM系统提供的替身页。
加载内核模块是Rootkit等恶意代码修改内核的常用手段。这一测试说明了SMM系统的内存隐藏模块可以阻止各种形式的从内核态访问敏感内存的尝试。
3.3 TsignalTsignal程序则定义自定义信号处理函数,并向自己发送该信号。实验结果表明,Tsignal程序异常退出。
这是由于SMM系统检测到发送信号的系统调用时的EIP寄存器与从系统调用返回用户态时的EIP寄存器不一致,SMM系统的代码保护模块发生作用强制退出了Tsignal程序。
这一测试实际上利用了自定义信号处理函数会修改返回用户态地址的行为,说明进入内核态后试图修改返回用户态地址的行为将被SMM系统的代码保护模块发现并阻止。
同时,也提示使用SMM系统编写应用程序时不能使用自定义信号处理函数功能。尽管自定义信号处理函数提供了一种灵活的事件处理机制,但实际应用中已经很少使用,图形应用中的各种消息机制是通过select()和poll()等新的事件响应机制实现的。现存的信号机制一般仅作为系统通知,无需自定义处理函数。
综合以上3个测试结果,说明SMM系统系统的内存隐藏模块和代码保护模块能够有效发挥作用,防止系统内核通过路径A或B对敏感信息的访问。
4 性能评测评测所使用的主机型号为联想扬天T4980d-10的台式机。宿主机和客户机都采用CentOS 6.5,为更好地支持虚拟化特性,将宿主机内核替换为Linux 3.12.14 ,Qemu版本为1.7.1。SMM对宿主机系统中的KVM模块进行了修改扩充。
4.1 微操作本节主要测试在SMM系统中执行申请和释放内存操作的性能损耗,结果如表2所示。尽管hymalloc/hyfree的运行时间比malloc/free高出近2个数量级,但其绝对时间仍可接受。此外,如果应用程序能够进一步配合SMM系统,将应用中所需的敏感内存一次性全部申请,则这部分时间开销可以忽略不计。
事实上,hymalloc()中调用了与malloc()相似的posix_memalign()函数,它们的平均执行时间的差值主要由超调用本身引起。超调用导致虚拟机上下文切换,在前述测试环境中,每次超调用的最小代价约为0.74 μs。
4.2 实例测试本节使用更为实际的应用场景进行测试。由于SMM系统需要应用自行指定要保护的敏感内存,简单地使用标准测试用例进行测试将不会发生hymalloc()和hyfree()的调用,实际上不会发挥SMM系统的作用。
因此,本节的实验模拟读取密文进行解密处理再加密的过程编写了测试应用,输入为密文文件,输出为使用新密钥的密文文件,具体流程为:
1) 调用malloc()或hymalloc()分配内存;
2) 读取密文文件内容到普通内存;
3) 解密算法,将普通内存中的密文内容解密到敏感内存中;
4) 执行加密算法,将敏感内存中的明文加密到普通内存中;
5) 将普通内存中的新密文写入新密文文件。
其中,加解密算法分别选取DES和TEA这2种方法进行实验,初始的密文文件大小选取不同的数值,测试执行的总时间。
测试结果如图6所示,纵坐标为SMM系统相对于原系统的性能比,保护内存大小即为密文文件的大小。可以看出,随着保护内存容量的增大,SMM系统带来的性能损耗逐渐减小。在保护内存大小达到64 MB以上时,SMM系统的性能损耗几乎可以忽略。其中,DES算法相比于TEA算法的运算过程更加复杂,可见SMM系统对运算密集型应用带来的性能损耗更小。
相比已有工作,SP3[8]对较小的测试程序只会带来3%左右的性能损耗,但当应用程序循环访问较大内存时,性能下降明显,循环访问4 MB内存时性能下降15%,循环访问16 MB内存时,性能已经下降2倍以上。OverShadow[9]的性能损耗与系统调用次数相关,对于大数据量访问的测试应用,性能将下降为原有的一半以下。可见,SMM系统的性能损耗与文[8—9]方法的相当甚至更低。
5 结 论本文对利用内核后门和漏洞窃取应用敏感信息的攻击方式进行建模分析,设计并实现了SMM系统。该系统通过虚拟化技术,使得应用程序能够直接向虚拟机管理器申请受保护的内存空间用来存放敏感信息,并利用影子页表技术为客户机的用户态和内核态生成不同的内存映射,达到阻止操作系统内核访问应用程序声明的敏感内存的目标。有效性测评和性能测评结果表明: SMM系统提供的内存保护粒度更小,带来的性能损耗更小。
[1] | 李洋. Linux安全策略与实例[M]. 北京:机械工业出版社, 2009.LI Yang. Linux Security Policy and Example[M]. Beijing:China Machine Press, 2009.(in Chinese) |
[2] | Pfleeger C P. Security in Computing.[M]. 4th ED. Upper Saddle River, NJ, USA:Prentice Hall, 2006. |
[3] | 范九伦, 刘宏月. 密码学基础[M]. 西安:西安电子科技大学出版社, 2008.FAN Jiulun, LIU Hongyue.Foundations of Cryptography[M]. Xi'an:Xidian University Press, 2008.(in Chinese) |
[4] | Sabelfeld A, Myers A C. Language-based information-flow security[J]. IEEE Journal on Selected Areas in Communications, 2003, 21(1):5-19. |
[5] | Xu W, Bhatkar S, Sekar R. Taint-enhanced policy enforcement:a practical approach to defeat a wide range of attacks[C]//15th USENIX Security Symposium. Vancouver, Canada:USENIX Association, 2006, 9. |
[6] | Zeldovich N, Boyd-Wickizer S, Kohler E, et al. Making information flow explicit in histar[C]//Proceedings of the Symposium on Operating Systems Design and Implementation. Seattle, WA, USA:USENIX Association, 2006:263-278. |
[7] | Efstathopoulos P, Krohn M, VanDeBogart S, et al. Labels and event processes in the asbestos operating system[C]//Proceedings of the ACM Symposium on Operating Systems Principles. Brighton, UK:ACM, 2005:17-30. |
[8] | Yang J, Shin K G. Using hypervisor to provide data secrecy for user applications on a per-page basis[C]//Proceedings of the fourth ACM SIGPLAN/SIGOPS International Conference on Virtual Execution Environments. Seattle, WA, USA:ACM, 2008:71-80. |
[9] | Chen X, Garfinkel T, Lewis E C, et al. Overshadow:A virtualization-based approach to retrofitting protection in commodity operating systems[C]//Proceedings of the 13th International Conference on Architectural Support for Programming Languages and Operating Systems. Seattle, WA, USA:ACM, 2008:2-13. |
[10] | Dalton M, Kannan H, Kozyrakis C. Raksha:A flexible information flow architecture for software security[C]//Proceedings of the 34th Annual International Symposium on Computer Architecture. San Diego, CA, USA:ACM, 2007:482-493. |
[11] | Chen Y Y, Jamkhedkar P A, Lee R B. A software-hardware architecture for self-protecting data[C]//Proceedings of the 2012 ACM Conference on Computer and Communications Security. Raleigh, NC, USA:ACM, 2012:14-27. |
[12] | Champagne D, Lee R B. Scalable architectural support for trusted software[C]//Proceedings of the 16th IEEE International Symposium on High-Performance Computer Architecture. Bangalore, India:IEEE Press, 2010:31-42. |
[13] | McCune J M, Li Y, Qu N, et al. TrustVisor:Efficient TCB reduction and attestation[C]//Proceedings of the IEEE Security and Privacy. Oakland, CA, USA:IEEE Press, 2010:143-158. |
[14] | Bae C S, Lange J R, Dinda P A. Enhancing virtualized application performance through dynamic adaptive paging mode selection[C]//Proceedings of the 8th ACM International Conference on Autonomic Computing. Karlsruhe, Germany:ACM, 2011:255-264. |