0

提供用户上传图片有广泛的用途,但是检查文件扩展名和 MIME 类型并不能保证正确的文件类型。

替代方案:我使用imagejpeg()imagecreatefromjpeg()函数来创建图像$_FILE['userfile']['tmp_name'],然后将其保存在images/目录中。在这种情况下,我忽略了move_uploaded_file()函数。

这段代码仍然容易受到假图片上传攻击吗?

$filename = $_FILE['inputfile']['name'];
$upload_path = 'images/';
//extract extension
$ext = strtolower(substr($filename, strrpos($filename, '.') + 1));

// return mime type ala mimetype extension
$finfo = finfo_open(FILEINFO_MIME_TYPE);
//get MIME type of the given file
$mime = finfo_file($finfo, $filename);
//close finfo
finfo_close($finfo);

if (is_uploaded_file($_FILES['inputfile']['tmp_name'])) {
    //first check: file extension and mime type
    if(!in_array($ext, array('jpeg', 'jpg', 'gif', 'png')) && !in_array($mime, array('image/jpeg', 'image/gif', 'image/png')) ){
     die("Error1: Invalid Image type");
    }
    if($ext == 'jpeg' || $ext == 'jpg'){
       $im = @imagecreatefromjpeg($_FILE['inputfile']['tmp_name']);
       if($im){

        $createimage = imagejpeg($im, $upload_path.$_FILE['inputfile']['name']);
        if(!$createimage){
          die("Error3: Can't create image!");
        }
        //last check
        $filecontent = file_get_contents($upload_path.$_FILE['inputfile']['name']);

        //clean the file from any php code
        $filecontent = str_replace(array("<?php", "<?", "?>"), "", $filecontent);

        $handle = fopen($upload_path.$_FILE['inputfile']['name'], "wb");
        fwrite($handle, $filecontent);
        fclose($handle);
       }
       else{

        die("Error2: Invalid Image Detected");

       }
    }

}
4

1 回答 1

1

始终可以将 PHP 代码安全地嵌入到完全有效的图像文件中。有太多方法可以做到这一点,甚至值得考虑避免它们。许多有效的图像格式,许多数据容器,例如 jpg 中的 EXIF,像素级和压缩操作等。

为了安全起见,应该保护服务器免受任意文件包含攻击并清理文件扩展名以逃避 apache 配置错误。

更疯狂的方法是创建一个稍微修改过的图像副本,更准确地说,从修改过的原始图像创建一个新图像,轻微调整大小或颜色操作将删除位图级别的 PHP 注入,而复制将使您免于大部分 PHP注入到图像内的其他数据容器中。

于 2013-08-14T20:55:47.857 回答