TL;DR Three vulnerabilities in the second most starred Javascript repository on Github which two of them are remote code execution and the third makes it possible to permanently delete any uploaded file made by jQuery-File-Upload. The latter is intended behaviour however our research suggests that user privacy is not respected as content can easily be viewed by external actors.
Detectify Crowdsource has been working with three vulnerabilities in jQuery-File-Upload submitted by our security researcher community, and now we’ve implemented these security tests in the Detectify tool. Our research found out that jQuery-File-Upload is included in several different platforms and not properly configured. The following Proof of Concept is of CVE-2018-9206: Unauthenticated arbitrary file upload vulnerability and the remote code execution due to ImageTragick. Explanations of all three vulnerabilities follow.
CVE-2018-9206: Unauthenticated arbitrary file upload vulnerability
This first vulnerability has been known for a few years, since 2015. But in 2018 a CVE was finally assigned and the vulnerability was brought to public attention as Thousands of Applications were vulnerable to RCE via jQuery File Upload. The open-source file upload widget, jQuery-File-Upload, is the second most starred Javascript repository on Github, after jQuery JavaScript Library itself. The core of CVE-2018-9206 is a vulnerability within the server configuration and PHP components of the technology and not Javascript. While a RCE in Javascript would be surprising, it’s not as surprising in PHP.
The vulnerability is due to the code relying on Apache’s .htaccess support. This is a way to restrict files being uploaded or executed on an Apache web server.
# The following directives prevent the execution of script files # in the context of the website. # They also force the content-type application/octet-stream and # force browsers to display a download dialog for non-image files. SetHandler default-handler ForceType application/octet-stream Header set Content-Disposition attachment # The following unsets the forced type and Content-Disposition headers # for known image files:ForceType none Header unset Content-Disposition <...>
The above .htaccess is included in jQuery-File-Upload and prior to version 9.22.0 it was the only protection against arbitrary file upload. The .htaccess files makes the browser download files with MIME application/octet-stream (for example PHP-files) instead of executing them in the context of the web server. This means that jQuery-File-Upload allowed any files to be uploaded, but not executed on the server, as they trusted the web server to make the check. After the patch, later versions have been changed so that the code checks the type of file being uploaded.
However, the problem is that Apache stopped to enable .htaccess support by default in version 2.3.9, making the only protection useless if not explicitly enabled. If another web server is in use (for example Nginx), there is no protection at all as .htaccess only works in Apache web server.
An attacker can simply upload any file and it will be handled by the web server. This leads to remote code execution as an attacker can upload PHP-files and execute them.
Remote code execution due to ImageTragick
The second jQuery-File-Upload vulnerability was also known within the hacking community for some years and was not publicly known until the technology started to get attention due to CVE-2018-9206, as more people started looking into jQuery-File-Upload’s code base. As the code makes use of ImageMagic, it may be possible to obtain remote code execution with GhostScript (CVE-2016-3714 AKA ImageTragick). This is demonstrated in the video.
An attacker can upload the following GhostScript saved with the whitelisted extensions; PNG, GIF or JPG.
%!PS userdict /setpagedevice undef save legal { null restore } stopped { pop } if { legal } stopped { pop } if restore mark /OutputFile (%pipe%ping example.com) currentdevice putdeviceprops
The server will then execute the command ping example.com. Note that GhostScript will look a little bit different depending on the operating system and the ping command works in most environments, making our automatic tests very accurate to detect this vulnerability.
Note that this is a vulnerability in a library that jQuery-File-Upload uses, and not in the code itself.
An intentional but vulnerable feature
The third and last vulnerability found was an insecure direct object reference or IDOR vulnerability. One website owner responded that the issue was actually “intentional behaviour” but many users of jQuery-File-Upload may not know of the behaviour, making it risky to use.
Here’s why: The endpoint where files are uploaded to can be requested with GET and the server will respond with a JSON object containing all the previous uploaded files. This exposes the file names, upload path, thumbnail and whether it is possible to delete the file permanently from the server. The response will look something like:
{"files":[{"name":image.jpg","size":68549,"url":"http://example.com/image.jpg","thumbnailUrl":"http://example.com/thumbnail/image.jpg","deleteUrl":"http://example.com/server/php?file=image.jpg","deleteType":"DELETE"}
With this, a user can now view all the previous uploaded files by requesting the value in the url key. It is also possible to delete any file by sending the DELETE HTTP-method to the value in the deleteUrl key. This can easily be done with cURL:
curl -X DELETE http://example.com/server/php?file=image.jpg
When looking for websites using jQuery-File-Upload I came across a few cases where this “intentional behaviour” probably shouldn’t be “intentional”. One case was a dating site where users naturally uploaded images of themselves. By sending this request, I was able to view the whole user base of uploaded photos. In another case I was able to access all uploaded photos on a website which requires users to verify their identity by uploading a photo of their government ID or passport. I have reached out to Sebastian Tschan (the maintainer of jQuery-File-Upload) and all these websites which I found the vulnerability on.
Remediation
The first two issues have been fixed in the latest version of jQuery-file-upload, and we recommend to update the code to latest version as soon as possible. To remediate the the last vulnerability, you would restrict access to the endpoint where files are uploaded (usually server/php/index.php) if it is important that all the uploaded files should not be publicly viewable.
Do you use jQuery-File-Upload on your web applications and you’re not sure if you have secured the code? You can check the code with Detectify now. Just log in here. Not a customer yet? No problem! You can sign up for your account and free trial today.