CVE-2019-8635:macOS double free

在macOS存在一個(gè)double free漏洞,這個(gè)漏洞由AMD組件的內(nèi)存損壞所引起。如果成功被利用,攻擊者可以完成權(quán)限提升并且可以再root權(quán)限下執(zhí)行惡意代碼。

漏洞簡單介紹

其實(shí)這個(gè)cve包含2個(gè)相似的漏洞:

  1. discard_StretchTex2Tex方法。
  2. 還有一個(gè)存在一個(gè)類中AMD Radeon class(AMDRadeonX400_AMDSIGLContext)對(duì)sideband tokens的處理過程。它是IOAccelGLContext2的派生類,并從IOAccelGLContext2擴(kuò)展。 這些類用于在macOS機(jī)器上渲染圖形。具體是在
    AMDRadeonX4000_AMDSIGLContext類的AMDSIGLContext::process_StretchTex2Tex函數(shù)中。并且在打開AMDRadeonX4000_AMDGraphicsAccelerator 客戶端的連接類型為1的情況下,這個(gè)類可以被AMDRadeonX4000_AMDSIGLContext的selector 2用戶態(tài)函數(shù)IOAccelContext2::submit_data_buffers訪問。

漏洞成因

下面簡要介紹下這兩個(gè)漏洞的成因:

  1. 第一個(gè)漏洞:AMDRadeonX4000_AMDSIGLContext discard_StretchTex2Tex double free漏洞
    這個(gè)漏洞可以在用戶態(tài)觸發(fā),但是必須最低要求是能夠在目標(biāo)macOS 系統(tǒng)獲取執(zhí)行低權(quán)限的代碼。因?yàn)闆]有對(duì)用戶提供的數(shù)據(jù)合法驗(yàn)證,能夠讀取已分配的數(shù)據(jù)結(jié)構(gòu),攻擊者利用此漏洞再結(jié)合其他的漏洞可以在內(nèi)核態(tài)提升權(quán)限。
  2. 第二個(gè)漏洞:AMDRadeonX4000_AMDSIGLContext Double Free漏洞
    在同一個(gè)AMD組件類中,它是在對(duì)sideband token的處理過程中,也存在類似的一個(gè)double free漏洞。和上一個(gè)漏洞一樣,是一個(gè)本地提權(quán)漏洞,必須在目標(biāo)系統(tǒng)有執(zhí)行低權(quán)限代碼的能力,也就是個(gè)普通用戶。具體是在函數(shù)AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex中,在對(duì)對(duì)象操作前,沒有對(duì)其進(jìn)行有效的驗(yàn)證,攻擊者可以利用此弱點(diǎn),從內(nèi)核態(tài)提升權(quán)限。
    本質(zhì)上講,就利用特點(diǎn)來看,兩個(gè)漏洞可能是相似的,都是對(duì)對(duì)象在釋放之前,沒有對(duì)對(duì)象的數(shù)據(jù)來源和數(shù)據(jù)的值進(jìn)行驗(yàn)證,可以在用戶態(tài)直接映射內(nèi)存就行修改索引,達(dá)到釋放相同的對(duì)象,并且釋放兩次,引發(fā)漏洞。
    但具體調(diào)用的函數(shù)上有一些區(qū)別,我們看具體分析:


    fig-1-pseudo-code-snippet-stretchtex2tex-function.png

    上圖AMDRadeonX4000_AMDSIGLContext: discard_StretchTex2Tex函數(shù)的偽代碼中我們看v10和v11是如何獲取的,如果 (cmdinfo+32)等于0x8c00, 這個(gè)IOAccelResource v10和v11從IOAccelShared2(this+172)獲取到,索引分別為*(shareMem_start_address_187_offset16+8) 和 *(shareMem_start_address_187_offset16+12),這個(gè)函數(shù)也會(huì)用IOAccelResource2::clientRelease()釋放這兩個(gè)加速資源。如果用戶態(tài)映射相同的索引,lookupResource函數(shù)相當(dāng)于從這兩個(gè)索引中取值,客戶端也會(huì)釋放相同的對(duì)象兩次,這就是漏洞所在、核心在于我們讓(shareMem_start_address_187_offset16+8)和(shareMem_start_address_187_offset16+12)的值相同,而shareMem_start_address_187_offset16的區(qū)域可以被用戶態(tài)控制和映射,通過修改而達(dá)到目的。
    第二個(gè)漏洞:


    fig-1-pseudo-code-snippet-process-stretchtex2tex-function.png

    如上圖函數(shù)AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex的偽代碼片段。結(jié)構(gòu)和上一個(gè)漏洞很類似,如果v15==0x8c00, accelResource_offset8和accelResource_offset12會(huì)從IOAccelShared2獲取到,索引為共享內(nèi)存+24和共享內(nèi)存+28的值。最后,這個(gè)函數(shù)會(huì)從 IOAccelShared2 _rst釋放accelResource_offset12, 如果 accelResource_offset8->member2!=10, 這個(gè)函數(shù)也會(huì)從IOAccelShared2釋放accelResource_offset8,這樣的話,如果我們?cè)O(shè)置共享內(nèi)存偏移24和28的位置為相同的值,將會(huì)釋放相同得對(duì)象accelResource兩次,引發(fā)了漏洞。
    在AMDRadeonX4000_AMDSIGLContext類里的process_StretchTex2Tex函數(shù)中,IOAccelResource2::clientRelease()將會(huì)釋放這兩個(gè)對(duì)象,而這兩個(gè)對(duì)象accelResource2均來自accelShare2共享內(nèi)存,對(duì)象通過IOAccelShared2::lookupResource函數(shù)以各自的索引值為參數(shù)來得到,這兩個(gè)索引值可以被用戶態(tài)通過 IOAccelContext2設(shè)置共享內(nèi)存來控制。 如果用戶態(tài)映射了兩個(gè)相同的索引值,就會(huì)釋放兩次相同的對(duì)象。

