如何查看上传的文件扩展名?

时间:2014-11-09 14:30:23

标签: php forms security file-upload web

如何在以下代码中检查上传的文件扩展名(我已经编写过文件类型检查)?我想阻止上传错误扩展名的图片文件,例如* .jpg.exe。

我的代码:

<?php

class Uploader {

    private $fileName;
    private $fileData;
    private $destination;

    public function __construct($key){
        $this->fileName = $_FILES[$key]['name'];
        $this->fileData = $_FILES[$key]['tmp_name'];
    }

    public function saveIn($folder){
        $this->destination = $folder;
    }

    public function save(){

        $folderWriteAble = is_writable($this->destination);
        if($folderWriteAble && (exif_imagetype($this->fileData) == IMAGETYPE_JPEG)){
            $name = "$this->destination/$this->fileName";
            $success = move_uploaded_file($this->fileData, $name);
        } else {
            trigger_error("cannot write to $this->destination");
            $success = false;
        }

        return $success;

    }

} 

4 个答案:

答案 0 :(得分:2)

如果您在服务器上运行linux,我会使用命令file检查文件内容类型,该命令返回文件的真实mime类型。你可以确定那些内容是什么(在大多数情况下)。

该程序使用该魔术字节。原始想法是检查第一个视图字节并检查文件是否包含已知模式,例如&#34; MZ&#34;对于Windows可执行文件或&#34;‰PNG&#34;对于png文件。但是,file程序还会比第一个视图字节的基本集更多。


根据评论的不同,您会关注错误,例如:双文件扩展名。我会说不要考虑它,只是重命名该文件,最好用一些随机名称。如果您担心有人只是计算一些文件编号以查看未发布的图像,那么这也会有所帮助。

答案 1 :(得分:1)

我认为你已经在(exif_imagetype($this->fileData) == IMAGETYPE_JPEG)上做了这件事,但这里有一个非常好的讨论:https://security.stackexchange.com/questions/57856/is-there-a-way-to-check-the-filetype-of-a-file-uploaded-using-php

答案 2 :(得分:0)

使用getimagesize检查文件中的前三位。请注意$ _FILES不安全,因为它读取扩展名(当然人们可以改变),而getimagesize读取权限位。

用法:

$image = getimagesize($_FILES['image']['tmp_name']);

$filetype = $image['mime'];

希望这有帮助

答案 3 :(得分:0)

我知道这不一定能回答你的具体问题,但是防止&#34; PHP图像的好方法&#34;被执行&#34;是从没有执行PHP脚本的地方提供图像,只提供静态图像(即:nginx,如果配置正确)。 它甚至可以是外部CDN,也可以只是一个不运行php的简单目录。

话虽如此,你也可以尝试:

1- Make sure file type is (jpg, gif or png)
2- Make sure dimensions are numbers
3- Make sure file size does not exceed allowed size
4- Make sure file is not executable by anyone else (proper chmod settings are important in shared environment).
5- Rename and convert all uploads through imagemagick to jpg (or your desired format)

使用GD库测试您的上传是否为jpg,此外,检查部分上传的图片是否也返回false:

$image = @imagecreatefromjpeg($this->fileData);
if(!$image) { imagedestroy($image); return false; } // file is not a jpg
else { imagedestroy($image); return true; } // file is a jpg

如果可以使用exec(),则还可以调用unix文件实用程序来检查旁路签名。

// verify that the file is a jpg
$mime = "image/jpeg; charset=binary";
exec("file -bi " . $this->fileData, $out);
if ($out[0] != $mime) {
    // file is not a jpg
    ...

如果安装了ClamAV,您还可以使用exec命令检查病毒:

exec("clamscan --stdout " . $this->fileData, $out, $return);
if ($return) {
    // file is infected
    ...