dongtui2029
2015-05-23 21:02
采纳率: 0%
浏览 79
已采纳

什么是最安全的PHP文件上传方法,可以处理所有文件类型?

I am trying to develop a small social network and would like to know if the following approach would be enough to make my 'file upload handling script' as secure as possible. I aim to allow my users to upload images[jpeg,jpg,png,gif], videos[3gp,wma,mp4] and mp3 files. I have gone through many of the questions here at SO, but most of them seem to deal with image uploading in detail and not videos and mp3. I would like to know what more i can do anything to make the script the msot secure uploading script available. [yes, i am pretty paranoid about security and would definitely want my site to be known for it's security rather than it's speed]. My current approach is as follows:

  • check if user is registered (by checking the session)
  • check if file is uploaded without errors
  • check if file size is in permissible range
  • sanitize the file name
  • get the file extension and check if it is an allowed extension
  • get the mime type and check if it is an allowed mime type
  • generate new random file name
  • set .htaccess rules for a folder outside public_html and use it to store the uploaded files
  • use move_uploaded_file()
  • use chmod() to set '0644' as permission for the uploaded file

In the .htaccess file the following will be added:

 SetHandler none
    SetHandler default-handler
    Options -ExecCGI
    php_flag engine off

ForceType application/octet-stream
<FilesMatch "(?i)\.jpe?g$">
    ForceType image/jpeg
</FilesMatch>
<FilesMatch "(?i)\.gif$">
    ForceType image/gif
</FilesMatch>
<FilesMatch "(?i)\.png$">
    ForceType image/png
</FilesMatch>
<FilesMatch "(?i)\.mp3$">
    ForceType audio/mpeg
</FilesMatch>
<FilesMatch "(?i)\.mp4$">
    ForceType video/mp4
</FilesMatch>

The code that i am trying is as follows :

$fileInput = $_FILES['image'];
$sizeLimit="4000";
if($fileInput['error'] === UPLOAD_ERR_OK && isset($fileInput['tmp_name'])){
if($fileInput['size'] < $sizeLimit){
$cleanedName=stripslashes($fileInput['name']); //cleaning file name
$checking = pathinfo($cleanedName); //finding extension
$ext=$checking['extension'];
$finfo = finfo_open(FILEINFO_MIME_TYPE); // find mime type
$mimetype =  finfo_file($finfo, $fileInput['tmp_name']);
finfo_close($finfo);
.
.
.//generate random name and use move_uploaded_file() and chmod()
}
}

Is this approach enough to keep my site secure,or are there some glaring flaws in this method?. Thanks in advance for your help.

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • duanbinian2243 2015-05-24 07:15
    已采纳

    Checking the filename extension is recommended, although be aware that the mime type can easily be spoofed, so this is not a good check for security.

    What you have so far is good, my additional tips would be:

    • Virus scan all uploads - this is more to protect other users of your application rather than your server.
    • Store images outside of the web root totally, and use an approach such as this one to proxy the files to be served. This has the advantage that any additional permission checks can be carried out in code (so Bob can't download Alice's files) and as the files are accessed as data, there is no chance of execution.
    • Serve files with the X-Content-Type-Options: nosniff header to prevent any XSS attacks via IE's mime sniffing.
    • Store images using server generated names. For example, you could name each file after the primary key of its database entry. This will mitigate against any directory traversal attacks (like this one) and if a user does manage to upload something malicious they will be less likely to find it on the server.
    • Load all images into an image library and resave them to ensure they don't have any exploits embedded for popular browsers.
    • Have some sort of manual monitoring system in place to watch for any uploaded illegal content.
    • Protect your form against CSRF.
    已采纳该答案
    打赏 评论