用戶態(tài)映射內(nèi)存

接下來看IOAccelContext2::processSidebandBuffer:

fig-2-pseudo-code-snippet-ioaccelcontext2-processsideandbuffer.png

這兩個(gè)漏洞的偽代碼片段顯示了共享內(nèi)存指向了command stream info +24,這個(gè)command stream info buffer在IOAccelContext2::processSidebandBuffer設(shè)置,在圖中,我們看到 v5=共享內(nèi)存+16 ,并且v5賦值給了this->member196, this->member196也指向了commandStreamInfo+24。

fig-3-pseudo-code-snippet-ioaccelcontext2-clientmemoryfortype-function.png

上圖是 IOAccelContext2::clientMemoryForType偽代碼片段,被API IOConnectMapMemory64所調(diào)用。IOConnectMapMemory64函數(shù)可以映射用戶態(tài)到內(nèi)核態(tài)。當(dāng)調(diào)用這個(gè)函數(shù)時(shí),它的參數(shù)應(yīng)該有連接對(duì)象,內(nèi)存類型,和其他的參數(shù)。這里,我們把連接對(duì)象設(shè)置為IOAccelContext2的實(shí)例,內(nèi)存類型為0,當(dāng)設(shè)置了內(nèi)存類型為0的時(shí)候,clientMemoryForType函數(shù)將會(huì)創(chuàng)建一個(gè)buffer,它的起始地址是這個(gè)變量“shareMem_start_vm_address_187”,也就是在IOAccelContext2::processSidebandBuffer命名的。
從這里開始,共享內(nèi)存可以被控制,兩個(gè)resource索引也可以被設(shè)置相同的,可以觸發(fā)這個(gè)bug。

崩潰日志

