【论文全称】Cache-in-the-Middle (CITM) Attacks : Manipulating Sensitive Data in Isolated Execution Environments
CITM Attacks
ABSTRACT
-
IEEs: Isolated Execution Environments —— 在普通世界(NW)保护安全敏感应用程序
-
本文贡献:
- 发现三种基于缓存的攻击(CITM) —— 针对 IEE数据保护模型 和 ARM缓存属性
- 可行性测试(主要针对SANCTUARY、Ginseng和TrustICE)
- CITM攻击原因及对策分析(实验表明,本文方法开销较小)
-
CCS概念:
- Security and privacy → Systems security
- Computer systems organization → Architectures
1 INTRODUCTION
-
TrustZone作为一种硬件辅助技术,将平台划分为两个执行环境: 正常世界 (非安全世界)和 安全世界 ,其中
- 正常世界 (NW)负责在rich Os上运行正常的应用程序
- 安全世界 (SW)保护安全敏感的代码和数据
-
TrustZone的传统用法是 在安全的环境中 运行安全敏感的应用程序 并存储它们的敏感数据,(也就是把这些敏感操作都放到安全世界中去),如图:
-
这便是 可信执行环境 ( TEE )系统,其中安全敏感的应用程序在这里被实现为 可信应用程序 ( TA ),运行在安全世界(SW)中。
- (例:三星KNOX、OP-TEE、高通QSEE、华为安全操作系统)
- TEE解决方案依赖于 内置的硬件支持 来实施安全隔离,并防范来自不可信的rich Os的攻击。
- 问题:设备制造商 和 第三方安全敏感的应用程序开发人员 存在 需求冲突 。(就是制造商不想打开SW让你安第三方APP,他们更信任自己的TA,但第三方APP想进入SW以求安全可信)
-
为此,研究人员建议在正常世界中创建 孤立的执行环境 (称为 IEE ),如图1:
-
关键点:在安全的世界中使用可信参考监视器(例: IEE监视器 ),确保只有经过授权的IEE应用程序(即运行在IEE中的安全敏感应用程序)才能访问相关的IEE敏感资源,从而保护一个IEE中的安全敏感应用程序不受其他IEEs和rich OS的影响。
- TrustICE 依赖于IEE监视器,通过动态控制IEE内存的安全属性来保护IEE内存。
- Ginseng 构建了IEEs来保护正常世界中的第三方应用程序的秘密,而不需要在安全世界中部署任何特定于应用程序的逻辑。
- SANCTUARY 将其IEE分配为per-core环境,以确保在正常世界中,为IEE指定的内存(以下简称IEE内存)不被任何其他非安全的内核访问。
-
IEE优缺:
- 用“ switch out ”来表示一个内核的上下文从IEE切换到不可信的rich OS的进程;用“ switch in ”来表示每个内核上的逆向进程。
- IEE系统能够最大限度地 减小SW的TCB :仅在SW中安装IEE监视器即可将安全敏感应用程序转移到NW中。
- IEE系统具有 可移植性 ,表现在:安全敏感的应用程序是在NW中安装和执行的。
- 但安全敏感的应用程序是由软件组件(例:IEE监视器)隔离和保护的,故IEE系统可能无法达到与TEE系统相同的安全保护级别。
-
CITM可以操纵IEE保护的敏感数据(以下简称IEE数据)。
- 首先,在并发执行时,通过 跨核缓存 操作来操纵IEE数据。
- 在多核平台上,防范并发运行的不可信的rich OS,仅确保在IEE内存上进行core-wise isolation是不安全的,因为缓存可能仍然对跨核访问开放,从而受到攻击者的操纵。
- SANCTUARY :在并发执行过程中,攻击者通过跨核L1缓存操作成功窃取和修改SANCTUARY系统的IEE数据。
- 其次,操纵IEE内存的 非安全缓存映射 绕过其安全保护措施。
- 当一个安全敏感的应用程序被挂起或完成时(即在“switch out”过程中),IEE系统必须采取一些安全措施来保护IEE数据,防止以后被rich OS访问。
- 然而,攻击者可以通过操纵到用于安全措施的IEE内存的非安全缓存映射来绕过这些安全措施。
- Ginseng :绕过“switch out”过程中强制执行的安全措施,窃取Ginseng系统的IEE数据。
- 第三,在“ switch out ”过程中 窃取 IEE敏感数据,并在“ switch in ”过程中 篡改 IEE数据。
- 当IEE内存保护是通过动态地控制内存的安全属性(例如,配置它在“switch in”前不安全,而在“switch out”前安全),缓存存在不完整的安全保护。
- TrustICE :利用在环境交换过程中没有得到很好保护的环境交换内存的非安全缓存,窃取和篡改TrustICE系统的环境交换数据。
- 首先,在并发执行时,通过 跨核缓存 操作来操纵IEE数据。
-
IEE系统中广泛存在的CITM攻击。除了主存之外,安全保护缓存对于确保IEE数据的安全性也很重要。
-
根本原因:缓存和内存之间的安全相关属性不一致,缓存和内存之间的读写操作不同步。
-
解决方案的主要思想:安全配置IEE内存的缓存属性;在环境切换期间,清除到IEE内存的缓存映射。
-
开发板:i.MX6Quad Sabre
-
贡献:
- CITM攻击可能被误用来窃取和篡改IEE系统中的敏感数据。
- 设计一个独立的执行环境时,内存和缓存要同时考虑。
- 提出了减轻CITM攻击的对策。
2 BACKGROUND
首先介绍ARM TrustZone硬件安全扩展,然后讨论ARM处理器上的缓存架构。(还包含三个IEE系统:SANCTUARY、Ginseng、TrustICE)。
2.1 ARM TrustZone
- TrustZone是自ARMv6体系结构以来的一种安全扩展,为安全的代码执行提供了基于硬件的隔离环境。
- 安全性表现在世界划分,包括处理器、内存和外设在内的资源,将其划分到安全世界或是正常世界。
- 如图所示,
在正常环境中,普通用户应用程序运行在rich OS上,
而安全环境则运行少量可信应用程序和可信操作系统。
- TrustZone将物理DRAM(主存)划分为两个分区——安全内存和非安全内存。
- 非安全内存可以被正常世界和安全世界访问,
- 而安全内存只能被安全世界访问。
- (也就是只对安全内存加了限制。非安全内存被谁访问都行,但安全内存只能被安全世界访问)
- 硬件外设—— TrustZone地址空间控制器(TZASC) ——实现了内存分离,将整个内存地址空间分割成几个内存区域。
- TZASC允许每个区域将自己的安全属性指定为安全或不安全。
- 最新的TZASC模型TZC-400引入了一个新的安全控制特性——Identity-based Filtering,用于分离非安全内存区域。
- 在ARM系统中,每个设备(如CPU、GPU、DMA控制器等)充当总线主机,并被分配一个唯一的非安全访问标识符(NSAID)。
- TZC-400配置了一个非安全内存区域,仅可被 基于它们自身NSAID的特定设备 访问,而阻止其他设备对该区域的访问。(也就是用一个标识符实现对内存区域的访问控制)
2.2 ARM Cache Architecture
- cache(高速缓存)是处理器上用于缓冲内存数据的组件。
- 大多数现代ARM处理器配备了两级缓存——一级缓存(L1 cache)和二级缓存(L2 cache)。
- L1 cache 进一步分为指令高速缓存(I-cache)和数据高速缓存(D-cache)。
- L2 cache 是统一的,保存指令和数据。
- L1和L2缓存都组织为N-way Set Associative Cache。
- 整个缓存空间被分成N个大小相等的部分,称为 way ;
- 每种way都用k条 cache lines 进行索引;
- 每个 line serves 作为 保存在cache中的数据单位;
- 同时,来自所有way的 具有相同索引的 cache lines 组成一个 cache set 。
- 为了将内存映射到缓存,将内存划分为block(块),每个块的大小与一条cache line相同。
- 内存的块 i i i 可以被加载到任何属于cache set ( i m o d k i \mod k imodk ) 的cache line中。
- 注:cache line大多是物理索引,物理标记(PIPT)。
- 缓存结构分为两个域——内部缓存域和外部缓存域。
- 内部缓存域是指在特定CPU核内配置的缓存(例:L1缓存,通常被一个核独占);
- 外部缓存域是指在CPU核外配置的缓存(例:L2缓存,通常被多个核共享)。
- 每个可缓存的域使用四个属性配置——non-cacheable, write-back, write-through 和 write-allocate。在内存页上配置属性。(缓存行为由属性确定)
- 当内存页为一个 可缓存域 配置 non-cacheable 时,对内存页的任何读写操作都不会通过该可缓存域。
- 当将内存页配置为 write-through 或 write-back 时,该可缓存域是可缓存的。
- write-through 属性还意味着 将当前级别缓存上的任何写操作立即转发到下一级别存储。
- 例:L1缓存上的写操作将被转发到L2缓存,L2缓存将被转发到主存。
- write-back 属性意味着 change操作仅被缓冲在当前级别的缓存中,而下一级别的存储只能在缓存回收时更新。
- 当写事务发生cache miss时,如果可缓存域设置为 write-allocate 属性,将分配一个新的cache line来保存写结果;否则,cache-missed write操作将对下一级存储进行修改。
- write-through 属性还意味着 将当前级别缓存上的任何写操作立即转发到下一级别存储。
- 注:当内部可缓存域和外部可缓存域都设置了相同的属性时,简单起见,本文省略了可缓存域属性(也就是省略‘外部’或者‘内部’)。
- 除了缓存属性的设置,ARM缓存的状态还会受到其他维护操作的影响,比如 invalidation 和 cleaning 指令。
- 当执行 invalidation 指令时,它直接使保存在缓存中的数据无效。
- cleaning 指令将目标缓存的内容转发到下一级缓存或主存。
- 对于支持TrustZone的ARM处理器,所有级别的缓存都扩展了一个额外的标记位(即图2中的NS位)来记录它们的安全状态。
- 当从正常世界访问内存时,相应的cache line将设置为非安全的;
- 当从安全世界访问内存时,相应的cache line将被设置为安全的。
- 另外,cache line的NS位是由硬件自动设置的,软件不能修改。
2.3 IEE Systems
- 在IEE中运行的安全敏感的应用程序可以是一个代码片段、一个函数、一个应用程序或一个系统,使其敏感数据受到很好的保护,不受不可信的 rich OS 的攻击。
- 现状:现有的IEE系统更多地关注于保护容纳IEE敏感数据的主存,而在IEE系统中缓存的安全性还没有得到很好的研究。针对三个IEE系统——SANCTUARY、 Ginseng和TrustICE——展开。
- SANCTUARY支持在IEE上运行敏感apps和微内核,同时在多核平台上运行 rich OS 。
- 每个IEE被分配运行在一个具有 core-isolated 内存的专用核上,并且IEE的执行不能被其他不安全的核中断。
- 为了防止基于缓存的攻击,微内核会在IEE环境切换的过程中(即在IEE终止之前或在敏感应用程序加载之前)清理L1缓存。
- 另外,对于运行IEE的核心,L2缓存是禁用的。
- 由于L1缓存位于每个核内,不能直接从其他核访问,因此在IEE运行期间,SANCTUARY不会对L1缓存提供额外的保护。
- Ginseng是一个IEE系统,可以在多核平台上保护选定功能的敏感数据。
- 为了防止恶意操作系统的并发运行,敏感数据仅存储在寄存器中进行处理,其他核无法访问这些寄存器。
- 由于敏感数据只存储在寄存器中,而不是核心隔离的内存中,Ginseng对缓存没有提供保护。
- TrustICE是一个在单一核心平台上实现的IEE系统,在这个平台上IEE和不可信的 rich OS 不能同时运行。
- 在一个IEE上运行的安全敏感应用程序,由用户程序和微内核组成。
- 利用内存来存储和处理敏感数据,通过动态配置IEE内存的安全属性来实现敏感数据保护,即在IEE运行时将分配给IEE的内存设置为非安全,否则设置为安全。
- 缺乏对缓存的保护。
3 THREAT MODEL
- 假设:
- 正常世界的 rich OS 均不可信,
- 具有root特权的攻击者旨在破坏IEE中敏感数据的保密性和完整性,即窃取和篡改EE中的敏感数据。
- ARM TrustZone技术可信,在正常世界和安全世界之间提供安全隔离。
- 在安全世界中运行的软件(例如IEE监视器)可信,并且不被 rich OS 所破坏。
- 在IEE中运行的安全敏感应用程序不会故意向外界公开其敏感数据,且IEE监视器保护其代码。
4 CITM ATTACKS
本节包括IEE系统中的两种通用数据保护模型、三种基于缓存的CITM攻击、缓存锁定技术。
4.1 IEE Data Protection
两种通用的数据保护模型 保护IEE数据 分为两种情况
(ⅰ)在正常世界,允许不可信程序与安全敏感应用程序同时运行;
(ⅱ)当一个安全敏感应用程序在正常世界运行时,暂停所有不可信程序。
-
Model 1:在NW中,不可信程序可以在两个(或多个)不同的核上与安全敏感的应用程序同时运行。
- 在多核平台上,在NW中,当安全敏感的应用程序运行在一个核上时,不可信程序(例:不可信的 rich OS )可能同时运行在不同的核 / 以 time-sharing 方式运行在同一个核上。(就是要么并行,要么串行)
- 这种IEE系统通常有三种安全措施来保护其敏感数据:(控制对 core-isolated 存储的分配)
- 为每个安全敏感的应用程序分配 core-isolated 存储,以便在并发执行期间处理其敏感数据。(为一个核分配的内存,不能被其他核访问,或者像寄存器那样进行 on-core 存储)
- 当一个安全敏感应用程序被挂起或完成时,在“switch out”进程期间,通过清理 core-isolated 存储,保护其所有敏感数据不受不可信程序影响。
- 当一个安全敏感的应用程序被恢复或启动时,IEE监视器负责恢复 core-isolated 存储,或在“switch in”进程期间,分配空白的 core-isolated 存储。
-
Model 2:在NW中,不可信程序不允许与安全敏感的应用程序同时运行。
- 在单核平台上,当一个安全敏感的应用程序在NW中运行时,所有不可信程序总是被挂起。
- 在多核平台上,即使有可用的核,所有不可信程序也会被IEE监视器挂起。
- 由于在NW中,所有内核在任何时候都只能运行安全敏感的应用程序或不可信程序,因此不需要分配 core-isolated 存储。(模型1不适合的原因)
- 措施:当不允许并发运行时,这种保护也可以通过在“switch out”进程期间,将IEE内存配置为对NW不可访问来实现,并在“switch in”进程期间,将其恢复为对NW可访问。(控制对NW的访问权限)
4.2 CITM Attack Types
IEE系统中强制实施的两种数据保护模型,可能会在NW中,通过不可信的 rich OS,操纵缓存而受到损害。
从攻击者的角度来看,这两种IEE数据保护模型有两个攻击切入点——在并发执行时操纵 core-isolated 内存、篡改IEE的环境切换。
下面介绍,在IEE系统上的识别。
- Type I. 在并发执行期间操纵 core-isolated 内存:
- 在多核系统中,当主存被用作安全敏感应用程序的 core-isolated 存储时,在NW中,并发运行的恶意操作系统可能会通过操纵缓存来窃取或修改 core-isolated 内存中的IEE数据。
- 当 core-isolated 内存设置为 cacheable 时,内存中的IEE数据将在内存被访问时通过缓存。
- 由于在NW中,内存是由安全敏感的应用程序访问的,相应的 cache line 被标记为非安全(见2.2节),并且可能被不可信的 rich OS 操纵。(安全标记误改为非安全标记,使得安全隐私泄露)
- 例:通过制作一个页表条目,其物理地址指向一个 core-isolated 的内存页,恶意操作系统可以通过访问相应的虚拟地址来操纵其 cache line 。本例将在第5.1节中说明,在SANCTUARY中的IEE数据是如何被破坏的。
- 注:现代的ARM平台提供了确保内存隔离的硬件功能,但它们缺乏确保缓存隔离的类似功能。
- 例:ZC-400上的 Identity-based 过滤特性(参见2.1节)可用于隔离内存,但不能隔离缓存。
- Type II. 在IEE“switch out”进程中绕过安全措施:
- 攻击者的目标可能是绕过IEE环境切换过程中的安全措施。
- rich OS 不可信,在SW中,“switch in”进程中的安全措施总是由可信IEE监视器发起和完成的。
- 由于相应的 cache line 被标记为安全,在NW中无法操作,因此很难通过操作相应的 cache line 来绕过这些安全措施。
- 出于安全,在“switch out”进程中强制执行的安全措施应该由IEE本身在NW中执行,或者由IEE监视器在SW中执行。
- 但,在这两种情况下都可以绕过安全措施。(以上解释目前的安全,但其实并不安全)
- 当NW中,由IEE执行这些安全措施时,如果利用内存存储IEE数据,则可通过 随机数据 或 全零数据 覆盖IEE内存来实现 数据清洗 。
- 由于内存清理是在NW中执行的,因此相应的 cache line 是不安全的。
- 可以通过控制非安全的缓存,来约束缓存中的内存写入,并保持内存不变。
- 例:内存被设置为write-back, write-allocate时,所有写入的内存都会被缓冲到相应的 cache set 中,直到 cache set 被清除为止(参见2.2节)。
- 攻击者可以利用缓存锁定技术(见4.3节)来防止缓存回收,这样在安全敏感的应用程序被挂起或完成后,IEE内存上的敏感数据可能不会被安全地清理。
- 当SW中的安全措施由IEE监视器执行时,IEE应该能够直接将控制转移到SW中的IEE监视器,而不涉及 rich OS 。否则攻击者可能操纵跨世界的环境切换来绕过安全措施。
- 但,从NW到SW的环境切换,通常是通过调用( rich OS 内核中的)SMC高特权指令来启动的。
- 当安全敏感的应用程序是一个函数或一个应用程序时,在IEE内部不能直接调用SMC指令。
- 为此,一些IEE系统故意通过安全敏感的应用程序来访问其安全内存,在SW中,通过触发外部中断来触发环境切换。
- 映射到安全内存的 cache line 是不安全的。当在NW被访问时,恶意的 rich OS 可能操纵相应的 cache line 来绕过 切换控制机制 和 安全措施 (例:数据清洗)。本例在5.2节中展示,在 Ginseng 系统的“switch out”进程中,如何通过控制不安全缓存来绕过安全措施。
- Type III. 在IEE的环境切换期间滥用不完整的安全措施:
- 在某些IEE系统中,通过动态控制IEE内存的安全属性来实现环境切换时的内存保护,即在“switch In”时将其配置为“non-secure”,在“switch out”时将其配置为“secure”。
- 在这些系统中,即使环境切换期间的安全措施得到了安全实施,攻击者仍然可能通过滥用缓存来操纵IEE数据。
- 因为内存配置是通过TZASC实现的(见2.1节),在NW中,相应的 cache line 可能仍然不安全。
- 如果“switch out”进程中缓存清理不当,可能会导致IEE数据泄露。
- 类似地,恶意数据可能在“switch in”之前加载到缓存中,然后被提供给安全敏感的应用程序,这不是IEE内存中的原始敏感数据。
- Type III攻击是由于缓存上的安全措施不完善造成的,不同于Type II攻击(主要在环境切换时绕过现有的安全措施)。之后将说明 TrustICE 系统,是如何通过在"switch in"和"switch out"进程中操纵缓存而变得脆弱的。
- 总之,当IEE系统使用Model 1进行数据保护时,它们可能会遭受这三种攻击。
当使用Model 2时,IEE系统容易受到Type II和IIl攻击,但不容易受到Type I攻击,因为并发运行是不允许的。 - 另外,Type I和IIl攻击只在使用内存存储IEE数据时起作用,Type II攻击只有在IEE中执行“switch out”进程的安全措施时才有这个要求。
4.3 Cache Lockdown Technique
缓存锁定是一种功能,允许程序将代码和数据加载到缓存中,并将其标记为免除驱逐。
锁定缓存中的代码或数据的主要目的是提供更快的系统响应,并避免由于缓存线回收而导致的不可预测的执行时间。
攻击者可能会滥用这种技术来发动CITM攻击,例:锁定缓存中的内存写操作,使内存清理操作无效。
- 可以采用三种方法来实现缓存锁定:
- 一些ARM开发板(例:i.MX53和i.MX6Quad开发板)允许用户通过配置 L2辅助缓存控制寄存器 来锁定特定的L2缓存方式。
然而,这种基于硬件的锁定控制寄存器在ARMv8处理器上不受支持。 - 攻击者通过将被控制的内存区域设置为 outer cache ,而将其他所有内存区域设置为 outer non-cacheable ,可以独占L2 cache。
单独使用L2缓存可能会给系统的正常执行带来巨大的性能开销。 - 攻击者可能通过对每个内存页的缓存属性进行细粒度控制来独占一些L2 cache sets。具体:
由于缓存属性是在内存页面的粒度上设置的,所以我们将每个缓存方式划分为页面大小的块。
块具有相同索引组成一组页面缓存(参见图3中被标记为灰色的cache lines)。
为了锁定L2缓存上指定内存页的数据,攻击者可以将该内存页配置为outer cacheable,并将共享相同页面缓存的所有其他内存页设置为outer non-cacheable。
例:在图3中,当page 1和page 6共享同一个page cache set时,攻击者可以通过将page 1设置为outer cacheable,将page 6设置为outer non-cacheable来锁定L2 cache上page 1的数据。
这种技术在SecTEE系统中被用来防止基于缓存的侧信道攻击。
考虑到L1缓存的大小,本文选择在攻击中使用第三种方法锁定L2缓存。
- 一些ARM开发板(例:i.MX53和i.MX6Quad开发板)允许用户通过配置 L2辅助缓存控制寄存器 来锁定特定的L2缓存方式。
5 CASE STUDY OF CITM ATTACKS
注:SANCTUARY系统是通过ARM Fast Models虚拟化工具实现的,而不是在实际的开发板上实现的,因此作者在i.MX6Quad开发板上模拟了SANCTUARY的缓存操作,并通过 cross-core L1 cache 操作成功地窃取和修改了敏感的IEE数据。SANCTUARY的缓存操作主要是通过对已发表的论文进行仔细研究得到的。Ginseng和TrustICE系统的CITM攻击是通过其作者在两个真正的硬件开发板HiKey620和i.MX6Quad SABRE上共享的源代码实现的。
5.1 SANCTUARY: Manipulating L1 Cache
接下来介绍:在IEE数据保护上SANCTUARY的安全措施。
由于在IEE运行时对L1数据缓存缺乏保护,SANCTUARY会遭受 Type I 攻击。
在SANCTUARY系统的IEE中对敏感数据进行泄露和篡改的攻击过程:
5.1.1 Data Protection Mechanisms.
- SANCTUARY包含了大量的数据保护机制来保护IEE中的敏感数据。
- 解释 SANCTUARY 不受 Type III 攻击
- 当IEE 完成 它的运行时(即在“switch out”进程期间),敏感数据将被(运行在IEE内部的)微内核 清理 ,受保护的 core-isolated 内存被全零数据覆盖, L1 cache 失效 (L2 cache在SANCTUARY中对核心隔离内存禁用)。
- 在启动一个IEE 之前 (即在“switch in”进程期间),安全世界中的IEE监视器为IEE构建了一个干净的环境。此外,微内核在加载敏感应用程序之前会使 L1 cache 失效 。
- 因此,由于在"switch in"和"switch out" 进程期间, core-isolated 内存和 L1 cache 都被微内核安全清理, L2 cache 被禁用,所以 SANCTUARY 不受 Type III 攻击。
- 解释 SANCTUARY 不受 Type II 攻击
- 因为数据清理操作是由运行在IEE内部的微内核完成的。
- 为了绕过数据清理操作,攻击者需要锁定 L1 cache 上的内存覆盖(即防止 L1 cache 上的数据被逐出内存)。
- 然而, L1 cache 的回收操作是由该核上的内存操作和 core-isolated 内存页的缓存属性决定的。
- 攻击者无法通过操纵另一个核来控制驱逐。
- 此外, core-isolated 内存的缓存属性也受到运行在IEE中的微内核的控制和保护。
- SANCTUARY通过保护内存和 L2 cache 来防御并发运行的恶意操作系统。
- 它为每个IEE分配 core-isolated 内存。
- 内存隔离是通过 Identity-based 的过滤特征实现的(见2.1节)。
- 它为每个核心分配一个唯一的非安全访问标识符(NSAID),并通过配置TZC-400为每个NSAID分配隔离的内存区域。
- 由于现有的ARM平台不支持将NSAID分配到CPU内核的粒度上,即所有CPU内核共享同一个NSAID,所以内存隔离是通过ARM Fast Models虚拟化工具实现的,而不是在实际的开发板上实现的。
- L2 cache 的保护是通过将受保护的内存区域配置为 outer non-cacheable 来实现的。
- 因此,敏感数据不会通过 L2 cache ,而 L2 cache 通常在ARM移动设备的所有核之间共享。
- 由于 L1 cache 位于每个核内,不能直接从其他核访问,因此在并发执行时,SANCTUARY不会对 L1 cache 提供额外的保护。
- 然而,我们通过操纵不同核上的 L1 data cache ,在 SANCTUARY 中识别出一种 Type I 攻击。
5.1.2 Type I Attack in SANCTUARY
- 在研究了ARM平台上的缓存特性后,作者发现了一个名为 shareability 的缓存属性,可以配置为通过操作另一个核的 L1 data cache 来读写一个核的 L1 data cache 。
- shareability 属性定义了要保证值一致性的缓存范围。
- shareability 域有两种类型,即the inner shareability 域和 the outer shareability 域。
- 前者保证了内核一个簇之间的值一致性,后者保证了内核所有簇之间的值一致性。
- 当ARM平台有一组以上的核心时,每一组代表一个簇。
- 例:Juno r2开发板配备了两个簇,一个簇具有四核Cortex-A53处理器,另一个簇具有双核Cortex-A72处理器。
- 由于值一致性在单核平台上自然得到保证,shareability属性仅在多核平台上可配置。
- 它仅在处理器运行在 Symmetric Multi-Processing (SMP) 模式时有效,该模式在大多数多核平台上是默认设置的。
- 当设置了 shareability 属性时,Snoop Control Unit (SCU) 可以保证值的一致性,SCU 包含处理内核之间直接 cache-to-cache 传输的缓冲区。
- 如果其中一个核的 L1 data cache 被修改,当其他同簇核的 L1 data cache 对应的内存页设置为 inner shareable 时,SCU会同步更改 L1 data cache 。
当内存页被设置为 outer shareable 时,更改将被同步到所有其他内核。 - 出于安全原因, non-secure cache 上的数据不会被同步到 secure cache ,反之亦然。
- 为了更好地了解 shareability 属性对不安全的 L1 data cache 的影响(见附录A),作者进行了一系列的实验。
A SHAREABILITY ATTRIBUTE ON ARM PROCESSORS
- 在i.MX6Quad sabre开发板上进行实验
- 该开发板配有1.2GHz的四核ARM Cortex-A9处理器和1GB DDR3 SDRAM。
- 由于单板只有一个簇,所以 inner shareability domain 与 outer shareability domain 相等。换句话说, inner shareability 与 outer shareability 具有相同的效果。
- 由于在多个核访问相同的数据时, shareability 属性常被用于增强值的一致性,所以我们令四个核访问相同的物理内存(以下简称测试内存)。
- 让所有核都在NW中运行,这样它们访问的 L1 cache 都是不安全的。为了消除通过 L2 cache 和内存引入 L1 cache 的潜在影响,我们禁用 L2 cache ,并将测试内存设置为安全内存。
- 将测试内存设置为 secure ,而不是在SANCTUARY中使用内存隔离方案,因为该方案仅通过ARM Fast Models虚拟化工具模拟,在实际的开发板上无法实现。
- 为了防止由于从NW中访问安全内存而引发外部中断,我们将测试内存设置为 write-back、write-allocate 并将所有其他内存设置为 non-cacheable.。
- 因此,测试内存的写入将被缓冲并锁定在 L1 cache 中,并且不会同步到内存中。
测试内存和相应的 L1 data cache 都初始化为零。
- 结果表明,一个核的 L1 data cache 上的数据可能会泄露给另一个核,并被另一个核篡改。
- 当两个内核在NW中运行时(这确保了相应的 cache lines 是 non-secure 的 ),并访问相同的物理内存地址,该内存页的缓存属性设置为 两个核的 inner shareable 或 outer shareable 。
- 缓存属性是为每个核单独配置的,因为它是在页表中配置的,而且每个核都有自己的一组页表。
- 相反,当一个核的 L1 data cache 被设置为 non-shareable (即,inner&outer non-shareable )时,数据不会泄露给另一个核,也不会被另一个核篡改。
5.1.3 Attacking Procedure
- 在i.MX6Quad SABRE开发板上模拟Sanctuary的缓存操作。
- 如图4所示:
- core_0和core_1运行在NW中,core_2运行在SW中。
- 安全敏感的应用程序运行在core_0上,不可信 rich OS 运行在core_1上。
- 静态可信应用程序(即SANCTUARY中的IEE监视器)运行在core_2上,它配置TZC-400为core_0分配一个隔离的内存区域,并禁用 core_0 的 L2 cache 的使用。
- 虽然分配给core_0的内存区域是非安全内存,但是它受到了静态可信App的保护,阻止了core_1的访问。
- core_0 访问的 L1 cache lines 是不安全的缓存,因为它们是在NW中访问的。
- 根据我们在附录A中列出的实验结果,可以通过操纵另一个核的 L1 data cache 来影响一个核的 L1 data cache ,当两个核的 L1 data cache 都是不安全的。
- 因此,通过控制 core_1 的 L1 data cache ,可能会盗取或修改 core_0 的 L1 data cache 中的敏感数据。
-
在Linux内核中,所有的 cacheable 内存默认设置为 shareable ( inner or outer shareable )。
-
根据本文的描述,SANCTUARY 系统通过在IEE环境切换过程中使 L1 cache 失效。
在IEE运行时,将 core-isolated 的IEE内存的 cacheability 属性改变为 inner cacheable ;
outer non-cacheable 来防止基于缓存的攻击。 -
由于 shareability 不配置属性,受保护的内存将被默认设置为 shareable
-
因此,并发执行期间,通过利用 shareability 属性,我们能够 read and write 驻留在 L1 data cache 中的敏感数据(例:当一个IEE与不可信 rich OS 同时运行)。
-
如图4中的红线所示:
- 首先为 core_1 创建一个页表条目,将内存页的缓存属性配置为 shareable ,并使其物理地址指向 core_0 的内存页(即受SANCTUARY保护的内存页)。
- 那么,当我们访问 core_1 上对应的虚拟地址时,由于 shareable 属性保证了值的一致性,core 0的 L1 data cache 中的敏感数据可以被窃取或修改。
-
上面的攻击过程需要识别IEE内存的物理地址(即为 core_0 分配的内存)。
-
由于与IEE内存相关的页表是在IEE中维护的,攻击者无法直接获取其物理地址范围。
-
整个物理内存被分为三个部分——IEE内存、TEE内存(分配给SW的内存)和未受保护的内存(分配给不可信 rich OS 的内存)。
- 恶意的 rich OS 自然知道不受保护的内存地址范围。
- 剩下的两个内存区域可以区分,因为对应于IEE内存的缓存是不安全的,而TEE内存的缓存是安全的。
-
虽然读取TEE内存总是会返回0或产生异常(取决于TZASC的配置),但是读取IEE内存可以在缓存中获得真实的数据。
- 因此,我们可以通过探测除未受保护内存外的内存区域来识别IEE内存。
- 由于缓存的大小通常比IEE内存小,我们可能需要探测几次来识别整个IEE地址范围。
- 探测次数取决于IEE和TEE内存的大小,以及IEE数据在L1数据缓存中的持续时间等。
注:由于缓存的 shareability 属性并不广为人知,而且在 SANCTUARY 论文中也没有提到过,所以当其他开发人员遵循这篇论文重新实现时,他们的系统很有可能也会出现同样的问题。
5.2 Ginseng: Mapping to Non-Secure Cache
如2.3节所述,Ginseng 是一个IEE系统,通过在寄存器中存储和处理敏感数据来保护它们。
因此,Ginseng 对 Type I 攻击免疫。
此外,由于寄存器中的内容不通过缓存,它也不会受到 Type IIl 攻击。
然而,我们发现 Ginseng 会遭受 Type II 攻击。
Ginseng 依靠在安全世界中运行的TEE监控器,在“switch out”过程中执行数据清理操作。
由于 rich OS 不被信任,为了触发一个安全中断,控制流通过访问IEE中的安全内存直接从IEE传输到TEE监视器。
然而,在正常情况下,通过操纵 non-secure cache (映射到安全内存),攻击者可以阻止从IEE到IEE监视器的控制流切换,从而绕过数据清理操作。
5.2.1 Data Protection Mechanisms
通过Listing 1所示的示例程序演示了 Ginseng 系统的工作流程。
-
该程序将基于从安全世界获得的两个密钥执行 hmac_sha1 操作。具体:
- 两个局部变量被标记为 sensitive ,即 key_top 和 key_bottom (第21行)。
- Ginseng 提供了一个编译器来执行静态污染分析,以识别所有可能携带敏感数据的变量,并将它们分配到寄存器中。
- 涉及敏感数据的函数被识别为敏感函数,并在执行前进行代码完整性检查。
- 在本例中,函数 run() (第19行)、 genCode() (第2行和第26行)和 hmac_sha1 (第7行)是敏感函数。
- 函数 printf() (第14行)是一个不敏感函数,其代码的完整性没有得到保证。
- 所有与敏感数据相关的操作都在寄存器中执行,而不是在内存中。
-
为了防御恶意内核,Ginseng 引入了6个安全API函数,将控制流从正常世界的用户空间直接传输到 GService (即 Ginseng 中的 IEE monitor )。
- 为程序提供了两个安全API函数来安全地与 GService 交互,即 ss_write() 和 ss_read() 。
- 另外四个安全API函数将由编译器自动插入到程序中。
- ss_savecleanV() 和 ss_readV() 有两个安全API函数插入每个函数调用之前和之后在敏感函数,在前负责对敏感数据进行加密,将加密数据存储在内存中,并清洗相应的寄存器,后来负责解密敏感数据和恢复寄存器。
- 例:ss_saveCleanV() 和 ss_readV() 将被插入 genCode() 中的 printf() 函数(第14行)之前和之后。
- 另外,在每个敏感函数的开头和结尾插入两个安全API函数 ss_start() 和 ss_exit() ,分别进行准备工作(如对敏感函数进行代码完整性检查)和清理所有敏感寄存器,防止数据泄漏。
-
在“switching out”IEEs之前,Ginseng实现了一个跨世界环境切换,直接从运行在NW用户空间的IEEs切换到运行在SW的GService,并在GService中执行安全敏感的操作(例:加密敏感数据,清理敏感寄存器等等)。
-
触发跨世界环境切换的正常方式是从内核空间调用高特权SMC指令。
-
然而,这种方法不适用于 Ginseng ,因为它的IEE运行在用户空间,不能调用SMC指令。
-
Ginseng 通过在IEEs中触发 security violation 来解决这个问题。 具体:
- 通过配置TZASC,为每个安全API函数分配一个唯一的安全内存。
- 然后,对安全API函数的调用 会触发安全冲突,因为它试图从NW访问安全内存。
- 默认情况下,在处理违规时,处理器会在正常情况下引发 外部中断(EA)。
- 为了在SW中引发EA,GService设置了安全配置寄存器的外部中断位,这样GService就可以获得EA并处理由安全API发送的请求,而不需要恶意内核的出席。
5.2.2 Type II Attack in Ginseng
因为与安全内存对应的 cache lines 不安全,上述触发解决方案可以被操纵。
我们使用安全API ss_savecleanV()作为示例来说明这个问题(Listing 2中的第11到19行是 Ginseng 中ss_savecleanV()的实现)。
它首先将channel_save_clean(分配给ss_saveCleanV()的安全内存)的地址加载到寄存器x4(第16行)。
然后,它将数据从位于x4的安全内存加载到寄存器x0(第18行)。
图5演示了详细的执行流程。
①当“secure memory loading”指令(即第8行)执行时,处理器尝试从缓存中加载数据。
②由于cache miss,cache从安全内存中读取数据。
③由于从NW中访问安全内存,导致外部异常中止,被GService捕获。
④GService加密敏感数据并清理相应的寄存器。
⑤控制流被传输回安全API ss_saveCleanV()。
⑥调用不敏感函数insensitive_func()。
尽管安全内存受到了恶意内核的保护,但步骤①中访问的缓存是不安全的缓存,因为它是从NW访问的。因此,它可以被攻击者操纵。
5.2.3 Attacking Procedure
基于Ginseng的开放源代码,作者在8核ARM Cortex-A53处理器的HiKey620开发板上实现了Ginseng的原型。
攻击可以通过图5中的红线所示的攻击过程成功窃取敏感数据。
特别地,我们引入了步骤〇,它在步骤①执行之前填充了映射到安全内存的 cache lines 。
然后,当处理器试图通过“secure memory loading”指令(即步骤①)从缓存加载数据时,它遇到的是 cache hit,而不是cache miss。
因此,步骤②*将被执行,而正常的步骤②、③、④和⑤被阻塞。
最后,在步骤⑥中,可以操纵不敏感函数insensitive_func()来读取未清理的敏感寄存器,因为它与敏感函数在同一个核上执行,并且不受代码完整性检查的保护。
例:我们可以更改printf()的控制流
(由 Listing 1 中的敏感函数genCode()通过修改libc.so库调用的不敏感函数)。
由于clean进程被无意识地中断,函数insensiti ve_func()可以从寄存器读取敏感数据(例:keys)。
Listing 2 中的 writeSM 函数用于完成步骤〇,即将数据写入 __channel_save_clean (分配给ss_savecleanV()的安全内存)的缓存。
首先,将 __channel_save_clean(第6行)的虚拟地址加载到寄存器x4中。
由于受保护的程序(如 Listing 1 中的 hmac_sha1 程序)包含 __channel_save_clean 虚拟地址的页表保存在 rich OS 内核中,因此攻击者可以获得它。
出于安全原因,Ginseng 将所有的页表更新操作挂起,并确保页表对 rich OS 内核是只读的。
然后,寄存器x0的数据被存储到位于x4的安全内存中(第8行)。
数据将首先被写入安全内存的缓存 __channel_save_clean 。
由于安全内存在 Ginseng 系统中设置为回写、写分配(write-back, write-allocate),数据被缓冲在缓存中,只有当 cache set 满时才会被清除到内存中。
利用第4.3节介绍的缓存锁定技术来防止缓存回收,即,我们使用安全内存 __channel_save_clean 共享相同页面,将 cache set 的内存页设置为 outer non-cacheable 。
由于一些数据在映射到安全内存 __channel_save_clean 的 cache lines 中提前被锁定,所以步骤①中的内存访问将会遇到 cache hit ,从而避免了从安全内存中取数据(即步骤②)。
然后,不会触发 security violation ,也不会触发跨世界环境切换。
通过在 ss_saveCleanV() 执行之前调用 writeSM 函数,我们可以成功绕过 IEEs 到 GService 的环境切换和 GService 中的数据保护。
用于在每个敏感函数末尾清除敏感寄存器的安全API函数 ss_exit() 也可能受到类似的攻击。
5.3 TrustICE: Incomplete Cache Cleaning
本节包括TrustICE中的数据保护机制、由于不完全的缓存清理TrustICE在环境切换过程中遭受 Type III 攻击、攻击过程。
5.3.1 Data Protection Mechanisms
TrustICE 将整个物理内存静态地划分为三个独立的区域,分别用于NW中的 rich OS、NW中的IEE 和SW中的 Trusted Domain Controller (即 TrustICE 中的IEE监视器)。
动态配置IEE内存的安全属性可以实现敏感数据保护。
当系统启动时,IEE内存被 Trusted Domain Controller 设置为 secure 。
在启动新的IEE之前, Trusted Domain Controller 从IEE内存中为它分配一个内存区域,并将该内存区域设置为 non-secure 。
当IEE完成时,内部的微内核通过调用SMC指令将控制流直接传输到SW。
Trusted Domain Controller 将相应的IEE内存区域配置为 secure ,然后再将控制传输回 rich OS 。
5.3.2 Type III Attack in TrustICE
由于 TrustICE 遵循 Model 2 来实现数据保护,所以它对 Type I 攻击免疫。
当恶意操作系统运行时,将IEE内存设置为“ secure ”;
当安全敏感的应用程序执行时,将IEE内存设置为“ non-secure ”。
在“switch out”进程期间的数据保护是通过动态地将关联的内存设置为 secure 来实现的。
它不能被绕过,因为它在SW中被强制执行,控制流通过调用SMC指令直接从IEE中的微内核传输到SW。
因此,IEE系统对 Type II 攻击免疫。
但是,在环境切换过程中,虽然IEE的内存受到了保护,但是对应的缓存是不安全的,没有被正确清理。因此,攻击者可以利用 Type III 攻击来危害敏感数据的安全性。
5.3.3 Attacking Procedure
在i.MX6Quad SABRE开发板上实现了 TrustICE 原型。
由于i.MX6Quad是一个多核平台,当一个IEE运行时,我们暂停所有其他核。
特别是,在启动一个IEE之前, Trusted Domain Controller 发送一个核间中断给其他不安全的核(分配给IEE的核除外),它被配置为一个安全中断。
当接收到安全中断时,核切换到 monitor 模式,因此运行在其上的程序被暂停。
攻击过程如下:
如图6(a)所示,我们制作一个页表条目在NW里,其物理地址是指着一个IEE内存页面(IEE内存的地址范围可以在节5.1.3中获得)及其属性设置为write-back, write-allocate。
尽管在“switch out”过程中,IEE内存页被配置为 secure ,但是我们仍然可以访问位于相应的 non-secure cache lines 中的敏感数据,因为 TrustICE 不会清除 cache lines 中的数据。
在“switch in”过程中,rich OS 可以将恶意数据写入IEE内存页面对应的 cache line 中,并使用4.3节中描述的缓存锁定技术锁定 cache line 中的数据。
当IEE执行时,它将首先读取驻留在 cache lines 中的恶意数据,而不是IEE内存页中的合法数据,如图6(b)所示。
6 COUNTERMEASURE
直观地说,最直接的防御策略是完全禁用所有IEE内存的缓存。
然而,由于在不使用缓存的情况下会产生巨大的性能开销,这是不切实际的。
基于对CITM攻击的根本原因的分析,
我们建议通过正确配置IEE内存的缓存属性 / 在环境切换期间清洗IEE内存的缓存来防止它们。
实验表明,我们的对策在 rich OS 和安全敏感的应用程序上都有较小的开销。
6.1 Defense Approaches
-
所有CITM攻击的主要原因:缓存和主存两层内存体系结构之间的不一致性。
- 首先, Type I 攻击的根本原因:内存隔离并不能自动保证缓存隔离。
特别是,当一个内存区域通过SANCTUARY中的TZC-400 identity-based 过滤特性,被隔离为一个专用核时,对应 L1 cache 的数据仍然可以在核之间共享。
通过为 core-isolated 内存配置 outer non-cacheable、non-shareable(即:inner&outer non-shareable)的缓存属性来消除 Type I 攻击。 - 其次, Type Il 攻击的主要原因:内存和缓存之间的读写操作没有同步。
例: Ginseng 中的跨世界切换可以通过限制缓存中的安全内存的读写来绕过。
预加载并锁定与安全内存对应的缓存中的恶意数据后,未来对IEE内部安全内存的读取就会 hit 预加载的恶意缓存。
通过在内存和缓存之间同步读写操作来击败 Type Il 攻击。具体:IEE内存的缓存属性(例: Ginseng 中的安全内存)应该总是配置为write-through, non write-allocate。由此,读写操作在缓存中不会受到限制。 - 第三,内存区域通过TZASC被配置为 secure 或 non-secure ,但是 cache line 的安全属性是由访问它的核的状态决定的。
换句话说,如果由在NW中运行的核 访问 cache line ,则自动将其标识为 non-secure ,如果由在SW中运行的核 访问 cache line ,则将其标识为 secure 。这是 Type IIl 攻击的主要原因。
例:CITM攻击 TrustICE (见5.3节)是在“switch out”后读取IEE内存的 non-secure cache ,在“switch in”前将恶意数据写入并锁定在 non-secure cache 中。
通过在“switch in”和“switch out”进程中清除 cache line 来击败 Type IIl 攻击,这样攻击者就无法读取剩余的敏感数据或将恶意数据保留在缓存中。
- 首先, Type I 攻击的根本原因:内存隔离并不能自动保证缓存隔离。
-
综上所述,本文所识别的三种CITM攻击可以通过以下方法来消除
- 将IEE内存的缓存属性配置为inner write-through、non- write-allocate、outer non-cacheable、non-shareable;
- 在环境切换时清理IEE内存的缓存。
在不同的IEE系统中,执行缓存属性的方法是不同的。
当IEE内存的页表在IEE中维护时(例:SANCTUARY),运行在IEE内部的安全敏感应用程序可以强制执行正确的缓存属性。
当IEE内存的页表是在SW中构造的(例: TrustICE ),缓存属性的实施可以由IEE监视器实现。
当IEE内存的页表在恶意操作系统(例: Ginseng )中被维护时,恶意操作系统的所有页表更新操作都应该被插入并转发给IEE监视器,然后强制缓存属性被正确配置。
- 特别是,我们通过将IEE内存的页表和内核特权代码,设置为对内核的只读,来阻止恶意内核的直接操作。
- 然后,替换所有指令在内核代码更新页表条目和相关的寄存器,使它们掉入SW的陷阱。
- 接受安全检查(即缓存属性的关键记忆正确配置)最终被执行之前,我们不配置系统设置特权执行(PXN)属性,默认任何新分配页面。
- 这样,当系统运行时,就不会插入可执行的内核特权指令。
- 缓存清理可以通过在IEE中调用 invalidation 和 cleaning 指令来实现。
6.2 Defense Overhead
我们在i.MX6Quad SABRE开发板上实现了我们的对策解决方案的原型,
该开发板配备了运行在1.2GHz和1GB DDR3 SDRAM的四核ARM Cortex-A9处理器。
然后,我们评估了防御系统引入的系统开销。
为了使实验中的干扰最小化,我们用1000次迭代运行每个测试并报告其平均值。
首先探讨由于强制缓存属性而导致的安全性敏感应用程序的开销。
特别地,我们在一个IEE中运行一个AES加密应用程序,当内存配置了不同的缓存属性时,计算它的执行时间。
实验结果表明,我们的防御系统(例:使用缓存属性设置为 non-shareable, inner write-through non write-allocate, outer non-cacheable)介绍了约90%的开销相比,默认设置(例:使用缓存属性设置为 shareable, inner write-back write-allocate, outer write-back writeallocate),它主要是通过禁用 L2 cache 引起的。
我们还观察到,对于为了保护而禁用 L2 cache 的IEE系统(例:SANCTUARY),我们的防御系统只引入了微不足道的额外开销。
此外,我们还评估了在每个页表更新操作上强制执行额外的跨域环境切换所引入的 rich OS 的开销。
结果表明,rich OS的执行带来了2.65%的总开销。
此外,我们评估涉及频繁更新页表的操作的开销,例:系统启动和应用程序加载。
它显示,在所有评估场景中,内核和应用程序的总体加载开销都小于10%。评估详情见附录B。
B EVALUATION OF THE DEFENSE SYSTEM
基于i.MX6Quad SABRE开发板实现的原型,我们评估了我们的防御系统引入的开销,该开发板搭载了运行在1.2GHz的四核ARM Cortex-A9处理器,1GB DDR3 SDRAM。为了使实验中的干扰最小化,我们用1000次迭代运行每个测试并报告其平均值。
我们首先探讨安全性敏感的应用程序上强制缓存属性带来的开销。特别地,我们在一个IEE中运行一个AES加密应用程序,当内存配置了不同的缓存属性时,计算它的执行时间。在表3中,大多数内存区域的默认配置显示在第二列中,其中S、WB、WA,加上l1和l2意味着将缓存属性设置为可共享2、内部回写write-allocate、外部回写write-allocate。我们的deense系统强制执行的属性显示在第四列中,其中non-s, WT, non- wa,不带L2表示不可共享,内部透写,非写入分配,外部不可缓存。第三列中说明的缓存属性与我们的防御系统中的缓存属性相似,但启用了L2缓存。实验结果表明,与默认设置相比,我们的防御系统引入了大约90%的开销,这主要是由禁用L2缓存引起的。我们还观察到,对于为了保护而禁用L2缓存的IEE系统(例如,SANCTUARY),我们的防御系统只引入了微不足道的额外开销。
然后,我们评估在每个页表更新操作上强制执行额外的跨域上下文切换所引入的富操作系统的开销。我们首先通过一个全面的基准测试套件来研究总体开销,也就是AnTuTu 2.9.4[3]。它在整数计算、浮点运算、二维和三维图形绘制等方面进行了性能测试。结果如表4所示,表中显示rich OS执行时引入了2.65%的总开销。数据库I/O操作开销17.74%的主要原因是,在将数据从磁盘复制到内存时,需要构建大量的页表映射。
我们还评估涉及频繁更新页表的操作的开销,即系统启动和应用程序加载。如表5所示,测试项内核记录从硬件引导到init进程启动的加载时间。Android Home是指Android启动进程的初始化时间。我们还测试了四个Android应用程序的加载时间,包括计算器、日历、音乐和设置。总的来说,在所有评估场景中,内核和应用程序的加载开销都小于10%。