《论文分享》Emilia: Catching Iago in Legacy Code

逆向病毒分析 1年前 (2022) admin
540 0 0

《论文分享》Emilia: Catching Iago in Legacy Code

今天分享的是一篇发表于NDSS 2021的paper《Emilia: Catching Iago in Legacy Code》。目前有一些TEE隔离技术是借助不可信的OS提供类似系统调用的服务来支持可信应用运行的。这种隔离技术存在一种知名的攻击Iago attack。这是因为一个恶意的内核可以操纵系统调用的返回值,而传统的应用代码通常会信任系统调用的返回值,因此当威胁模型改变,OS变为不可信时,这种信任就可能导致漏洞。例如mmap返回一个被篡改的地址时,通过故意映射到应用栈的内存地址空间,就可能导致后续的控制流被修改造成ROP攻击。


1. Design

因此,作者提出了Emilia,对系统调用拦截并fuzz它们的参数返回值来发现应用代码中可能存在的Iago attack漏洞。

《论文分享》Emilia: Catching Iago in Legacy Code

Emilia通过fuzzing产生输入造成程序崩溃后,通过coredumps来发现内存崩坏的Iago bugs。而在fuzzing之前,fuzzing的目标系统调用是具有不确定性的。也就是说系统调用的数量和调用的序列都可能会变化。例如下面的例子,fstat因为fuzzing的输入造成的异常导致新的syscall write被调用。

《论文分享》Emilia: Catching Iago in Legacy Code


2. fuzzing value set

Emilia为每个调用的syscall生成一系列输入集合,包括系统调用的返回值和一些函数参数。值的变化范围包括运行时产生的最小、最大和随机值,以及从程序源码中获取的静态的合法值。


3. Classification of vulnerabilities

作者fuzzing了17个主流的开源程序和库,检测到了51个内存崩溃Iago bugs,同时将这些Iago bugs基于语义分为了以下5类:


a. Static: 这类错误独立于syscall参数和过去的返回值记录。例如在Redis中发现的accept系统调用,当一个系统调用返回负数值作为错误码时,应用代码内通常有预设一个检测返回错误的判断。然而glibc中的代码对这个syscall的返回值的处理是只在大于-4096时才会返回-1,这就导致应用代码的预设错误检测可能被通过,从而造成后续代码在用一个异常的值运行。

《论文分享》Emilia: Catching Iago in Legacy Code


b.Local: 这类错误只依赖于传递给syscall的具体参数。例如read/write的返回字节数要小于或等于在syscall参数指定的buffer长度才是安全的。如下述例子开发者对返回的长度len做了小于sizeof(buf)-1的假设,这就可能导致数组越界。

《论文分享》Emilia: Catching Iago in Legacy Code


c. Stateful: 这类错误受之前syscall的历史记录影响。一个代表性的例子就是当前对打开文件的读写指针是取决于之前应用程序调用的syscall的。比如epoll_wait返回就绪的fd个数,而ev→fdarray数组是可以由攻击者控制的,因此可能导致数组越界,执行攻击者构建的epoll handler。

《论文分享》Emilia: Catching Iago in Legacy Code


d.Unauthenticated Channel:主要是多进程间通信时需要依靠OS建立通信通道,例如pipe。因此可能泄露敏感数据。例如read系统调用从另一个库libevent的wakeup pipe(timeout_fd)读取数据,因为timeout_fd是另一个程序的线程创建的,因此timeout_fd可能被修改导致非法内存访问。

《论文分享》Emilia: Catching Iago in Legacy Code


e.Externeal:这类错误是与应用程序的外部状态有关的syscall造成的,例如随机数、时间、文件大小。

总的来说,作者对17个开源程序的检测发现超过80%的iago bugs都是因为返回的size造成的,也就是边界超过了合法的最大值。比如epoll_wait返回的文件描述符个数可能超出最大的epoll event数。

《论文分享》Emilia: Catching Iago in Legacy Code

4. Mitigating Iago vulnerabilities

一种显而易见的抵御iago attack的方式就是检测syscall的返回值是否合法。这可以由应用自己或者可信环境的syscall 转发层(OS forward layer OFL)完成。对于上述五种类型的syscall,则有不同的处理难度。


a. local与static:这两个类型的语义可以通过检查预设的范围或者约束来完成,无需维护状态。因此这种检查可以很容易地通过OFL来完成。比如OFL可以检查返回的size是否小于或等于系统调用参数指定的最大长度大小。通过Table 3内的iago 漏洞种类可以看到,这种方式的检查可以解决绝大部分的iago攻击漏洞(82.35%)。这些边界语义可能需要手动地从OS的代码或者syscall的实现细节中来获取并配置在OFL,然而这种方式只需要一次的effort就可以有效的应用在对应的OS版本上。


b. Stateful:比起local与static,Stateful类型的iago漏洞需要更复杂的逻辑来维护同步的状态。比如记录syscall的执行返回历史记录。然而这种记录如果依赖OFL来完成,则会引入更多的代码,由于OFL属于TEE的TCB,因此完全依赖OFL来实现这种类型的iago攻击是与减小TEE的TCB的理念相悖的。因此,作者的建议是依靠应用程序本身来抵御这种类型的攻击。例如作者指出6类受epoll_wait影响的应用程序可以简单地通过将epoll_wait替换成其他类型的polling系统调用像是poll和select来解决。


c. Unauthenticated Channel:针对这种依赖OS通道通信的iago漏洞,作者提出的解决方式是加密通道的信息来解决。


d. External:这种类型的iago漏洞则需要应用开发者自己注意,例如应用不应该假设其没有做追踪的来源是可信的。同时一些文件和类似文件大小的metadata需要被加密来防止被恶意修改。

《论文分享》Emilia: Catching Iago in Legacy Code


5. OFL analysis

最后,作者对一些已有的SGX开源项目进行了分析,发现这些工具对几种类型的iago攻击的防御都有一些不完善的地方。

《论文分享》Emilia: Catching Iago in Legacy Code



原文始发于微信公众号(COMPASS Lab):《论文分享》Emilia: Catching Iago in Legacy Code

版权声明:admin 发表于 2022年11月28日 下午5:46。
转载请注明:《论文分享》Emilia: Catching Iago in Legacy Code | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...