Neptune 1.0 Beta 3 Documentation: File Uploads

Neptune Information

Download from RIA Forge

File Uploads

Neptune aims to make web development as easy as possible and remove as many decision points as possible. How to handle file uploads, however, is a subject that requires a decision with understanding of the trade-offs.

First, we would suggest that you read Tips for Secure File Uploads with ColdFusion by Pete Frietag for an overview of security concerns with file uploads.

A few notes from his entry:

Don't rely on cffile accept attribute
All file fields should have an "extensions" attribute. This will cause Neptune to verify the file extension on upload (on the server). This field may be required in a future release.
Validate that the File Extension matches File Format
Neptune does not have built-in support for this.
Always upload to a temp directory outside of the Web Root
Neptune does this for all uploads using its built-in tags and components. See "Script Injection Attack: Smoking Gun?" by Mark Kruger of CF Webtools for more details.
Keep uploaded files outside the web root
See below.
Remove execute permissions from upload directories
This should be done by default in Neptune, but it is highly recommended that you verify this setting. This setting is essential for good security.
Upload to a static content server
Neptune does not currently have built-in support for this.
Don't trust on the client supplied file name
Neptune fixes file names to be valid.
ColdFusion Administrator Settings
This is outside the scope of Neptune, but still a good idea.

Storage Location

Once the file is uploaded, the location to which it is stored is an important decision. The easiest thing to do is leave the default as-is.

Neptune secures uploads within the upload directory in the following ways (more to be added as needed):

If you want extra security beyond this, move the upload path outside of the web root. To do so, you need only change the "UploadPath" configuration to a folder outside the web root. This will require "indirect retrieval" (see below) which is the default behavious in Neptune.

Direct or Indirect Retrieval

The default method to serve up an uploaded file in Neptune is what we call "indirect retrieval" - the URL field for the file is a .cfm file that returns the requested file from another location. This ensures that the file cannot be executed. It also allows you to write custom code in handling that file retrieval (for logging or additional security, for example). It is also required in order to store files outside of the web root.

Note that indirect retrieval offers only mild security improvements if the files remain stored within the web root as the storage location can be guessed (easily if the hacker knows your site is a Neptune site). The benefits of potential extra functionality still remain, however.

This method does have one drawback. Every uploaded file (image or otherwise) takes up a ColdFusion thread every time it is served. This thread will last until the entire file is retrieved. For very large files, this can potentially tie up considerable resources.

If you would rather serve up the file directly, just change the "UploadURL" configation to the URL for the "UploadPath" folder. This will reduce your power and flexibility and potentially reduce security, but it will also free up server resources. This is a significant and difficult decision.

Extra Functioanlity for Indirect Retrieval

By default, Neptune serves up all uploaded files through "/file.cfm". The processing for which is done in "/file.cfm", which calls the "loadData_File" on the base Page Controller.

To add functionality to your file downloads (for logging or security, for example) you can either add a "loadData_File" method to your site-specific Page Controller (_config/PageController.cfc) or directly in file.cfc.