根本原因分析
CVE-2023-48409
该漏洞在2023年12月的Pixel安全公告中被覆盖。通过回滚设备版本到早期补丁UP1A.231005.007进行分析:
|
|
具体来说,漏洞出现在整数溢出计算中:
- 分配的对象大小:
8*buffer_count*2 + 4*live_ranges_count([1]和[2]) - 从分配对象的偏移量:
+ 8*buffer_count*2([1]和[3])
如果精心构造值使得8*buffer_count*2 + 4*live_ranges_count = (1<<64) + <object_size>,我们的live_ranges缓冲区将位于分配对象之前4*live_ranges_count - <object_size>字节处。
什么是CONFIG_HARDENED_USERCOPY?
CONFIG_HARDENED_USERCOPY是自Linux v4.8引入的内核配置。在copy_*_user期间,内核调用check_object_size,如果指针落在SLUB对象内,它确保读/写区域必须完全落在该特定对象的可用区域内。
缺失的部分:CVE-2023-26083
原始漏洞利用中的第二个漏洞CVE-2023-26083涉及驱动中的流功能(tlstream),该功能自由暴露给用户空间进程,可能包含某些对象的内核地址作为纯字节。
单漏洞提权
物理映射喷射
ret2dir是一种滥用physmap的流行技术,physmap是将物理内存直接1:1映射到内核虚拟地址空间。
通过物理映射喷射,我们可以耗尽页分配器,最大化对象在我们选择地址分配的机会。
页表喷射
脏页表技术依赖于这样一个事实:页表本身由页分配器作为普通order-0块分配,通过写原语,我们可以修改其条目,使mmap的用户态虚拟页反映几乎任何任意的物理页。
从物理到虚拟:转换我们的原语
有趣的是,我们仍然没有适当的泄漏。尝试munmap相关页面不会立即释放页表,而是通过RCU排队。
Android的独特挑战
绕过Android的应用沙箱
在Termux环境中,当我们尝试调用setuid(0)时,程序立即因SIGSYS而崩溃。这是由于所有应用程序上默认启用的seccomp过滤器。
禁用SELinux强制
一旦我们拥有任意内核写入,通过清除selinux_state.enforcing位来完全禁用SELinux是相对简单的。
意外发现
理解时间线流泄漏
Mali GPU驱动提供了一个称为时间线流(tlstream)的功能,它基本上充当事件记录器。它通过跟踪点提供相关函数在驱动中记录信息的功能,包括内核中的指针(指向GPU相关对象)。
命令流前端
第3代Valhall GPU引入了命令流前端(CSF)作为其先前作业管理器(JM)模型的替代,以更好地适应现代API(如Vulkan)的需求。
黄金对象:kbase_context
在源代码中快速挖掘后,我发现了不同的低挂果实:kbase_context在上下文创建时立即泄漏其地址,并且它包含一个task_struct指针,直接指向我们当前的任务!
清理:使漏洞利用实用
在Android上,仅清除uid/gid不足以获得完全权限。需要考虑的更多事项:
- 我们还没有所有能力
- SELinux尚未禁用
- 进程沙箱仍然有效
- 退出进程会使内核崩溃
结论
这项研究成功证明了Pixel 6 Pro可以使用单个漏洞进行利用,挑战了传统上需要CVE-2023-48409和CVE-2023-26083两个漏洞的常规认知。
Android确实有其有趣的特性,既(主要)加强又(有些可能无意中)削弱了其防御,如上述漏洞利用过程中所示。
至于分析的两个漏洞,本文希望强调简单的弱点如何仍然可以在复杂的内核驱动中容易找到,以及它们可能造成的损害。