【论文分享】Fuzzing SGX Enclaves via Host Program Mutations

本次介绍的论文使用程序变异(program mutation)结合模糊测试(fuzzing)的方法,针对英特尔可信执行环境SGX应用进行漏洞挖掘。论文发表于Euro S&P 2023,作者团队来自于普渡大学。

01 研究背景

随着漏洞挖掘技术和攻击手法的不断迭代,攻击者往往可以通过攻破高权限代码(系统内核、虚拟机监视器等)窃取用户的机密数据。为了应对这种威胁,厂商提出了可行执行环境(TEE,Trusted Execution Environment)技术,其本质是一种隔离的运行时环境,确保了用户数据、代码在可信执行环境中的机密性和完整性。SGX(Software Guard Extensions)是Intel公司开发的一种TEE的实现方式。SGX提供了一种机制(其本质为一组指令),允许应用程序创建称为Enclave(enclave)的安全区域。这些Enclave在物理内存中有专门的区域,即使在操作系统层面遭到破坏,其中的数据和代码也能保持安全。Enclave内的代码和数据对于操作系统、虚拟机管理程序(hypervisor)和甚至是具有root权限的用户来说,都是不可见的。尽管SGX提供了计算时数据和代码的安全性,但Enclave的实现通常使用内存不安全和类型不安全的语言(如C/C++)编写,增加了安全风险。因此Enclave实现的安全性得到了研究者广泛的关注。

本文提出了一种基于输入和程序变异的模糊测试工具,专为Intel SGX Enclave实现而设计。FUZZSGX提供了一个模糊测试运行时环境,即FUZZSGX RUNTIME,这是一个兼容Intel SGX SDK的库,它能够在Enclave内部实现代码覆盖率和内存漏洞检测的功能。进一步,为了探索宿主应用与Enclave的边界信息,FUZZSGX对现有的宿主应用和Enclave实现进行静态分析和符号执行,以自动化生成测试程序。在实验中,作者在30个流行的SGX应用上评估了FUZZSGX的模糊测试效果,并在这些SGX项目中找到了93个漏洞,包括数据竞争、空指针解引用、越界访问等错误。通过针对性地对宿主应用与Enclave边界进行测试,FUZZSGX实现了3.2倍的代码覆盖率提升,并发现了48.2%更多的漏洞。

02研究挑战

在对SGXEnclave实现进行模糊测试时,主要面临两大困难:运行时环境受限(Runtime Challenges)和已有模糊测试方案无法高效探索Enclave内部的代码(Fuzzing Challenges)。

运行时挑战(Runtime Challenges)

1. 有限资源(Limited Resources):SGXEnclave提供的资源是有限的,大多数实现仅提供128MB的EPC(Enclave Page Cache)内存,这在系统中是全局共享的。由于模糊测试往往需要同时运行多个目标程序实例,高吞吐量的模糊测试工具很快就会耗尽这些内存资源。

2. 不可用的操作系统服务(Unavailable OS Services):在SGXEnclave内部无法使用任何操作系统服务,如系统调用。现有的模糊测试解决方案,如AFL,高度依赖于操作系统服务,因此无法直接应用于SGX。

3. 无法导出代码覆盖率(No Code Coverage Export):由于SGXEnclave内存处于被保护的区域,现有的模糊测试方案无法从Enclave内部获取更新信息。

4. 缺少地址Sanitizer(Missing Sanitizers):模糊测试高度依赖于sanitizer来发现常见的内存错误。由于有限资源和操作系统服务不可用的限制,现有的sanitizer无法在Enclave内工作。

模糊测试挑战(Fuzzing Challenges)

1. 深层代码路径(Deep Code Paths):调用了Enclave接口的代码可能隐藏在宿主应用程序代码的深层路径中。因此,现有的模糊测试工具可能需要数小时的变异才能找到触发了Enclave接口调用的输入。

2. 未使用的ECALLs(Unused ECALLs):尽管Enclave可以提供多个ECALLs,但宿主应用中可能没有使用全部的ECALLs,这使得模糊测试工具无法对未使用的ECALLs进行测试。

3. 有限的ECALL输入和OCALL输出覆盖率(Limited ECALL Input and OCALL Output Coverage):受限于Enclave环境的限制,很难直接进行覆盖率收集和部署sanitizer。

4. 不可用的宿主应用(Unavailable Host Apps):当Enclave实现被用作安全库时,开发人员可能根本不提供宿主应用,仅提供Enclave以作为安全库使用,传统的模糊测试工具在没有宿主程序的情况下无法进行测试。

03研究方法

