Как я могу проверить расширение загруженных файлов в следующем коде (я уже писал проверку типа файла)? Я хочу предотвратить загрузку файлов изображений с неправильным расширением, например *.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, я бы проверил тип содержимого файла с помощью командного file
который возвращает реальный тип mime файла. Чем вы можете быть уверены, что это за контент (в большинстве случаев).
Эта программа использует магические байты. Оригинальная идея состоит в том, чтобы проверить первые байты представления и проверить, содержит ли файл известный шаблон, например "MZ" для исполняемых файлов Windows или "‰ PNG" для png файлов. Однако в этой file
программе также есть несколько вещей, кроме базового набора первых байтов представления.
В зависимости от комментариев вы обеспокоены неправильным, например, удваиваете расширения файлов. Я бы сказал, не думайте об этом и просто переименуйте этот файл, в лучшем случае с каким-то случайным именем. Это также может быть полезно, если вы беспокоитесь о том, что кто-то просто подсчитывает некоторые номера файлов, чтобы увидеть неопубликованные изображения.
Я думаю, что вы уже делаете это (exif_imagetype($this->fileData) == IMAGETYPE_JPEG)
, но здесь есть очень хорошая дискуссия: https://security.stackexchange.com/questions/57856/is-there-a -WAY к регистрации по прибытии в-типа файлов-на-а файла-закачанный- с использованием PHP-
Я знаю, что это не обязательно ответит на ваш конкретный вопрос, но хороший способ предотвратить "выполнение изображений 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 файла для проверки подписей bynary.
// 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
...
Используйте getimagesize, который проверяет первые три бита в файле. Обратите внимание, что $ _FILES не является безопасным, поскольку он читает расширение (которое люди могут сменить, конечно), vs getimagesize, который считывает биты разрешения.
Применение:
$image = getimagesize($_FILES['image']['tmp_name']);
$filetype = $image['mime'];
Надеюсь это поможет