如何在下面的代码中检查上传的文件扩展名(我已经写了一个文件类型检查)?我想防止上传带有错误扩展名的图像文件,如*.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;
}
}
如果您在服务器linux上运行,我会使用返回文件真实mime类型的命令file
检查文件内容类型。然后你可以确定内容是什么(在大多数情况下)。
那个程序使用了神奇的字节。最初的想法是检查第一个视图字节,并检查文件是否包含已知模式,例如,对于windows可执行文件为"MZ",对于PNG文件为"‰PNG"。然而,file
程序也做了一些比仅第一视图字节的基本集合更多的事情。
根据评论,您担心的是错误的,例如双文件扩展名。我想说的是,不要想它,只需重命名该文件,在最好的情况下使用一些随机名称。如果你担心有人只是统计一些文件号来查看未发布的图像,这也会有所帮助。
我认为您已经在(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
使用getimagesize检查文件中的前三位。请注意,$_FILES读取扩展名(当然人们可以更改)与读取权限位的getimagesize相比并不安全。
用法:
$image = getimagesize($_FILES['image']['tmp_name']);
$filetype = $image['mime'];
希望这能帮助
我知道这不一定能回答你的具体问题,但防止"PHP图像"被"执行"的一个好方法是让图像从一个不执行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
...