上载时检查文件类型以及浏览器依赖性问题

时间:2010-01-08 13:04:52

标签: php mime-types

我正在构建一个php文件上传器,我遇到了一些安全问题。例如,我不想允许“.php”文件上传。据我所知,检查文件类型的唯一方法是使用$_FILES['file']['type'],并且它的值取决于浏览器。

我检查了多个浏览器并发现在选择常规.php文件时,不同的浏览器会返回以下值:

firefox: application/x-download
chrome: text/plain
safari: text/plain
IE: text/plain
opera: application/octet-stream

我还尝试使用常规.txt文件进行相同的实验,并且所有浏览都返回text/plain作为mime类型。

所以这就是问题所在,如果我想允许.txt文件上传我应该做些什么来阻止.php文件上传?

3 个答案:

答案 0 :(得分:3)

不要依赖客户端发送的信息。即使是客户端发送的媒体类型也可以伪造。

如果您不想允许PHP文件,请不要允许文件扩展名为.php的文件或将其更改为.txt

if (strtolower(strrchr($_FILES['file']['name'], '.')) == '.php') {
    // has file extension .php
}

答案 1 :(得分:2)

使用以下功能:

function Mime($path)
{
    $result = false;

    if (is_file($path) === true)
    {
        if (function_exists('finfo_open') === true)
        {
            $finfo = finfo_open(FILEINFO_MIME_TYPE);

            if (is_resource($finfo) === true)
            {
                $result = finfo_file($finfo, $path);
            }

            finfo_close($finfo);
        }

        else if (function_exists('mime_content_type') === true)
        {
            $result = preg_replace('~^(.+);.*$~', '$1', mime_content_type($path));
        }

        else if (function_exists('exif_imagetype') === true)
        {
            $result = image_type_to_mime_type(exif_imagetype($path));
        }
    }

    return $result;
}

这将返回任何文件的正确mime类型。

答案 2 :(得分:0)

尝试以下方法。这是FAR从傻瓜证明,但它是一个快速检查。它会阻止任何标记为.php的东西(因为它在客户端机器上),所以如果它们有类似'do_evil.php.txt'的东西,它将允许它BUT(阅读代码注释)

$file_ext = substr($_FILES['userfile']['name'], -3);
if($file_ext == 'php') {
   //REJECT FILE
}
else {
   // allow upload and once the file has been upload to the temp directory
   // have a peice of code move the file to the final location and rename 
   // the file and specify a new file extension, using $file_ext as the extension
   // so even if the file was 'do_evil.php.txt' when it comes to rest at the 
   // final location it will be 'do_evil.txt' and thus treated by the server as a
   // text file and not PHP
}

我过去曾使用过上述结果。它绝不是防弹,但它至少应该有所帮助。我想我可能会有一些代码可以解决所有这些问题,如果你需要它就会去寻找它但没有承诺我能找到它