CVE-2019-8635: Apple macOS double free漏洞分析

ang010ela 新闻 2019年7月5日发布
Favorite收藏

导语:Trend Micro研究人员在macOS中发现一个double free漏洞,漏洞CVE编号为CVE-2019-8635。

Trend Micro研究人员在macOS中发现一个double free漏洞,漏洞CVE编号为CVE-2019-8635。该漏洞是由于AMD组件中的内存破坏漏洞引发的。如果该漏洞被成功利用,攻击者就可以实现权限提升,并在系统中以root权限执行任意代码。目前苹果公司已经释放了漏洞补丁。

CVE-2019-8635包含2个漏洞,分别是discard_StretchTex2Tex方法和AMD Radeon类的processing of sideband tokens处理AMDRadeonX400_AMDSIGLContext。这是IOAccelGLContext2提取的类,这是从IOAccelContext2类中扩展得到的。
这些类的作用是在macOS机器上进行图形渲染。
漏洞存在于AMDRadeonX4000_AMDSIGLContext类的discard_StretchTex2Tex和AMDSIGLContext::process_StretchTex2Tex函数中,可以使用AMDRadeonX4000_AMDSIGLContext userclient和selector 2函数IOAccelContext2::submit_data_buffers来进行访问,AMDRadeonX4000_AMDGraphicsAccelerator客户端可以用connect type 1打开。

AMDRadeonX4000_AMDSIGLContext discard_StretchTex2Tex Double Free权限提升漏洞

该漏洞允许攻击者在用户空间(userspace)执行代码。为了利用该漏洞,攻击者必须首先可以在目标macOS系统上执行低权限的代码。
该漏洞是由于没有对用户提供的数据进行适当验证造成的,最终会导致对分配的数据结构的读。攻击者正是利用了这一点和其他漏洞一起来进行权限提升,获取kernel级权限。

AMDRadeonX4000_AMDSIGLContext Double Free权限提升漏洞

在该ADM类的sideband tokens处理工程中还存在double free漏洞。该漏洞允许本地攻击者在受影响的macOS系统中执行任意代码。跟前面的漏洞相似,攻击者必须首先获取目标系统中执行低权限代码的能力。
前面的漏洞存在于AMDRadeonX4000_AMDSIGLContext: discard_StretchTex2Tex函数中,本漏洞存在于AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex函数中。漏洞产生的原因是在该对象中执行操作前没有对该对象进行有效性验证。攻击者可以利用该漏洞来提升权限到kernel级。
这两个漏洞在利用方面是相似的,不同点在于所利用的函数。

漏洞根源分析

图1. 伪随机代码段:函数 AMDRadeonX4000_AMDSIGLContext: discard_StretchTex2Tex (上), 函数AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex (下)

如图1 (上)所示,如果cmdinfo+32等于0x8c00,IOAccelResource v10和v11都是来自于IOAccelShared2,*(shareMem_start_address_187_offset16+8)和*(shareMem_start_address_187_offset16+12)值是索引。该函数会使用 IOAccelResource2::clientRelease() 函数来释放两个加速器资源。但是这两个索引值可以通过映射内存用IOAccelContext2 userclient从用户空间控制。如果用户空间从函数lookupResource映射了相同的索引值,clientRelease就会释放2次相同的资源客户端,此时double free漏洞就发生了。

如图1 (下) 所示,如果v15等于0x8c00,那么accelResource_offset8和accelResource_offset12都来源于IOAccelShared2,共享的内存offset 24和28就说索引。最后,函数会从IOAccelShared2 _rst中释放accelResource_offset12,如果accelResource_offset8->member2不等于10,该函数就会从IOAccelShared2中释放accelResource_offset8。但设置共享内存offset 24和28为相同的值会释放2次accelResource。

在 process_StretchTex2Tex()函数中,完成stretch操作会使用函数 IOAccelResource2::clientRelease()释放2个资源客户端。但这两个来自accelShare2共享内存的accelResource2会释放2个资源客户端。但这两个都是来自于AMDRadeonX4000_AMDSIGLContext类的共享内存的,并使用IOAccelShared2::lookupResource 函数和每个索引。该索引可以通过映射内存和IOAccelContext2 userclient从用户空间进行控制。如果用户空间映射了与lookupResource函数相同的索引,clientRelease就会释放相同的资源客户端2次,这也就说double free漏洞发生的原因。