接下來我們看一下應(yīng)用crash的backtrace信息。“AMDRadeonX4000`AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex”和“process_StretchTex2Tex(IOAccelCommandStreamInfo&) + 2893”的偏移會(huì)有所不同,如果discard_StretchTex2Tex被用來觸發(fā)漏洞,也同樣可以注意到。
當(dāng)內(nèi)核檢測到系統(tǒng)錯(cuò)誤時(shí),這個(gè)錯(cuò)誤會(huì)在內(nèi)核代碼段檢測到,就會(huì)拋出沒有解決的處理器異常,像無效內(nèi)存地址引用,或者在調(diào)用鏈中的bug等等,mac系統(tǒng)就會(huì)產(chǎn)生kernel panic,加入log。我們可以看到所出現(xiàn)的panic log.

* thread #1, stop reason = signal SIGSTOP
frame #0: 0xffffff7f8d7adc37 IOAcceleratorFamily2`IOAccelResource2::clientRelease(IOAccelShared2*) + 13
frame #1: 0xffffff7f8d880dad AMDRadeonX4000`AMDRadeonX4000_AMDSIGLContext::process_StretchTex2Tex(IOAccelCommandStreamInfo&) + 2893
frame #2: 0xffffff7f8d79b5d5 IOAcceleratorFamily2`IOAccelContext2::processSidebandBuffer(IOAccelCommandDescriptor*, bool) + 273
frame #3: 0xffffff7f8d8885e4 AMDRadeonX4000`AMDRadeonX4000_AMDSIGLContext::processSidebandBuffer(IOAccelCommandDescriptor*, bool) + 182
frame #4: 0xffffff7f8d79bae7 IOAcceleratorFamily2`IOAccelContext2::processDataBuffers(unsigned int) + 85
frame #5: 0xffffff7f8d7a2380 IOAcceleratorFamily2`IOAccelGLContext2::processDataBuffers(unsigned int) + 804
frame #6: 0xffffff7f8d798c30 IOAcceleratorFamily2`IOAccelContext2::submit_data_buffers(IOAccelContextSubmitDataBuffersIn*, IOAccelContextSubmitDataBuffersOut*, unsigned long long, unsigned long long*) + 1208
frame #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: 0xffffff7f913044c2
frame #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
panic(cpu 6 caller 0xffffff800aa1391c): Kernel trap at 0xffffff7f8d7adc37, type 14=page fault, registers:
CR0: 0x0000000080010033, CR2: 0x0000000000000018, CR3: 0x0000000fea85f063, CR4: 0x00000000001626e0
RAX: 0x0000000000000000, RBX: 0xffffff800b473e28, RCX: 0x00000000ffffffff, RDX: 0x0000000000000000
RSP: 0xffffff8742023610, RBP: 0xffffff8742023610, RSI: 0xffffff80b0f8e470, RDI: 0xffffff80afa29300
R8: 0x0000000000000229, R9: 0xffffff800b2c4d00, R10: 0xffffff800b2c2c70, R11: 0x0000000000000058
R12: 0xffffff87299cb9b4, R13: 0x0000000000000001, R14: 0xffffff80b094e608, R15: 0xffffff80b094e000
RFL: 0x0000000000010282, RIP: 0xffffff7f8d7adc37, CS: 0x0000000000000008, SS: 0x0000000000000010
Fault CR2: 0x0000000000000018, Error code: 0x0000000000000002, Fault CPU: 0x6, PL: 0, VF: 0

在log中也會(huì)看到寄存器信息,$r12指向共享內(nèi)存+16的位置,為0xffffff87299cb9b4,這兩個(gè)resource索引都為0x42.

(lldb) register read
General Purpose Registers:
rax = 0x0000000000000000
rbx = 0xffffff800b473e28 kernel.development`kdebug_enable
rcx = 0x00000000ffffffff
rdx = 0x0000000000000000
rdi = 0xffffff80afa29300
rsi = 0xffffff80b0f8e470
rbp = 0xffffff8742023610
rsp = 0xffffff8742023610
r8 = 0x0000000000000229
r9 = 0xffffff800b2c4d00 kernel.development`zone_array + 8336
r10 = 0xffffff800b2c2c70 kernel.development`zone_array
r11 = 0x0000000000000058
r12 = 0xffffff87299cb9b4
r13 = 0x0000000000000001
r14 = 0xffffff80b094e608
r15 = 0xffffff80b094e000
rip = 0xffffff7f8d7adc37 IOAcceleratorFamily2`IOAccelResource2::clientRelease(IOAccelShared2*) + 13
rflags = 0x0000000000010282
cs = 0x0000000000000008
fs = 0x00000000ffff0000
gs = 0x00000000afa20000

(lldb) x/20g $r12
0xffffff87299cb9b4: 0x00000364001a8c00 0x0000004200000042 //here
0xffffff87299cb9c4: 0x0000104000000101 0x0055550000900002
0xffffff87299cb9d4: 0x0004000800040008 0x1048000000010001
0xffffff87299cb9e4: 0x0055560000900002 0x0002000800020008
0xffffff87299cb9f4: 0x0000000000010001 0x0000000000000000
0xffffff87299cba04: 0x0000000400000004 0x0000000000000000
0xffffff87299cba14: 0x0000000200000002 0x00000364001a8c00
0xffffff87299cba24: 0x0000004200000042 0x0000104800000101
0xffffff87299cba34: 0x0055560000900002 0x0002000800020008
0xffffff87299cba44: 0x1050000000010001 0x0055570000900002

蘋果在 macOS Mojave 10.14.4已更新補(bǔ)丁
引用:

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/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Lua 5.1 參考手冊(cè) by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 14,259評(píng)論 0 38
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,675評(píng)論 1 32
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,986評(píng)論 0 9
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,599評(píng)論 0 6
  • 必備的理論基礎(chǔ) 1.操作系統(tǒng)作用: 隱藏丑陋復(fù)雜的硬件接口,提供良好的抽象接口。 管理調(diào)度進(jìn)程,并將多個(gè)進(jìn)程對(duì)硬件...
    drfung閱讀 3,769評(píng)論 0 5

友情鏈接更多精彩內(nèi)容