-
-
[翻译]Android Q 版本在安全加固方面的改进
-
发表于: 2019-6-26 21:46 8581
-
现已公布 Android Q Beta版本。在Android Q 引入的众多新特征中也包括了安全加固方面。虽然每个Android版本中都添加了新的安全功能,但加固通常是指对现有组件进行安全性改进。
在优先考虑平台加固时,我们会分析多个数据源的数据,包括我们的漏洞奖励计划(vulnerability rewards program,VRP)。之前的安全事件告诉我们哪些组件需要进行加固。Android每月发布的安全公告中就包含了通过我们的VRP报告的Android开源项目(AOSP)中所有高危漏洞的补丁。修复漏洞是必须的,同时我们也从元数据中获得了很多有用信息——对漏洞位置和类别的分析。基于这些信息,我们可以将下列策略应用于现有组件:
来看一下2018年产生高危漏洞的各组件信息及漏洞产生的原因:
大多数Android漏洞都是由媒体组件和蓝牙引起的。Use-after-free(UAF),整数溢出,和越界(OOB)读写是大多数漏洞产生的原因,而且越界读写占了大多数。
在Android Q中,我们将软件编解码器从主要的mediacodec服务中移出到受限沙箱中。这是我们通过将各种多媒体组件隔离到拥有较少特权的沙箱来提高安全性的一大进步。正如Project Zero的Mark Brand在他的 Return To Libstagefright 博客中指出的那样,受限沙箱是攻击者不愿意触及的地方。在2018年中,媒体组件的近80%的高危漏洞都是发生在软件编解码器中,所以将它们隔离开来是一大进步。根据Android安全指南,由新的mediacodec沙箱提供的安全措施将使之前的漏洞降低一个危险级别。
下图概述了最近的Android版本中媒体服务布局的演变过程。
通过这一举措,现在媒体漏洞的两个主要来源都被限制在沙箱中。软件编解码器类似于extractor,因为它们都有广泛的代码解析来自不可信源的比特流。在源代码中识别出漏洞后,可以通过将精心制作的媒体文件发送到媒体API(例如,MediaExtractor或MediaCodec)来触发漏洞。将这两项服务沙箱化使我们能够在不影响性能的情况下降低潜在安全漏洞的严重性。
除了限制风险较高的编解码器之外,还有许多方法可用于防止常见类型的漏洞。
错误的或者缺少数组内存边界检查是34%的Android用户空间漏洞产生的原因。在编译时已知数组大小的情况下,LLVM的bound sanitizer(BoundSan)会自动检查数组以防溢出。
BoundSan 指令
BoundSan在Android Q的11个媒体编解码器和蓝牙栈中都可以使用。通过优化一些不必要的检查,性能开销降低至不到1%,BoundSan已经发现/防止了编解码器和蓝牙中的潜在漏洞。
当我们第一次在媒体框架中使用整数消毒剂(integer sanization,IntSan)时,Android创造性地在Android Nougat中使用了这些消毒剂。这一项工作在后续很多Android版本中都有继续,并且在防止可利用漏洞方面效果显著。例如,Android Pie中的IntSan减轻了11个高危漏洞。启用IntSan是一项很有挑战性的工作,因为溢出通常是良性的,无符号溢出也是定义好的,有时甚至是故意的。这和Bound Sanitizer不一样,因为越界读写通常不是有意的,而且越界读写是可利用的。启用IntSan是一项多年的项目,但在Android Q中,通过包含11个以上的编解码器我们已经在媒体框架中启用了它。
IntSan通过在发生溢出时检测算术运算使其停止来达到目的。但是这种检测会对性能有影响,所以评估对CPU使用率的影响是必要的。当性能影响较大时,我们会在手动检查安全性后确定热函数并单独禁用这些函数的IntSan。
BoundSan和IntSan是威力较大的减缓措施,因为(一旦使用)它们能从根源上避免内存安全漏洞。接下来要说的减缓方法针对的是共同利用技术。这些减缓方法能在一定程度上减轻漏洞利用的可能,因为它们通过限制漏洞的使用让漏洞利用变得更加困难。
在Android Pie的媒体框架、蓝牙和NFC中都启用了LLVM的控制流完整性(Control Flow Integrity,CFI)。通过保护流程图的前向边,例如指针函数和虚拟函数,CFI使得代码重用攻击变得困难。在Android Q中使用LLVM的Shadow Call Stack(SCS)保护返回地址,以保护控制流图的后向边。SCS的实现方法是将返回地址存储在一个单独的影子堆栈中,该影子堆栈通过将其位置存储在x18寄存器中来防止泄露,现在该寄存器由编译器保留。
SCS指令
由于影子堆栈是单独的,SCS的性能开销可以忽略不计,而且它增加的内存是很小的。在Android Q中,SCS已在部分蓝牙堆栈中打开,也可用于内核。我们将在即将发布的帖子中对此做进一步介绍。
和SCS一样,只执行内存(eXecute-Only Memory,XOM)是为了让共同利用变得更加困难。XOM通过增强由ASLR提供的保护来实现,这又反过来使得攻击者先暴露它们打算重用的代码的位置,从而使代码重用攻击变得更加困难。这就意味着攻击者现在需要两个漏洞,一个读原语和一个写原语,以前只需要一个写原语就能实现它们的目标。XOM通过使代码不可读来防止泄露(代码段的内存泄露)。试图读取只执行代码会导致进程安全中止。
从Android Q开始,平台提供的二级制文件和库中的AArch64代码段都作为只执行加载。并非所有的设备都是这样的,因为它有一定的要求:硬件(ARMv8.2+)和内核(Linux 4.9+,CONFIG_ARM64_UAO)。对于targetSdkVersion低于Q的应用程序,Android的zygote进程将放宽保护以避免潜在的应用程序破坏,但64位系统进程(例如,mediaextractor,init,voId等)依然受到保护。XOM保护是在编译时应用,所以没有内存和CPU开销。
Scudo是一个动态堆分配器,旨在抵御堆相关的漏洞,如:
Scudo不直接阻止漏洞利用而是通过主动内存管理使漏洞利用变得更加困难。它根据性能要求在每个进程的基础上进行配置。Scudo在媒体框架中的extractor和编解码器中都可使用。
AOSP利用许多开源项目来构建和保护Android。谷歌正在积极回馈这些项目,涉及多个安全关键领域:
AddressSanitizer的创建者和主要贡献者,以及LLVM的其他“sanitizer”(基于编译器的动态测试工具)。
LLVM中基于编译器的加固工具的主要贡献者(ControlFlowIntegrity, ShadowCallStack)。
fuzzing工具(AFL, libFuzzer, honggfuzz, syzkaller)和针对用户空间和操作系统内核的fuzzing 结构 (oss-fuzz, syzbot) 的创建者。
LLVM中 Scudo hardened allocator 的主要贡献者。
感谢 Ivan Lozano, Kevin Deus, Kostya Kortchinsky, Kostya Serebryany, 和Mike Antares对本文的贡献。
原文地址:https://security.googleblog.com/2019/05/queue-hardening-enhancements.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+GoogleOnlineSecurityBlog+%28Google+Online+Security+Blog%29
编译:看雪翻译小组 lumou
校对:看雪翻译小组 梦野间
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!