这两个漏洞是伪代码端都表明指向命令流信息offset 24的共享内存地址。但命令流信息缓存其实是在 IOAccelContext2::processSidebandBuffer函数中设置的。如图2所示,v5指向shareMem offset 16,this->member196指向commandStreamInfo offset 24。

Figure 2. The pseudo code snippet of IOAccelContext2::processSidebandBuffer

图2. IOAccelContext2::processSidebandBuffer伪代码段

图3是IOAccelContext2::clientMemoryForType函数的伪代码段。该函数是由IOConnectMapMemory64 API调用的,该API可以映射用户空间缓冲区和kernel空间。在使用IOConnectMapMemory64函数时,应当设定connect object, memory type和其他参数。在这个例子中,connect object是IOAccelContext2的实例,memory type为0,如图3所示。当把memory type设为0时, clientMemoryForType函数就会创建一个缓冲内存描述符(buffer memory descriptor)并返回开始地址到用户空间。还会设置缓冲内存地址为变量shareMem_start_vm_address_187。该变量其实就是IOAccelContext2::processSidebandBuffer函数中使用的值。
这样,共享的缓冲就可以被控制,两个资源索引也被设置为相同的值,然后就可以触发double free漏洞。

Figure 3. The pseudo code snippet of the IOAccelContext2::clientMemoryForType function

图3. IOAccelContext2::clientMemoryForType 函数伪代码段

下面是应用奔溃日志的backtrace信息,其中如果使用函数discard_StretchTex2Tex,那么只有“AMDRadeonX4000AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex”和函数offset“process_StretchTex2Tex(IOAccelCommandStreamInfo&) + 2893”是不同的。

* thread #1, stop reason = signal SIGSTOPframe #0: 0xffffff7f8d7adc37 IOAcceleratorFamily2`IOAccelResource2::clientRelease(IOAccelShared2*) + 13frame #1: 0xffffff7f8d880dad AMDRadeonX4000`AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex(IOAccelCommandStreamInfo&) + 2893frame #2: 0xffffff7f8d79b5d5 IOAcceleratorFamily2`IOAccelContext2::processSidebandBuffer(IOAccelCommandDescriptor*, bool) + 273frame #3: 0xffffff7f8d8885e4 AMDRadeonX4000`AMDRadeonX4000_AMDSIGLContext::processSidebandBuffer(IOAccelCommandDescriptor*, bool) + 182frame #4: 0xffffff7f8d79bae7 IOAcceleratorFamily2`IOAccelContext2::processDataBuffers(unsigned int) + 85frame #5: 0xffffff7f8d7a2380 IOAcceleratorFamily2`IOAccelGLContext2::processDataBuffers(unsigned int) + 804frame #6: 0xffffff7f8d798c30 IOAcceleratorFamily2`IOAccelContext2::submit_data_buffers(IOAccelContextSubmitDataBuffersIn*, IOAccelContextSubmitDataBuffersOut*, unsigned long long, unsigned long long*) + 1208frame #7: 0xffffff800b027a3c kernel.development`::shim_io_connect_method_structureI_structureO(method=, object=, input=, inputCount=, output=, outputCount=0xffffff8742023968) at IOUserClient.cpp:0 [opt]frame #8: 0xffffff800b025ca0 kernel.development`IOUserClient::externalMethod(this=, selector=, args=0xffffff87420239b8, dispatch=0x0000000000000000, target=0x0000000000000000, reference=) at IOUserClient.cpp:5459 [opt]*frame #9: 0xffffff800b02ebff kernel.development`::is_io_connect_method(connection=0xffffff80b094e000, selector=2, scalar_input=, scalar_inputCnt=, inband_input=, inband_inputCnt=136, ool_input=0, ool_input_size=0, inband_output=””, inband_outputCnt=0xffffff80b0d81e0c, scalar_output=0xffffff8742023ce0, scalar_outputCnt=0xffffff8742023cdc, ool_output=0, ool_output_size=0xffffff80ab5c7574) at IOUserClient.cpp:3994 [opt]frame #10: 0xffffff7f913044c2frame #11: 0xffffff800a9bbd64 kernel.development`_Xio_connect_method(InHeadP=, OutHeadP=0xffffff8742023ce0) at device_server.c:8379 [opt]frame #12: 0xffffff800a88d27d kernel.development`ipc_kobject_server(request=0xffffff80ab5c7400, option=) at ipc_kobject.c:359 [opt]frame #13: 0xffffff800a859465 kernel.development`ipc_kmsg_send(kmsg=0xffffff80ab5c7400, option=3, send_timeout=0) at ipc_kmsg.c:1832 [opt]frame #14: 0xffffff800a878a75 kernel.development`mach_msg_overwrite_trap(args=) at mach_msg.c:549 [opt]frame #15: 0xffffff800a9f63a3 kernel.development`mach_call_munger64(state=0xffffff80af471bc0) at bsd_i386.c:573 [opt]frame #16: 0xffffff800a823486 kernel.development`hndl_mach_scall64 + 22

