提问

问题1:上传漏洞是怎么产生的?

问题2:是否可以只用js判断文件类型而php不判断?

问题3:为什么必须用move_uploaded_file?

课程单元

一个简单的文件上传例子

文件上传漏洞是怎么产生的

如何避免文件上传漏洞

1. 一个简单的文件上传例子

这是一个简单的上传文件的html代码。

<form action="upload.php" method="post" enctype="multipart/form-data">
    选择一个文件:<input type="file" name="file" /><br />
    <input type="submit" value="上传" />
</form>

这是一个简单的上传文件的php代码。

<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['file']['name']);
if(move_upload_file($_FILES['file']['tmp_name']), $uploadfile)){
    echo "文件上传成功";
}
else{
    echo "文件上传失败";
}

2. 文件上传漏洞是怎么产生的

上面的文件上传的例子,没有对被上传的文件进行任何判断,这样用户可以上传一个.php文件,然后通过浏览器访问该php文件,来达到攻击的目的。

3. 如何避免文件上传漏洞

1、js判断允许上传的文件类型

2、php判断允许上传的文件类型

3、使用move_uploaded_file

4、web服务器增加配置

3.1. JS判断上传的文件类型

在客户端提交文件上传之前,判断只允许上传指定类型的文件。

<script type="text/javascript">
    function checkform(){
        var filename = uploadform.file.value;
        var fileext = filename.substring(filename.length - 4, filename.length);
        if(fileext != '.jpg'){
            alert('文件类型必须为jpg!');
            return false;
        }
        return true;
    }
</script>
<form action="upload.php" method="post" enctype="multipart/form-data" onsubmit="return checkform();">
    选择一个文件:<input type="file" name="file" /><br />
    <input type="submit" value="上传" />
</form>

3.2. php判断上传的文件类型

在文件上传后,判断上传的文件类型,如果类型不对,则不执行上传操作。

<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['file']['name']);

$fileext = strtolower(end(explode('.', $uploadfile)));
if($fileext != '.jpg'){
    echo '文件类型必须为jpg!';
    die();
}

if(move_upload_file($_FILES['file']['tmp_name']), $uploadfile)){
    echo "文件上传成功";
}
else{
    echo "文件上传失败";
}

3.3. 使用move_uploaded_file

bool move_uploaded_file ( string $filename , string $destination )

本函数检查并确保由 filename 指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 destination 指定的文件。

在执行文件上传操作时,都必须用这个函数来移动上传的临时文件到正式目录下,而不能自己使用move方法来移动。

3.4. web服务器增加配置

可以在web服务器中,配置保存上载的目录不能执行php文件,这样万一js或者php判断都不严谨,也不会出现问题。

apache服务器配置不能执行php文件

<Location /uploads>
    AddType application/x-httpd-php-source .php
</Location>