PHP上传安全性 - 防止用户使用ajax上传上传无限量的文件

时间:2017-05-18 09:22:52

标签: php ajax forms security upload


编辑2:我注意到用户可以上传无限文件并可以占用所有磁盘空间,如何防止这种情况?
编辑:因为没有人回答这个问题,有没有我可以阅读的来源得到我的答案???

我有联系表格。有三个输入。我使用jQuery插件上传文件。 This插件添加了另一个表单元素并通过ajax上传文件 我是初学者,但这段代码适合客户和实际工作,所以我想确保它的安全!

在我看来:

<form action="" method="post" enctype="multipart/form-data" >
<input type="text" name="name"  />
<input type="number" name="phone" />
<textarea name="enquiry" rows="10" ></textarea>
<div id="upload-div">
<div id="extraupload">Upload</div>
<input type="hidden" name="count" value="0" id="count"/>
<input type="submit" />

$(document).ready(function()
{
   var uploadObj = $("#extraupload").uploadFile({
      url:"/uplod_url",
      fileName:"file",
      onSuccess:function(files,data,xhr,pd)
      {
        data =  jQuery.parseJSON(data);
        if(data.status == 'success') {
          var count = $('#count').val() * 1 + 1;
          for(var i=0; i<data.files.length; i++) {
            $('<input type="hidden" name="file_'+count+'" value="'+data.files[i]+'">').insertBefore('#extraupload');
            $('#count').val(count);
            count++;
          }
        }
      },
    }); 
});
</script>

每次成功上传,都会将一个值添加到input count 并附加一个带有上传文件名值的隐藏输入。

在php中我检查文件类型并更改文件名:

upload_url.php:

if ($_FILES['file']['type']=='image/jpeg' || $_FILES['file']['type']=='image/pjpeg') { 
    $ext = '.jpg';
}
elseif ($_FILES['file']['type']=='image/png') { 
    $ext = '.png'; 
}
elseif ($_FILES['file']['type']=='application/pdf') { 
    $ext = '.pdf'; 
}
else {
    echo json_encode('Only images and pdf files are allowed!');
    die();
}
$fileName = md5(uniqid());
$fileName = $fileName.$ext;
move_uploaded_file($_FILES["file"]["tmp_name"], 'image/tmp'.$fileName); 
$result = array('status'=> 'success','files' => $fileName);
echo json_encode($result);

将文件的名称更改为唯一的哈希后,我将其保存在tmp文件夹中。

然后当提交主表单时,会发生以下情况:

//validation method: if that file exists in tmp folder  
if(isset($this->request->post['count']) && is_numeric($this->request->post['count'])) {
    for($i=1; $i<=$this->request->post['count']; $i++ ) {
        if(isset($this->request->post['file_'.$i])){
            if(!file_exists('image/tmp/'.$this->request->post['file_'.$i])){
                //throw error
            }
        } else{
            //throw error
        }               
    }
}
// hidden input count can only be integer
if(isset($this->request->post['count']) && !is_numeric($this->request->post['count'])) {
    //throw error
}

然后邮寄文件并在数据库中保存文件名(我没有包含数据库部分,因为我确定它没问题)

//by every submition delete files in tmp folder older than 1 day
$oldFiles = glob($tmp_dir."*");
$now   = time();

foreach ($oldFiles as $oldFile) {
    if (is_file($oldFile)) {
        if ($now - filemtime($oldFile) >= 60 * 60 * 24) { 
            unlink($oldFile);
        }
    }
}

$mail = new Mail();
//Mail Setting and details deleted

//if there's any file uploaded
if($this->request->post['count'] != 0) {
    //unique directory for every form submition
    $dir_path = 'image/submitted/'.uniqid();
    mkdir($dir_path, 0764, true);               

    //for all hidden inputs move file from tmp folder to $dir_path
    for ($i=1; $i <= $this->request->post['count']; $i++) {
        $file = $this->request->post['file_'.$i];
        rename('image/tmp'.$file, $dir_path.'/'.$file);
        $mail->AddAttachment($dir_path.'/'.$file);
    }
}
$mail->send();

现在我的问题是:这样安全吗?特别是当我用文件名附加隐藏的输入并从隐藏的输入计数中获取上传文件的数量?
此代码已经有效,但我认为这可能是一个安全问题 非常感谢你的耐心和抱歉我的英语不好!
ps:我使用opencart

1 个答案:

答案 0 :(得分:0)

一般的误解是,在AJAX应用程序中更安全,因为认为用户无法在没有呈现的用户界面(基于AJAX的网页)的情况下访问服务器端脚本。基于XML HTTP Request的Web应用程序掩盖了服务器端脚本,这种模糊性给网站开发人员和所有者带来了错误的安全感 - 默默无闻并非安全。由于XML HTTP请求使用与Web上其他所有协议相同的协议(HTTP),从技术上讲,基于AJAX的Web应用程序容易受到与“普通”应用程序相同的黑客攻击方法的攻击。<​​/ p>