作者:启明星辰ADLab
最近,在进行 Android 源码审计的时候,发现了存着于高通声卡驱动中的一个条件竞争漏洞 CVE-2017-7368(CNVD-2017-10809,CNNVD-201704-037)。虽然审计的源码稍微有点过时,谷歌在六月份已经修复了该漏洞,但是整个漏洞发现的过程和漏洞的分析还是比较有意义的。本文首先介绍高通声卡的攻击面和攻击向量,然后详细分析该漏洞成因,最后给出 POC。
Android 是基于 Linux 的移动操作系统,其基本架构如下图:
其中,驱动位于 Linux 内核层,驱动程序是一个软件组件,可以让操作系统和设备彼此通信。驱动程序会创建一些接口,允许用户从用户空间访问,以便控制硬件。如果驱动程序中存着漏洞,用户就可以从用户权限提升到内核权限,也就是 root 权限。
Linux 驱动程序一般会在 /dev
目录下创建一些文件,然后用户可以打开这些文件,通过 ioctl 函数控制硬件。其中,声卡创建的文件在 /dev/snd
目录下,如下图:
声卡驱动一般是由第三方厂商实现,如果采用高通的芯片,那么声卡驱动就是由高通提供,而第三方厂商的代码更容易出现一些安全漏洞。因此高通的声卡驱动是一个非常好的攻击面,ioctl 函数就是这个攻击面的攻击向量。
出现漏洞的代码位于 sound/soc/msm/qdsp6v2/msm-lsm-client.c
:
用户空间通过打开 /dev/snd/
目录下的对应文件,然后设置 ioctl 函数的 cmd 参数为 SNDRV_LSM_REG_SND_MODEL_V2
,就会进入这块代码。
问题主要出现在 767 行和 775 行,第 767 行驱动程序为 ptrd->lsm_client
分配 snd_model_v2.data_size
长度的内核空间,然后将 snd_model_v2.data
(用户空间数据)拷贝到分配的内核空间里。其中,snd_model_v2
是用户空间传入的参数,snd_model_v2.data_size
和 snd_model_v2.data
都是用户可以控制的,ptrd->lsm_client
是一个全局变量。这段代码如果单线程执行,并不存在什么问题,分配了snd_model_v2.data_size
长度的内核空间,并从用户空间拷贝对应长度的用户空间数据,不会出现越界。但这里的 ptrd->lsm_client
是一个全局变量,如果多线程运行,就会出现一些问题。
这里,我们假设有两个线程,线程 A 和线程 B。
假设线程 A 请求分配 2000 个字节的空间,这时内核执行到 767 行为 ptrd->lsm_client
分配了 2000 字节,ptrd->lsm_client
的长度为 2000,这时线程 A 挂起,执行线程 B。
线程 B 请求分配 1000 个字节的空间,这时内核执行到 767 行为ptrd->lsm_client
分配了 1000 字节,ptrd->lsm_client
的长度为 1000,这时线程 B 挂起,执行线程 A。
线程 A 继续执行到 775 行,进行数据拷贝,此时 ptrd->lsm_client
的长度已经变成了 1000,而线程 A 并不知情,依然拷贝 2000 个字节到 ptrd->lsm_client
,这时就会出现一个堆的溢出。
但是,这种情况并不一定会出现,只有一定的概率出现。不过,如果请求的次数足够多,这种情况就会出现。
漏洞修补方案比较简单,增加一个锁即可。
分析清楚漏洞的成因之后,就可以进行POC的构造。首先,打开 /dev/snd
下对应的文件。
然后,构造两个 snd_model_v2
结构体,一个的 data_size
设置为 2000,另一个设置为 1000。
最后,开启两个线程不断循环的进行请求,即可触发该漏洞。
条件竞争的漏洞目前很难 fuzz 出来,只能靠安全人员的代码审计,所以这类漏洞还是会有很多。并且 Android 的碎片化导致安全更新很难全部部署到所有的手机上,仍有大量的手机面临着漏洞的风险。
启明星辰积极防御实验室(ADLab)
ADLab成立于1999年,是中国安全行业最早成立的攻防技术研究实验室之一,微软MAPP计划核心成员。截止目前,ADLab通过CVE发布Windows、Linux、Unix等操作系统安全或软件漏洞近300个,持续保持亚洲领先并确立了其在国际网络安全领域的核心地位。实验室研究方向涵盖操作系统与应用系统安全研究、移动智能终端安全研究、物联网智能设备安全研究、Web安全研究、工控系统安全研究、云安全研究。研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。