近日,谷歌发布 5 月份补丁更新,本次共修复了32个漏洞。其中包含一个Qualcomm漏洞,威胁等级为高危,CVE编号为CVE-2016-2443,CNNVD编号为CNNVD-201605-060。
本文主要分析该漏洞的局限性和可利用性。
测试设备为运行Qualcomm SoC的Nexus 7 2013, AOSP中与测试设备对应的代码名称为flo。由于内核的master分支为空,因此需要切换分支,例如,检查android-msm-flo-3.4-marshmallow-mr1分支。
Linux kernel的一个比较有趣的功能和攻击面就是debug filesystem或debugfs,攻击者可以通过与debugfs创建的文件系统交互获取内核代码路径。
debugfs
以下引用自Documentation/filesystems/debugfs.txt目录下的Linux内核文档,是比较典型的对debugfs的描述:
debugfs挂载在/sys/kernel/debug目录下,并且在Android设备中通常符号链接到/d/目录。
发现漏洞
相比从搜索文件系统项开始,更好的是使用相反的方法:内核代码检查。首先,寻找危险的函数和宏,例如writel,并且回溯它们的使用方法检查其是否可以被用户空间的debugfs或devices利用。
writel宏/函数是相关的实现,但是实际上它的功能等同于void writel(unsignedvalue, address)函数,该函数用于向地址中写入值。也就是说,如果攻击者可以控制address和value参数,那么就可以想内核写入任意内容。
漏洞详情
通过搜索代码,发现了debugfs条目的writel函数: 该debugfs条目为root用户可写(该限制降低了漏洞的影响程度),所有用户可读。
在分析代码前,首先来测试一下POC,以root权限运行: 测试设备内核崩溃并重启,在/proc/last_kmsg中可以查看内核崩溃的摘要信息: 可以看出,通过向0×41414141中写入0×42424242导致内核崩溃。注意,以未提权用户权限读取该内容时也可以导致内核崩溃:cat /sys/kernel/debug/mddi/reg
如果用户可以避免内核崩溃,那么攻击者就可以利用这一点以未提权用户权限导致信息泄露,获取内存中的重要信息。
代码分析
从后往前看,从在drivers/video/msm/mdp_debugfs.c文件中创建/sys/kernel/debug/mddi/reg条目的代码开始: 在该段代码中,内核会创建debugfs条目,并分配pmdh_fops文件操作处理程序(在相同的文件中:drivers/video/msm/mdp_debugfs.c): 在pmdh_reg_write成员中有一个用于读取文件系统写入数据的函数(仍然在drivers/video/msm/mdp_debugfs.c文件):
在mddi_reg_write函数中会调用我们在上面提到的没有充分边界检查的writel函数(drivers/video/msm/mdp_debugfs.c文件):
对于读操作,这是一个非常类似的代码路径:mddi_reg_read -> readl漏洞利用
任意内核内存写入是内核漏洞利用最基本的方式,因此比较容易实现。例如,可以覆盖函数指针,劫持内核进而执行任意代码。
与用户空间相比,内核代码执行在Android平台上效果会更加显著。如果想要尝试利用TrustZone,就需要在内核中执行代码。
利用该漏洞首先要root。其中一个利用实例为:如果获取了一个root服务的代码执行权限,但是它的SELinux上下文是受限制的,那么就需要利用该漏洞完全禁用SELinux,获取不受限制的系统完全访问权限。
还没有评论,来说两句吧...