[原创]CVE-2019-8635:macOS double free root cause
在macOS存在一个double free漏洞,这个漏洞由AMD组件的内存损坏所引起。如果成功被利用,攻击者可以完成权限提升并且可以再root权限下执行恶意代码。
漏洞简单介绍
其实这个cve包含2个相似的漏洞:
- discard_StretchTex2Tex方法。
- 还有一个存在一个类中AMD Radeon class(AMDRadeonX400_AMDSIGLContext)对sideband tokens的处理过程。它是IOAccelGLContext2的派生类,并从IOAccelGLContext2扩展。 这些类用于在macOS机器上渲染图形。具体是在
AMDRadeonX4000_AMDSIGLContext类的AMDSIGLContext::process_StretchTex2Tex函数中。并且在打开AMDRadeonX4000_AMDGraphicsAccelerator 客户端的连接类型为1的情况下,这个类可以被AMDRadeonX4000_AMDSIGLContext的selector 2用户态函数IOAccelContext2::submit_data_buffers访问。
漏洞成因
下面简要介绍下这两个漏洞的成因:
- 第一个漏洞:AMDRadeonX4000_AMDSIGLContext discard_StretchTex2Tex double free漏洞
这个漏洞可以在用户态触发,但是必须最低要求是能够在目标macOS 系统获取执行低权限的代码。因为没有对用户提供的数据合法验证,能够读取已分配的数据结构,攻击者利用此漏洞再结合其他的漏洞可以在内核态提升权限。 - 第二个漏洞:AMDRadeonX4000_AMDSIGLContext Double Free漏洞
在同一个AMD组件类中,它是在对sideband token的处理过程中,也存在类似的一个double free漏洞。和上一个漏洞一样,是一个本地提权漏洞,必须在目标系统有执行低权限代码的能力,也就是个普通用户。具体是在函数AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex中,在对对象操作前,没有对其进行有效的验证,攻击者可以利用此弱点,从内核态提升权限。
本质上讲,就利用特点来看,两个漏洞可能是相似的,都是对对象在释放之前,没有对对象的数据来源和数据的值进行验证,可以在用户态直接映射内存就行修改索引,达到释放相同的对象,并且释放两次,引发漏洞。
但具体调用的函数上有一些区别,我们看具体分析:
上图AMDRadeonX4000_AMDSIGLContext: discard_StretchTex2Tex函数的伪代码中我们看v10和v11是如何获取的,如果 (cmdinfo+32)等于0x8c00, 这个IOAccelResource v10和v11从IOAccelShared2(this+172)获取到,索引分别为(shareMem_start_address_187_offset16+8) 和 (shareMem_start_address_187_offset16+12),这个函数也会用IOAccelResource2::clientRelease()释放这两个加速资源。如果用户态映射相同的索引,lookupResource函数相当于从这两个索引中取值,客户端也会释放相同的对象两次,这就是漏洞所在、核心在于我们让(shareMem_start_address_187_offset16+8)和(shareMem_start_address_187_offset16+12)的值相同,而shareMem_start_address_187_offset16的区域可以被用户态控制和映射,通过修改而达到目的。
第二个漏洞:

如上图函数AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex的伪代码片段。结构和上一个漏洞很类似,如果v15==0x8c00, accelResource_offset8和accelResource_offset12会从IOAccelShared2获取到,索引为共享内存+24和共享内存+28的值。最后,这个函数会从 IOAccelShared2 _rst释放accelResource_offset12, 如果 accelResource_offset8->member2!=10, 这个函数也会从IOAccelShared2释放accelResource_offset8,这样的话,如果我们设置共享内存偏移24和28的位置为相同的值,将会释放相同得对象accelResource两次,引发了漏洞。
在AMDRadeonX4000_AMDSIGLContext类里的process_StretchTex2Tex函数中,IOAccelResource2::clientRelease()将会释放这两个对象,而这两个对象accelResource2均来自accelShare2共享内存,对象通过IOAccelShared2::lookupResource函数以各自的索引值为参数来得到,这两个索引值可以被用户态通过 IOAccelContext2设置共享内存来控制。 如果用户态映射了两个相同的索引值,就会释放两次相同的对象。
用户态映射内存
接下来看IOAccelContext2::processSidebandBuffer:

这两个漏洞的伪代码片段显示了共享内存指向了command stream info +24,这个command stream info buffer在IOAccelContext2::processSidebandBuffer设置,在图中,我们看到 v5=共享内存+16 ,并且v5赋值给了this->member196, this->member196也指向了commandStreamInfo+24。
注意:上传附件及图片大小不得大于30M。
⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。
