CVE-2019-8635:macOS提权及任意代码执行漏洞分析
0x00 前言
我们在macOS中发现了一个双重释放(double free)漏洞(编码为CVE-2019-8635),该漏洞由AMD组件的内存破坏缺陷所导致。如果成功利用该漏洞,攻击者可以实现权限提升,以root权限在系统上执行恶意代码。我们向Apple反馈了漏洞情况,厂商后面也发布了相应补丁。
这个CVE编号实际上覆盖了两个缺陷:discard_StretchTex2Tex方法以及AMDRadeonX400_AMDSIGLContext这个AMD Radeon类中对边带令牌(sindeband token)的处理逻辑。AMDRadeonX400_AMDSIGLContext派生自IOAccelGLContext2类,而后者由IOAccelContext2类扩展而来。这些类用来在macOS主机上渲染图像。
漏洞位于discard_StretchTex2Tex以及AMDSIGLContext::process_StretchTex2Tex函数中,这两个函数是AMDRadeonX4000_AMDSIGLContext类的函数,我们可以使用AMDRadeonX4000_AMDSIGLContext userclient以及selector 2对应的函数IOAccelContext2::submit_data_buffers来访问这个类,使用connect type 1来打开AMDRadeonX4000_AMDGraphicsAccelerator客户端。
0x01 AMDRadeonX4000_AMDSIGLContext discard_StretchTex2Tex双重释放权限提升漏洞
攻击者可以利用该漏洞在用户空间上执行代码。为了利用该漏洞,攻击者首先必须具备在目标macOS系统上执行低权限代码的能力。
该缺陷是因为系统没有对用户提供的数据进行适当的验证,导致读取操作超出已分配数据结构的末尾地址。攻击者可以利用这一点,再与其他漏洞结合起来,将权限提升至内核级别。
0x02 AMDRadeonX4000_AMDSIGLContext双重释放权限提升漏洞
同一个AMD类对边带令牌的处理过程中也存在一个双重释放漏洞。本地攻击者可以利用该漏洞在受影响的macOS上执行任意命令。与上一个漏洞一样,攻击者首先必须具备在目标系统上执行低权限代码的能力,才能进一步利用该漏洞。
虽然前一个漏洞位于AMDRadeonX4000_AMDSIGLContext:discard_StretchTex2Tex函数中,但这个漏洞位于AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex函数中。漏洞成因在于系统在对目标对象执行操作前,没有去验证该对象是否存在。攻击者可以利用该漏洞将权限提升至内核级别。
从本质上讲,这两个漏洞在可能的利用途径方面比较相似,但在于具体利用的函数方面有所区别。
0x03 漏洞分析
图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就会两次释放相同的资源客户端,此时就会出现双重释放漏洞。
如图1(下)所示,如果v15等于0x8c00,那么accelResource_offset8以及accelResource_offset12都会从IOAccelShared2中取值,以共享内存偏移24及28的值作为索引。最终,该函数会从IOAccelShared2 _rst释放accelResource_offset12,如果accelResource_offset8->member2不等于10,该函数也会从IOAccelShared2释放accelResource_offset8。然而将共享内存偏移24及28对应的值设成相同值,就会导致系统两次释放同一个accelResource。
在process_StretchTex2Tex()函数中,完成stretch操作时会使用IOAccelResource2::clientRelease()函数来释放两个资源客户端。然而,这两个accelResource2源自AMDRadeonX4000_AMDSIGLContext类中的accelShare2共享内存,使用对应的索引通过IOAccelShared2::lookupResource函数来获取。攻击者可以从用户空间中,通过IOAccelContext2用户客户端,利用内存映射来控制这些索引值。如果用户空间对lookupResource函数映射相同的索引,那么clientRelease就会两次释放相同的资源客户端,最终出现双重释放漏洞。
根据这两处代码执行流,共享内存地址指向的都是commandStreamInfo + 24。然而,commandStreamInfo缓冲区实际上在IOAccelContext2::processSidebandBuffe函数中设置,如下图所示。在图2中,v5指向的是shareMem + 16,而this->member196指向的是commandStreamInfo + 24。
图2. IOAccelContext2::processSidebandBuffer伪代码片段
IOAccelContext2::clientMemoryForType函数的伪代码片段如图3所示。该函数由已知的IOConnectMapMemory64 API来调用,而后者会将一个用户缓冲区映射到内核空间中。在使用IOConnectMapMemory64函数时,我们需要设置连接对象、内存类型以及其他一些参数。此处连接对象为IOAccelContext2的实例,内存类型为0,如图3所示。当我们将内存类型设置为0时,clientMemoryForType函数会创建一个缓冲区内存描述符,返回用户空间的起始地址。此外,该函数还会将缓冲区内存地址设置为shareMem_start_vm_address_187变量(我们设置的变量名,非原始代码使用的变量名),该变量实际上正是在IOAccelContext2::processSidebandBuffer函数中使用的值。
根据该代码流程,我们可以控制共享缓冲区,以类似的方式设置这两个资源索引,随后触发双重释放漏洞。
图3. IOAccelContext2::clientMemoryForType函数伪代码片段
应用崩溃日志中的回溯信息如下所示,其中如果使用discard_StretchTex2Tex函数,那么只有AMDRadeonX4000AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex以及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 kernelelopment`::shim_io_connect_method_structureI_structureO(method=, object=, input=, inputCount=, output=, outputCount=0xffffff8742023968) at IOUserClient.cpp:0 [opt]frame #8: 0xffffff800b025ca0 kernelelopment`IOUserClient::externalMethod(this=, selector=, args=0xffffff87420239b8, dispatch=0x0000000000000000, target=0x0000000000000000, reference=) at IOUserClient.cpp:5459 [opt]*frame #9: 0xffffff800b02ebff kernelelopment`::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 kernelelopment`_Xio_connect_method(InHeadP=, OutHeadP=0xffffff8742023ce0) at device_server.c:8379 [opt]frame #12: 0xffffff800a88d27d kernelelopment`ipc_kobject_server(request=0xffffff80ab5c7400, option=) at ipc_kobject.c:359 [opt]frame #13: 0xffffff800a859465 kernelelopment`ipc_kmsg_send(kmsg=0xffffff80ab5c7400, option=3, send_timeout=0) at ipc_kmsg.c:1832 [opt]frame #14: 0xffffff800a878a75 kernelelopment`mach_msg_overwrite_trap(args=) at mach_msg.c:549 [opt]frame #15: 0xffffff800a9f63a3 kernelelopment`mach_call_munger64(state=0xffffff80af471bc0) at bsd_i386.c:573 [opt]frame #16: 0xffffff800a823486 kernelelopment`hndl_mach_scall64 + 22
当Mac系统出现内核错误(kernel panic)时,panic文本会被添加到日志中。kernel panic指的是内核检测到的系统错误,根源在于内核代码中没有对处理器异常进行处理(比如引用了无效的内存地址,或者调用链中出现错误,可以对比用户空间代码检测到的错误)。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的信息如下所示。$r12寄存器指向的是共享内存地址+ 16,资源索引值也为0x42。
(lldb) register readGeneral Purpose Registers:rax = 0x0000000000000000rbx = 0xffffff800b473e28 kernelelopment`kdebug_enablercx = 0x00000000ffffffffrdx = 0x0000000000000000rdi = 0xffffff80afa29300rsi = 0xffffff80b0f8e470rbp = 0xffffff8742023610rsp = 0xffffff8742023610r8 = 0x0000000000000229r9 = 0xffffff800b2c4d00 kernelelopment`zone_array + 8336r10 = 0xffffff800b2c2c70 kernelelopment`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
0x04 缓解措施
攻击者可以使用双重释放漏洞来攻击未打补丁的macOS系统,成功在目标主机上获取较高权限。Apple已推出安全补丁,改进内存处理机制来修复内存破坏问题。macOS Mojave 10.14.4已经可以使用最新补丁,大家应当尽快更新系统。此外,大家也可以安装类似Trend Micro Antivirus for Mac以及Trend Micro Protection Suites之类的解决方案来检测并阻止使用利用各种缺陷的攻击行为。
登录安全客 - 有思想的安全新媒体http://www.anquanke/,或加入交流群814450983、下载安全客APP来获取更多最新资讯吧~
第五届86358贾家庄短片周面向全球征集短片
中新网太原4月25日电 (记者 范丽芳)由贾樟柯艺术中心主办的第五届86358贾家庄短片周“华语短片竞赛”单元正式启动征片,即日起,面向全球范围内的华语电影短片作品及华人电影工作者开放报名。
86358贾家庄短片周是一个专注于华语电影短片展示、交流、推广的专业平台。截至目前已成功举办过四届,逐渐成为青年电影人与华语电影短片集中展示的重要平台之一,致力于为青年影人与中国乡村的联结、与全球范围内电影工作者搭建沟通桥梁,为电影产业助推有创造力与潜力的人才。
贾樟柯艺术中心策展人徐志鹏表示,在86358贾家庄短片周,青年电影人不仅能与来自中国最基层的观众分享自己的多元创造与独特叙事,也在见证、参与和沟通中不断突破艺术的想象力,“贾家庄短片周作为品牌文化活动,不仅促进文化资源回流基层,也推动了电影艺术教育与文旅深度融合发展”。
往年的86358贾家庄短片周,除“华语短片竞赛”单元外,还设置相关的交流展映板块,为参加活动的影人、观众提供多维度的交流空间。
据悉,第五届86358贾家庄短片周将会在节目内容与活动形式上进行优化升级,组织丰富多彩的学术活动,邀请业界资深电影工作者开展主题论坛、对话、电影公开课等活动。(完)
来源:中国新闻网
五项华语短片荣誉揭晓!第五届贾家庄短片周精彩闭幕
9月20日,第五届86358贾家庄短片周荣誉典礼在贾家庄工业创意园贾樟柯艺术中心广场举行。闭幕红毯拉开了本次荣誉典礼的序幕,入围本届短片周主竞赛、特别放映和本土力量三大单元主创陆续踏上红毯。随后,梅峰、陈洁、李丹枫、班宇、黄奕、张力尹、阚昕、张薇、徐志鹏、辛奇等嘉宾踏上红毯隆重出场。
作为86358贾家庄短片周的重要节目单元,今年主竞赛单元共收到报名作品1603部,最终确定16部作品入选。经过评审团细心与认真的评选以及激烈讨论,最终评选出了本届贾家庄短片周的五项华语短片荣誉。《手风琴》获得最佳影片荣誉,《炮仗的故事》和《布谷鸟》获得评审团荣誉。《森林王子》获得了最佳导演荣誉,《鲸》获得了最佳编剧荣誉,《春江花月夜》摘得最佳摄影荣誉。
荣誉典礼上,梅峰代表评审团对本届贾家庄短片周的邀请表示了感谢。他也认为短片周作为提供给青年影人与观众见面的重要平台,让他们的作品得以被行业里的人所认可,起到的作用越来越重要。他希望青年影人能从这里出发,成长为中国电影的中坚力量。
另外,从首届短片周举办伊始,电影人之间展开的对话与交流便是主要板块之一。今年,短片周联合后浪电影特邀周全、邢健、闫冰、刘泽在20日上午围绕“作的个性与理性——我的第一部”的主题展开了学术交流。其间,短片周还举办了“点映秀-影人派对”和“篝火派对”两场影人活动,为青年电影创作者提供了一个活泼的交流空间。
值得一提的是,广东的作品《有风的日子,有云》也在本届贾家庄短片周进行了展映。短片由李康生执导,讲述了一对父女之间平凡但温暖的相处故事,穿梭市井,分开相聚,导演用镜头表达出了生活的真谛——最深的爱就在日常。
【背景介绍】
86358贾家庄短片周由贾樟柯艺术中心主办。
“86358”的含义:“86”代表中国大陆的国际区号;“0358”是汾阳当地的电话区号。贾樟柯将电影短片交流周命名为“86358”意为突破地域限制,将汾阳与世界电影艺术连接起来。
【记者】刘长欣 实习生 南柯鑫
【作者】 刘长欣
【来源】 南方报业传媒集团南方+客户端
来源:南方+ - 创造更多价值