Secure File upload best practices

Secure file uploads are critical to applications that support this feature.

It is important that the files adhere to the best practices of secure file upload listed below:

  1. DO NOT RELY on client side validation. Whatever you do on the client side ALL the following checks MUST be implemented on the server side.
  2. Check for the SIZE OF THE FILE UPLOADED – absolutely critical must do. If you need very large files to be uploaded go back to the white board and see what alternatives can be explored. Generally any file upload should not be more than 4 MB.
  3. Ensure that only a set of known good file extensions/types are allowed to be uploaded– USE A WHITELIST of allowed extensions. DO NOT use a list of bad extensions to be avoided – NO BLACKLIST`ing.
  4. Generate the file names; DO NOT USE/AVOID files names that are provided by the end user.
  5. Upload the file to a location decided by the application WITHOUT any end user influence. DO NOT let the user have a say in where the file is uploaded.
  6. Upload in a location that is a NON SYSTEM drive.
  7. AVOID uploading the file to the WEB ROOT.
  8. ALWAYS DO a Virus scan on the uploaded files.
  9. Run a MIME check on the allowed MIME types. Note this can be manipulated by any user and by no means should be the only mechanism to secure a file upload. <<Adding some more to the original list>>
  10. Check “Magic Numbers” rather than just checking the file extensions. Check what a Magic Number is here.
  11. Pay attention to the decompression of compressed files.
  12. Ensure that the file upload is Audited.
  13. Refrain from overwriting of a uploaded file.
  14. Do not allow execute permissions on folder where the file is uploaded.

The validateFileToUpload class implements the three checks below using ASP.Net:

  • CHECK #1   Check for the file size
  • CHECK #2   Check for the file extension and map it to a white list of allowed extensions
  • CHECK #3   MIME Type Validation
public void validateFileToUpload(FileUpload objFile)
{
int MAX_FILE_SIZE = (4 * 1024 * 1024); //5 MB file size limit
//————————————————————
//CHECK #1
//You can set the httpRunTime maxRequestLength to the required
//file size in the web.config file too
//————————————————————
int fileSize = objFile.PostedFile.ContentLength;
if (fileSize > MAX_FILE_SIZE)
{
returnMessage = “File size exceeds the safe file size limit.  Reduce the file size.”;
return returnMessage;
}
//—————————————
//CHECK #2
//Check with a white list of extension
//—————————————
string chosenFileExtension = System.IO.Path.GetExtension(objFile.FileName);
string[] allowedExtensions = { “.doc”, “.xls”, “.ppt”, “.pptx”, “.txt” };
if (!allowedExtensions.Contains(chosenFileExtension))
{
returnMessage = “Upload Failed: Files with ” + chosenFileExtension + ” extensions are not allowed.”;
return returnMessage;
}
//—————————————
//CHECK #3
//Check with a white list of MIME types
//—————————————
string[] allowedMimeTypes = { “text/plain”, “text/xml” };
string chosenFileMiMeType = objFile.PostedFile.ContentType;
if (!allowedMimeTypes.Contains(chosenFileMiMeType))
{
returnMessage = “Upload Failed: Files with ” + chosenFileMiMeType + ” MIME types are not allowed.”;
return returnMessage;
}
There are some additional checks that needs to be kept in mind in addition to the 9 checks listed above like double extension files, filename checks for files coming from different operating systems (#4 kind of handles this though).Learnt to keep these checks in mind in a VERY HARD way today :’((
Advertisements