以下是按组件和原因从2018年开始的高严重性漏洞:
Android的大多数漏洞都发生在多媒体和蓝牙组件中。释放后使用(UAF),整数溢出和越界(OOB)读/写构成漏洞的90%,其中OOB是最常见的漏洞。
软件编解码器(SW Codec)
从Android Q中,软件编解码器从媒体编解码器服务中移出到受约束的沙箱中。这是我们通过将各种媒体组件隔离到特权较低的沙箱中来提高安全性的重要一步。受约束的沙箱并不是攻击者想要终结的地方。在2018年,媒体组件中大约80%的严重/高严重性漏洞发生在软件编解码器中,这意味着进一步隔离它们是一个很大的进步。由于新的mediaswcodec沙箱提供了增强的保护,因此根据Android的严重性准则,这些相同的漏洞将具有较低的严重性。
下图概述了最近的Android版本中媒体服务布局的演变。
- 在N之前,媒体服务都在一个整体的媒体服务器进程中,提取器在客户端内部运行。
- 在N中,我们提供了一个主要的安全性架构,在该架构中,许多低级媒体服务被分离为具有减少特权的沙箱的单个服务流程。提取器移至服务器端,并放入受约束的沙箱中。Mediaserver本身仅保留了几个高级功能。
- 在O中,服务被“ 分散 ”,并进一步被剥夺特权,即被分离到各个沙箱中并转换成HAL。media.codec服务成为HAL,同时仍托管软件和硬件编解码器实现。
- 在Q中,从media.codec进程中提取软件编解码器,然后移回系统端。它成为公开编解码器HAL接口的系统服务。Selinux策略和seccomp筛选器在此过程中进一步加强。特别是,虽然先前的媒体编解码器进程可以访问硬件加速编解码器的设备驱动程序,但软件编解码器进程却不能访问设备驱动程序。
通过此举,现在还有两个主要漏洞源,这些漏洞是在受限流程中严格沙箱化的。软件编解码器与提取器相似,因为它们都具有广泛的代码来解析来自不受信任来源的比特流。一旦在源代码中识别出漏洞,就可以通过将精心制作的媒体文件发送到媒体API(例如MediaExtractor或MediaCodec)来触发该漏洞。将这两项服务沙盒化使我们能够降低潜在安全漏洞的严重性,而不会影响性能。除了限制风险较高的编解码器外,还需要做很多工作来防止常见类型的漏洞。
Bound Sanitizer
数组上的内存边界检查不正确或丢失,约占Android用户空间漏洞的34%。如果在编译时知道阵列大小,则LLVM的绑定清理器(BoundSan)可以自动检测阵列,以防止溢出和安全地失败。
BoundSan instrumentation
在11个媒体编解码器和整个Android Q的蓝牙堆栈中启用了BoundSan。通过优化消除了许多不必要的 检查,性能开销降低到了不到1%。BoundSan已经发现/防止了编解码器和蓝牙中的潜在漏洞。
More integer sanitizer in more places
首次开始在媒体框架中推出整数清理(IntSan)时, Android 率先在Android N 使用了sanitizer.每个发行版均会继续进行这项工作,并且在防止其他可利用的漏洞方面非常成功。例如,Android P 中新的IntSan覆盖范围缓解了11个关键漏洞。启用IntSan具有挑战性,因为溢出通常是良性的,并且无符号整数溢出定义明确,有时是有意的。OOB读/写始终是意料之外的,并且经常被利用。启用Intsan历时多年,在 android Q,我们就在媒体框架中完全启用了它。
IntSan Instrumentation
IntSan通过检测算术运算以在发生溢出时中止工作。该工具可能会对性能产生影响,因此有必要评估对CPU使用率的影响。如果对性能的影响太大,我们将手动检查它们的整数安全性后,确定热点function,并分别禁用这些function的IntSan。
BoundSan和IntSan被认为是强有力的缓解措施,因为它们(在应用时)防止了内存安全漏洞的根本原因。
Shadow Call Stack
在Android P的媒体框架,蓝牙和NFC中启用了LLVM的控制流完整性(CFI)。CFI通过保护调用的stack(例如函数指针和虚函数),使代码重用攻击更加困难。Android Q使用LLVM的影子调用栈(SCS)来保护返回地址。SCS通过将返回地址存储在单独的影子堆栈中来实现此目的,通过将其地址存储在x18寄存器中可以防止泄漏,该寄存器现在由编译器保留。
SCS Instrumentation
由于单独的堆栈,SCS的性能开销可忽略不计,并且内存增加很小。在Android Q中,SCS已在部分蓝牙堆栈中打开,并且也可用于内核。
eXecute-Only Memory
像SCS一样,XOM的目的是使常见的攻击技术变得更加昂贵。它通过加强地址空间布局随机化(ASLR)已经提供的保护来做到这一点,这反过来又要求攻击者首先泄漏他们打算重用的代码位置,从而使代码重用攻击更加困难。这通常意味着攻击者现在需要两个漏洞,一个读取原语和一个写入原语,以前为了实现其目标,仅需要一个写入原语即可。XOM通过使代码不可读来防止泄漏(代码段的内存泄漏)。尝试读取仅执行代码会导致进程安全中止。
Tombstone from a XOM abort
从Android Q开始,二进制文件和库中平台提供的AArch64代码段被加载为仅执行。并非所有设备都会立即受益,因为此强制执行具有硬件依赖性(ARMv8.2 )和内核依赖性(Linux 4.9 ,CONFIG_ARM64_UAO)。对于targetSdkVersion低于Q的应用程序,Android的进程将放宽保护,以避免潜在的应用程序损坏,但会保护64位系统进程(例如mediaextractor,init,vold等)。XOM保护在编译时应用,并且没有内存或CPU开销。
Scudo Hardened Allocator
Scudo是一种动态堆分配器,旨在针对修复堆相关的漏洞,例如:
- 释放后使用:隔离释放的块。
- 双重释放:通过跟踪块状态。
- 缓冲区溢出:通过检查标头求和。
- 堆布局处理:通过改进的随机性。
Scudo不会阻止利用,而是以使利用更加困难的方式主动管理内存。可根据性能要求在每个过程中对其进行配置。在媒体框架的提取器和编解码器中启用了Scudo。在 Andorid 11 中,将作为heap 的分配器。
This table covers the definitions of process types. The process type can be defined by the type of app or process or the area in which it runs. This table is ordered from least to most privileged.
rocess type | Type definition |
---|---|
Constrained process | A process that runs in a highly limited SELinux domain. OR A process that's significantly more limited than a normal app. |
Unprivileged process | A third-party app or process. OR An app or process that runs in the SELinux untrusted_app domain. |
Privileged process | An app or process with capabilities that would be forbidden by the SELinux untrusted_app domain.OR An app or process with important privileges that a third-party app can't obtain. OR A built-in hardware component on the device that isn't part of the trusted computing base (TCB). |
Trusted computing base (TCB) | Functionality that's part of the kernel, runs in the same CPU context as the kernel (such as device drivers), has direct access to kernel memory (such as hardware components on the device), has the capability to load scripts into a kernel component (for example, eBPF), the Baseband Processor, or is one of a handful of user services that is considered kernel equivalent: init, ueventd, and vold. |
Bootloader | A component that configures the device on boot and then passes control to the Android OS. |
Trusted Execution Environment (TEE) | A component that is designed to be protected from even a hostile kernel. |
Secure element (SE) | An optional component designed to be protected from all other components on the device and from physical attack, as defined in Introduction to Secure Elements. |