PHP图片库(上传问题)

时间:2010-12-30 08:26:44

标签: php image class file-upload

这可能是一个简单的问题,但我发现很难完成。

我有一个php类(“class.upload.php”代码在*之下),它被调用:

<?php 
    $upload = new upload(); 
    $upload->upload_file();
?>

所以在测试页面中就是这样:

<?php 
    $upload = new upload(); 
    $upload->upload_file(); 
?>


<form action="" method="post" enctype="multipart/form-data">
    <input type="file" id="real_upload" class="hide" name="file" />
    <input type="submit" id="real_submit" class="hide" value="Upload" />
</form>

问题是我正在为网站的某些部分使用这个上传系统,我想要的是让这个类在上传“图库上传”片段后上传文件:

    <?php

    $mysql_link = mysql_connect("localhost", "", "");   
        mysql_select_db("") or die("Could not select database");

        while($counter <= count($photos_uploaded)) {
            if($photos_uploaded['size'][$counter] > 0) {
                if(!array_key_exists($photos_uploaded['type'][$counter], $known_photo_types)) {
                    $result_final .= "File ".($counter+1)." is not a photo<br />";
                }
                else {
                    mysql_query( "INSERT INTO gallery_photos(`photo_filename`, `photo_caption`, `photo_category`) VALUES('0', '".addslashes($photo_caption[$counter])."', '".addslashes($_POST['category'])."')" );
                    $new_id = mysql_insert_id();
                    $filetype = $photos_uploaded['type'][$counter];
                    $extention = $known_photo_types[$filetype];
                    $filename = $new_id.".".$extention;

                    mysql_query( "UPDATE gallery_photos SET photo_filename='".addslashes($filename)."' WHERE photo_id='".addslashes($new_id)."'" );
 }

    ?>

我将如何处理这个问题?

谢谢,Keiran

class.upload.php

<?php
class Upload {
    //File Max Size:
    protected $max_file_size = 5;

    public function upload_file() {
        //Check for upload request:
        if(isset($_FILES['file'])) {
            //Set File Information:
            $file = array(
                'name' => $_FILES['file']['name'],
                'type' => $_FILES['file']['type'],
                'size' => $_FILES['file']['size'],
                'temp' => $_FILES['file']['tmp_name'],
                'error' => $_FILES['file']['error']
            );

            //Check if it is under the max size limit
            if($file['size'] < ($this->max_file_size * 1048576)) {

            //Filename:
                $filename = strtolower($file['name']);
                $filename = str_replace(" ","_",$filename);

                //Check for a custom path location, if none exists it will load into a file associated directory
                if (isset($_REQUEST['customPath'])) {
                    $path = 'uploads/'.$_REQUEST['customPath'].'/';
                } else {
                    $path = 'uploads/'.$file['type'].'/';
                        if(!file_exists($path) && !is_dir($path)) {
                            mkdir($path, "511", true);
                        }
                }

                //Now lets more the file:
                $move_file = move_uploaded_file($file['temp'], $path . $filename);

                if($move_file) {
                    echo 'uploads/'.$filename;
                }
            } else {
                echo 'Your file is too big to upload to our server.';
            }
        }
    }
}

?>

1 个答案:

答案 0 :(得分:1)

您的上传课程正在打开您的服务器以完全妥协。

  1. 您不会清理customPath字段,并盲目地将其用作“我在何处放置此文件”路径的一部分。恶意用户可以输入相对路径,您的脚本将很乐意尝试在您的服务器上任意编写上传的文件
  2. 您不检查文件名冲突,因此恶意用户可以将漏洞#1与此结合起来,您的脚本将很乐意覆盖Web服务器可以访问的任何文件。虽然(我希望)您的服务器没有以root身份运行,但请考虑../../../../../../../../../../etc/的customPath和上传的文件名passwd,导致您的网络服务器使用用户提供的版本覆盖/etc/passwd
  3. $ _FILES数组中的size参数也是用户提供的,可以简单地伪造。恶意用户可以将其设置为1并上传多TB文件(如果他们愿意的话)。最好使用filesize($_FILES['file']['tmp_name'])来确定实际的文件大小。
  4. 检查isset($_FILES['file'])不足以确定文件是否实际上传。无论上传成功与否,file条目都将在表单中随时重新创建<input type="file" name="file">。您必须检查($_FILES['file']['error'] === UPLOAD_ERR_OK)以查看上传是否成功(错误常量已定义here
  5. $ _FILES数组的type部分也是用户提供的,可以被破坏。没有什么可以阻止恶意用户将其设置为image/jpeg,但仍会将nasty_virus_from_hell.exe上传到您的服务器。您必须使用getimagesize()FileInfo()以安全的方式自行确定mime类型。
  6. addslashes()是一种非常差的清理SQL查询插入数据的方法。它不是一种安全的方法,使用mysql_real_escape_string(),它使用MySQL自己的API进行清理,并以保证对MySQL“安全”的方式这样做。