Overview: 针对以上困难,本文提出了一种针对于Enclave实现的模糊测试工具,通过两种策略来提高模糊测试的有效性:模拟执行环境(FUZZSGX RUNTIME)和 自动化模糊测试程序生成。

1. FUZZSGX RUNTIME

目的:解决Enclave执行环境资源受限的问题,提供模糊测试必要的覆盖率收集和sanitizer功能。

实现方式:作者实现了一个特别的库操作系统(libOS),在接口层面和Intel SDK互相兼容。具体来说,作者分别在宿主程序和Enclave内实现了一个Shim层,用来传递必要的覆盖率、sanitizer反馈信息给模糊测试器。同时这个libOS可以在普通的用户态执行,进而实现了在虚拟的SGX环境中加载被测的Enclave,同时作者迁移了现有的覆盖率方案和sanitizer方案,以便在运行时提供反馈和检查。

2. 模糊测试程序的生成

目的:高效探索Enclave内部的代码。

实现方式:FUZZSGX主要依赖程序变异来生成宿主程序代码实现对Enclave的测试。在分析阶段,FUZZSGX主要提取了接口、依赖信息。

■Enclave接口识别:FUZZSGX解析了SGX中的接口定义EDL文件,提取ECALL/OCALL函数和接口的相关信息,以解决未使用ECALLs的挑战。

■程序依赖性推断:FUZZSGX利用静态分析和符号执行分析ECALLs之间的依赖关系。在有宿主应用的情况下,通过分析宿主应用中ECALL的调用来推断其依赖关系。在没有宿主应用的情况下,会通过对Enclave中全局变量等状态的跟踪,分析ECALL间的依赖关系。

■初始种子生成:FUZZSGX利用符号执行帮助生成模糊测试所需的初始种子,以提高测试的效率。

在获取到依赖信息后,SGXFUZZ会自动化生成一系列的宿主程序,在编译执行后即可实现对Enclave的测试。

04实验结果

作者选取了30个Enclave实现作为实验目标,在8个Enclaves中发现了总计80个bug。

 1. 对比实验:在对比实验部分,作者和已有方案在吞吐量、代码覆盖率、漏洞数量上进行了对比。实验选取了SGXFuzz做为对比,同时还使用AFL直接对宿主程序进行模糊测试作为参考。

吞吐量实验:实验结果表明该方案的吞吐量和AFL接近,并大幅度领先于SGXFuzz。

覆盖率实验:选取了评估数据集中的10项目,进行了24小时的实验,并收集了代码覆盖率。根据实验结果,AFL在所有目标中产生的代码覆盖率都较低,因为它无法从Enclave内部提取代码覆盖率。FUZZSGX在除了sgx-gmpdemo项目以外的所有项目中都探索了更多的代码。作者指出,SGXFuzz在sgx-gmp-demo项目中覆盖了更多的代码,可能是由于该项目有大量简单实现的ECALL。总体而言,得益于FUZZSGX RUNTIME的高吞吐量,FUZZSGX在评估中实现了比SGXFuzz高3.2倍的覆盖率,比AFL高23倍的代码覆盖率。

漏洞数量:与代码覆盖率类似,AFL在大多数项目中发现的崩溃数量最少。除sgx-mpi项目外,FUZZSGX在所有其他项目中发现的崩溃数量均多于SGXFuzz。

 2. 消融实验:作者选择了6个项目进行了消融实验,从代码覆盖率、漏洞数量两个维度进行了比较。

覆盖率实验:在大多数应用程序中,由开发者编写的应用程序产生了更高的代码覆盖率。这是因为开发者通常了解不同ECALL之间的实际依赖关系。对于一些项目,如mbedtls,FUZZSGX生成的宿主程序产生了更高的代码覆盖率。这可能是因为原本的宿主应用并没有充分使用Enclave的功能。

 漏洞数量实验:对于每个项目,开启程序变异的配置都找到了更多的崩溃。作者在研究后发现,一些对用户输入检查的逻辑被放在了宿主应用中,而不是Enclave中。由于SGX威胁模型指出,所有参数必须由Enclave进行检查,这种错误的信任使得FUZZSGX直接对ECALL接口进行测试,即可产生大量崩溃。

05总结

本文针对SGX Enclave测试,提出了一种基于程序变异和虚拟执行环境的模糊测试方案。并进一步实现了基于libOS的FUZZSGX RUNTIME运行时环境以及支持程序变异的模糊测试器FUZZSGX。在实验中,本方案在代码覆盖率和漏洞挖掘的表现上都要好于目前已有的方案。

Bookmark the permalink.

Comments are closed.