-
-
[翻译]android11中的系统加固
-
发表于: 2020-8-1 21:20 18616
-
在android 11中,我们继续增强了系统安全。现在我们有更安全的默认设置,增加了内存分配的安全性,并使用了编译器级的防御技术用于对抗各种漏洞利用技术。
在android 11中,我们为用户空间和linux内核同时启用了自动内存初始化。内存未初始化漏洞常见于C/C++中,它意味着你使用了一个未经初始化的变量。这种类型的漏洞可能带给你一定的迷惑,甚至“未初始化”这个术语可能会误导你。未初始化暗示着某个变量的值是随机的,然而事实上,它不是随机的,而是上一次操作中设置好的值。在攻击者眼中,这个是可预测的,甚至是可控制的。而且它还可能会导致更好严重的漏洞,如ASLR绕过导致的信息泄露,由栈/堆喷导致的控制流劫持。另一个可能的副作用是在高级别的编译器优化中,可能会使程序行为变得不可预测。在相关的C标准中,这种行为是未定义行为。
在生产实践中,使用未初始化内存也很难检测。未初始化的内存可能在大多数时候都有一个相对“安全”的值,从而导致错误代码在不为人知的角落里待了好几年。当这种漏洞发生时,要在源代码里找到这样的漏洞是非常困难的,尤其是这个漏洞非常难以触发。
消除所有这种漏洞相比于逐个地去解决这种漏洞要更高效一些。自动栈变量初始化依赖于clang编译器的一个功能,它可以自动把栈变量初始化为0或某个特定值。
把字符串,索引,指针和大小默认初始化为0是一种更安全的行为。然后对于返回值来说,初始化为0又不那么安全,因为它使得代码中的bug更难暴露出来。而将栈变量初始化为特定值是为了暴露出更多的漏洞,它对于返回值来说会更安全,但对字符串,索引,指针和大小就不那么安全了。
自动栈变量初始化会在整个android用户空间中启用。在android 11开发中,我们最初将默认值初始化为特定值,以此把漏洞都暴露出来,在几个月后,我们又将默认值设为0以提高安全性。OS级的开发者可以设置AUTO_PATTERN_INITIALIZE=true m
以把漏洞尽可能多地暴露出来。
自动栈和堆初始化最近已经被合并到linux内核的上游了。现在这些功能已经能用在早期的android内核中,包括4.14,4.19和5.4。这些功能会强制把局部变量和堆变量初始化为已知的值,从而使得攻击者不能再控制它们,即使泄露了,也无关紧要。虽然这些功能会带来一带性能上的开销,但也使得系统更加稳定和安全。
在linux上游,我们使用CONFIG_INIT_STACK_ALL
来进行内核栈初始化。它当前依赖于Clang的栈变量特定值初始化,不过它在将来可能会变化。
堆初始化由两个启动时标志控制, init_on_alloc 和 init_on_free,前者在堆分配对象空间时初始化内存为0(想想内核中的s/kmalloc/kzalloc),而后者在对象释放之前做同样的事情(它帮助减小了安全敏感数据的生命周期。init_on_alloc是缓存友好的,对性能的影响更小(低于2%),因此,android内核中采用的是它。
在android 11中,Scudo取代了Jemalloc作为android默认的native层分配器。Scudo在内存分配上更安全,它能够检测及减小堆中内存崩溃漏洞造成的影响,如:
Scudo并不能完全预防漏洞利用,但它添加了大量合理性校验(sanity checks),能够有效减少堆中的内存崩溃漏洞。
除此之外,通过减少配置模式的可预测性,使用大小分割内存分配,使得内存崩溃漏洞的利用变得更加困难。
在我们内部的测试中,已经证明了Scudo能够将先前未检测到的安全和稳定性漏洞暴露出来。
Android 11引进了GWP-ASan,一个生产环境中的堆内存安全漏洞检测工具,它被直接整合进native层的内存分配器Scudo中。GWP-ASan能够检测并在堆内存安全漏洞发生时提供报告。在系统进程和系统app中,无论是32位还是64位进程,都默认开启了这个功能。
通过在App的AndroidManifest.xml中添加一行可选行,GWP-ASan也可以用于开发者应用。不需要复杂的构建(build)支持或是重编译必要的库文件。
在android中采用Arm内存标签扩展,android 11中包含了对内核HWASAN的支持,也就是基于标签的软件KASAN.从android 10开始就已经支持用户空间的HWASAN了.
KernelAddressSANitizer(KASAN)是一个动态内存错误检测器,用于找到linux中的越界和use-after-free漏洞.它使用的基于标签模式的软件是一种软件,它在内核中实现了内存标签的概念,基于标签的软件KASAN在4.14,4.19和5.4的android内核中都可以使用,它可以通过CONFIG_KASAN_SW_TAGS内核配置项启用.当前基于标签的KASAN只支持标记slab内存,将来会支持其他类型的内存(如栈和全局变量)
相比于通用型KASAN,基于标签的KASAN在内存需求方面明显更低(参考内核提交以获取更多细节).这使得它能够用在内部试用测试设备上.另一个基于标签的KASAN的用例是检测与当前内核代码中标记内存的兼容性.因为基于标签的KASAN和将来的内核内的MTE支持都是基于相似的概念,那么将来在添加内核内的MTE支持时,内核代码的工作量会更少.
在先前的发行版中,我们进一步地扩展了编译器的防御策略.它包括某些核心库的整型和越界检查器.例如,libminikin字体库以及libui渲染库现在都有了越界检查.通过在这些组件中实现整型溢出检查器和越界检查器,我们加固了NFC栈.
除了在检查器方面的增强,我们还增加了对CFI漏洞利用的防御.CFI在android的网络守护进程,DNS解析器以及其他的核心javascript库,如libv8和PacProcessor中使用.
在先前的android 10中,我们为软件编解码器发布了一个新的沙盒.成果非常可喜.因为自android 5.0中臭名昭著的stagefright漏洞出现以来,android 10是第一个在媒体框架中其漏洞严重级别为0的android版本.
[招生]系统0day安全班,企业级设备固件漏洞挖掘,Linux平台漏洞挖掘!
赞赏
- [原创]分享一个基本不可能被检测到的hook方案 44816
- [翻译]利用Qiling框架实现带有代码覆盖率信息的PE文件模拟执行 23478
- [翻译]android11中的系统加固 18617
- [翻译]使用hook绕过EDR内存保护 18369
- [翻译]SATURN反混淆框架 15797