Skip to content
This repository has been archived by the owner on May 25, 2023. It is now read-only.

Security

blueimp edited this page Apr 16, 2012 · 16 revisions

If you allow users to upload files to your webserver, you have a potential security hole.
To prevent an attacker from executing arbitrary files in the context of your web application, some security considerations have to be kept in mind.

For an in-depth understanding of the potential security risks and possible mitigations, the OWASP project has a good overview:

Unrestricted File Upload (OWASP)

Following are some security considerations specific to the jQuery File Upload plugin:

Client-side

File upload restrictions on client-side are only means to improve the usability of your application. The client-side is under the control of any potential attacker, therefore you cannot trust any client-side input and absolutely have to implement validations and restrictions on server-side.

You also need to keep in mind files that can be downloaded and executed on client-side in the context of another user to exploit Cross-site scripting (XSS) vulnerabilities or spread malware. As this can only be controlled on server-side, it's part of the next section.

Server-side

To prevent arbitrary files (e.g. JavaScript files) from being executed on client-side in the context of the web application, the provided server-side implementations serve non-image files with attachement headers, to force a download dialog:

Content-Disposition:attachment; filename=script.js;

Image files are served with their proper mime type headers (e.g. "image/png") and an additional header to prevent Internet Explorer 8 and higher from sniffing the mime type and executing JavaScript masked as image files:

X-Content-Type-Options: nosniff

Please note that all provided implementations allow cross-site file uploads. If you don't need that functionality, you should remove the code parts that set the "Access-Control-Allow" headers.

Please also note that the provided implementations allow anyone to upload files. The uploaded files are also accessible for anyone to download. It's up to you to incorporate the server-side file upload implementation into your user-authentication system.

Google App Engine (Python, Go)

On Google App Engine, uploaded files cannot be saved directly on the file system and are instead stored in the Blobstore. This prevents executing uploaded files (e.g. Python scripts) on server-side in the context of your web application.
The provided Python and Go implementations also restrict uploaded files by default to image files (GIF, JPEG, PNG).

Node.js

The Node.js implementation serves uploaded files with a static file server, which - as the name implies - only serves static files and doesn't interpret any uploaded scripts (as Apache would do e.g. with PHP scripts with the PHP module installed).
The Node.js implementation also restricts uploaded files by default to image files (GIF, JPEG, PNG).

PHP

The PHP implementation allows to upload all file types by default. Since you probably don't need that functionality, it is recommended to adjust the accept_file_types option. If you're running PHP >= 5.3, you can override this option in the upload handler instantiation, else you have to edit the appropriate line in the upload class itself:

$upload_handler = new UploadHandler(array(
    'accept_file_types' => '/\.(gif|jpe?g|png)$/i'
));

The PHP implementation stores uploaded files in the pre-defined directory "files". This directory contains a file .htaccess that is absolutely required as it contains directives for Apache to enforce security restrictions:

ForceType application/octet-stream
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
  ForceType none
</FilesMatch>

The ForceType directive "application/octet-stream" enforces Apache to serve all files with an attachment header to force a download dialog. More importantly, it prevents Apache to run any of the uploaded files through an interpreter like PHP, even if the file extension is ".php".

Clone this wiki locally