在该事件中,mac系统经历了kernel panic(内核错误),错误文本已经加入了日志。kernel panic是由于kernel代码中未处理的处理器异常导致的内核检测到的系统错误,比如对无效内存地址的引用、或调用链的漏洞。Panic日志如下:

panic(cpu 6 caller 0xffffff800aa1391c): Kernel trap at 0xffffff7f8d7adc37, type 14=page fault, registers:CR0: 0x0000000080010033, CR2: 0x0000000000000018, CR3: 0x0000000fea85f063, CR4: 0x00000000001626e0RAX: 0x0000000000000000, RBX: 0xffffff800b473e28, RCX: 0x00000000ffffffff, RDX: 0x0000000000000000RSP: 0xffffff8742023610, RBP: 0xffffff8742023610, RSI: 0xffffff80b0f8e470, RDI: 0xffffff80afa29300R8: 0x0000000000000229, R9: 0xffffff800b2c4d00, R10: 0xffffff800b2c2c70, R11:0x0000000000000058R12: 0xffffff87299cb9b4, R13: 0x0000000000000001, R14: 0xffffff80b094e608, R15: 0xffffff80b094e000RFL: 0x0000000000010282, RIP: 0xffffff7f8d7adc37, CS: 0x0000000000000008, SS:0x0000000000000010Fault CR2: 0x0000000000000018, Error code: 0x0000000000000002, Fault CPU: 0x6, PL: 0, VF: 0下面是kernel panic的寄存器的debug信息。$r12寄存器指向共享内存地址offset 16。资源索引为0x42。(lldb) register readGeneral Purpose Registers:rax = 0x0000000000000000rbx = 0xffffff800b473e28 kernel.development`kdebug_enablercx = 0x00000000ffffffffrdx = 0x0000000000000000rdi = 0xffffff80afa29300rsi = 0xffffff80b0f8e470rbp = 0xffffff8742023610rsp = 0xffffff8742023610r8 = 0x0000000000000229r9 = 0xffffff800b2c4d00 kernel.development`zone_array + 8336r10 = 0xffffff800b2c2c70 kernel.development`zone_arrayr11 = 0x0000000000000058r12 = 0xffffff87299cb9b4r13 = 0x0000000000000001r14 = 0xffffff80b094e608r15 = 0xffffff80b094e000rip = 0xffffff7f8d7adc37 IOAcceleratorFamily2`IOAccelResource2::clientRelease(IOAccelShared2*) + 13rflags = 0x0000000000010282cs = 0x0000000000000008fs = 0x00000000ffff0000gs = 0x00000000afa20000(lldb) x/20g $r120xffffff87299cb9b4: 0x00000364001a8c00 0x00000042000000420xffffff87299cb9c4: 0x0000104000000101 0x00555500009000020xffffff87299cb9d4: 0x0004000800040008 0x10480000000100010xffffff87299cb9e4: 0x0055560000900002 0x00020008000200080xffffff87299cb9f4: 0x0000000000010001 0x00000000000000000xffffff87299cba04: 0x0000000400000004 0x00000000000000000xffffff87299cba14: 0x0000000200000002 0x00000364001a8c000xffffff87299cba24: 0x0000004200000042 0x00001048000001010xffffff87299cba34: 0x0055560000900002 0x00020008000200080xffffff87299cba44: 0x1050000000010001 0x0055570000900002

如何应对

攻击者可以利用double free漏洞来攻击未修复的macOS系统,并用提升的权限来入侵机器。苹果提供了一个安全补丁通过改善内存处理来修复内存破坏问题。研究人员建议用户尽快更新系统到最新版本。

本文翻译自:https://blog.trendmicro.com/trendlabs-security-intelligence/cve-2019-8635-double-free-vulnerability-in-apple-macos-lets-attackers-escalate-system-privileges-and-execute-arbitrary-code/​如若转载,请注明原文地址: https://www.4hou.com/info/news/18999.html
点赞 8
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论