PHP Upload file enhance security

2019-01-13 21:54发布

问题:

Hey.. my question is how to prevent someone upload a virus or some malicious code with the extension you pretend for example i have a pdf file uploader, anyone can upload a binary with pdf camouflage there are lots of programs to do that.

回答1:

There are a number of secuirty concerns that arise with uploading files. The first problem is that the file might not be the file you want, in this case a pdf. The variable $_FILES['file_name']['type'] is controlled by the attacker can never be trusted. This value is commonly modified using exploit code or using tamperdata.

1)The first step in your secuirty system is to make sure the file has a .pdf extension:

if("pdf"!=substr($fileName, strrpos($fileName, '.') + 1)){
   die("Invalid File Type");
}

2)Next you should check what file type it is using the php filetype() function.

3)A serious problem is that these PDF files can exploit vulnerabilities such as buffer overflows commonly found in software made by Adobe. These PDF's are used to spread viruses in a Drive By Download attack.

The best solution is to install the web application firewall Mod_Security. This will stop attacks like sql injection and xss from hitting your web application. Mod_Secuirty can be configured to scan all upload files for viruses using modsec-clamscan .



回答2:

we use a combination of fileinfo + file extension check. While browsers usually sends the mime type you should never trust on it since this can be hijacked.

In our case we don't run any file in our server. So what we do is to have a extension while list like (for example): pdf jpg png etc.. and a list of blacklisted mime extensions. This way we avoid the risk of having a file with an extension that doesn't matches the mime type.

once the file is saved in the server we always force the mime type to application/octet-stream so files are always downloaded.

something like this:

<?php

$allowed_types = array(
/* images extensions */
'jpeg', 'bmp', 'png', 'gif', 'tiff', 'jpg',
/* audio extensions */
'mp3', 'wav', 'midi', 'aac', 'ogg', 'wma', 'm4a', 'mid', 'orb', 'aif',
/* movie extensions */                              
'mov', 'flv', 'mpeg', 'mpg', 'mp4', 'avi', 'wmv', 'qt',
/* document extensions */                               
'txt', 'pdf', 'ppt', 'pps', 'xls', 'doc', 'xlsx', 'pptx', 'ppsx', 'docx'
                        );


$mime_type_black_list= array(
# HTML may contain cookie-stealing JavaScript and web bugs
'text/html', 'text/javascript', 'text/x-javascript',  'application/x-shellscript',
# PHP scripts may execute arbitrary code on the server
'application/x-php', 'text/x-php', 'text/x-php',
# Other types that may be interpreted by some servers
'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh',
'text/x-c++', 'text/x-c',
# Windows metafile, client-side vulnerability on some systems
# 'application/x-msmetafile',
# A ZIP file may be a valid Java archive containing an applet which exploits the
# same-origin policy to steal cookies      
# 'application/zip',
                        );


$tmp_file_extension = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));

if(!strlen($tmp_file_extension) || (!$allow_all_types &&
  !in_array($tmp_file_extension,$allowed_types))) {
    return false;
}

$finfo = new finfo(FILEINFO_MIME, MIME_MAGIC_PATH);

if ($finfo) {
    $mime = $finfo->file($file_name_tmp);
}
else {
    $mime = $file_type;
}

$mime = explode(" ", $mime);
$mime = $mime[0];

if (substr($mime, -1, 1) == ";") {
    $mime = trim(substr($mime, 0, -1));
}

return (in_array($mime, $mime_type_black_list) == false);

in addition to this you could add virus scan using clamav + the php extension



回答3:

Take a look at php's FileInfo extension.
The recognition of the actual content type is similar to the unix file command.
But that's only helpful against malicious users that simply rename e.g. virus.exe to virus.pdf. It doesn't prevent the upload of an harmful pdf (using some bug in one or more of the more widespread pdf readers).



回答4:

You cannot prevent someone from uploading a virus. The best method is to run a virus scan like clamscan on all files that are uploaded to your site.

Using extension checking/MIME checking will only tell you that the file is named correctly, OR has the correct MIME signature. You will have no way to tell if there is a virus or not until you actually scan it.



回答5:

The simplest two-step answer to allow users to securely upload files in PHP is:

  1. Always save files outside of your document root
  2. Write a PHP script to serve the files without allowing them to be executed

That will stop most file upload based attacks, but not all. A more thorough and complete solution consists of each of the following:

  1. Never storing files outside the document root, serve it via a proxy script (as above).
  2. Using finfo_file() to validate the MIME type of the actual file contents.
  3. When uploading, save to a random filename instead of the one provided, and use a database row to retain the metadata (and so your proxy script can find the correct file to serve).
  4. Encode/encrypt the actual file contents on disk, and make your script decode/decrypt it. This prevents malicious users from uploading a malicious payload then using another vulnerability (e.g. LFI) to trigger it. In this case, base64_encode() should provide a sufficient safeguard. (But if you have another vulnerability in your application, you should really fix that.)

If you do all of the above, your upload form will not likely ever be a source of vulnerability.