如何在以下代码中检查上传的文件扩展名(我已经编写过文件类型检查)?我想阻止上传错误扩展名的图片文件,例如* .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;
}
}
答案 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
...