Есть Ли Какие — Либо Проблемы С Безопасностью В Следующем Скрипте Загрузки Файла- PHP

#php #file #security #file-upload #imageprocessor

Вопрос:

Я просмотрел ряд ответов на вопросы StackOverflow о безопасной загрузке изображений с помощью PHP. Я собрал этот следующий сценарий вместе с объяснителями и хотел знать, не упускает ли он чего-нибудь. Моя единственная/главная проблема заключается в том, что я, похоже, не могу найти много информации об удалении вредоносного кода из самого изображения, хотя это частично описано в коде.

Пара ответов SO касаются GD функциональности изображений, но на самом деле они не дают никаких хороших примеров кода, и, поскольку я новичок в php, я не могу понять, как это использовать (с точки зрения создания новой версии изображения).

Примечание: Эти изображения в этом коде переходят в каталог «/images», но на реальном сайте они перейдут в поддомен под названием «изображения», который находится за пределами общей папки и будет обслуживать только статические файлы (без PHP, Perl и т. Д.). Он short_open_tag будет отключен в файле php.ini.

Файлы выбираются с file помощью типа ввода с именем «профиль-изображение».

Следующий код разделен на составные части — первая часть-это операторы if/isset, которые проверяют, что была нажата кнопка отправки, называемая «отправить-профиль-изображение», и файлы были загружены в память в ['tmp_name'] ключе $_FILES суперглобального:

 if(isset($_POST['submit-profile-image'])) {

    $allowed = ['jpeg', 'jpg', 'png'];

    if($_FILES['profile-image']['error'] === 0 ) { 

        // THE DIFFERENT CHECKS IN THE MAIN CODE BELOW GO HERE

    } else {
        $error[] = "Image failed to load please try again";
    }
}
 

Весь этот следующий код содержится во 2 — м операторе if, показанном выше, — я разбил его, чтобы показать, для чего он предназначен:

Установите имена переменных для временного файла загрузки и имя файла ввода

 $profileImageName = $_FILES['profile-image']['name'];
$temp = $_FILES['profile-image']['tmp_name'];
 

Разнесите строку, чтобы разделить имя файла и расширение файла

 $ext = explode('.', $profileImageName);
$ext = strtolower(end($ext));
 

Полностью переименуйте файл и сохраните только расширение файла из исходного файла:

 $file = uniqid('', true) . time() . '.' . $ext;
 

Очистите строку для дополнительной безопасности (возможно, не требуется)

 $file = filter_var($file, FILTER_SANITIZE_STRING);

$file = strtolower($file);
 

Проверьте, соответствует ли расширение файла разрешенному массиву расширений файлов:

 if (!in_array($ext, $allowed)) {
    $error[] = "File type must be in the jpg / jpeg or png format";
}
 

Check MIME type using the getImageSize() function which is more reliable than the ‘type’ key found in the standard $_FILES superglobal:

 $getImageSizeMime = getImageSize($temp);

if(isset($getImageSizeMime['mime']) == false) {
    $error[] = "Not a recognised MIME type";
} else {
    $getImageSizeMime = $getImageSizeMime['mime'];
}
 

Убедитесь, что тип MIME соответствует расширению файла:

 if (in_array($ext, $allowed) != $getImageSizeMime) {
    $error[] = "Mime type must be of the jpg / jpeg or png format";
}
 

Проверьте содержимое самого файла изображения:

 $cleanUpload = file_get_contents($temp) ;
 

Запретить, если содержимое файла содержит php или script :

 if(preg_match('/(<?phps)/', $cleanUpload)) {
    $error[] = "Image data cannot contain php script tags";
}

if(preg_match('/script/', $cleanUpload)) {
    $error[] = "Image data cannot contain javascript tags";
}
 

Очистите содержимое файлов HTML-тегов

 $cleanUpload = filter_var($cleanUpload, FILTER_SANITIZE_STRING);
 

Переместите загруженный файл, если ни одна из вышеперечисленных ошибок не присутствует

 if (!isset($error)) {
    if(in_array($ext, $allowed)) {

        move_uploaded_file($temp, 'images/' . $file);

    }
}
 

Любая информация о любых пропущенных проблемах безопасности или любых дополнительных проверках самого файла изображения была бы чрезвычайно признательна — особенно о том, как дублировать изображение, чтобы сохранить данные изображения только с помощью библиотеки GD, если это возможно/необходимо? Некоторые ответы на StackOverflow очень старые и, похоже, содержат методы, которые также не считаются самыми современными (чего я избегал в этом вопросе).

Было бы действительно полезно посмотреть, существуют ли какие-либо методы PHP для проверки самих файлов изображений и удаления потенциально опасного кода.

Комментарии:

1. Запуск FILTER_SANITIZE_STRING в подлинном файле изображения может привести к повреждению файла.

2. «проверка самих файлов изображений и удаление потенциально опасного кода» Вам не нужно сильно беспокоиться о содержимом изображения, если вы не пытаетесь выполнить файл изображения. Вы можете использовать GD или ImageMagick для чтения файла, а затем перезаписать его, тем самым гарантируя, что это действительное изображение.

3. @TangentiallyPerpendicular — я действительно беспокоился об этом. Это не было сделано ни на одном из (многих) изображений, которые я пытался загрузить в пакетном режиме, но, скорее всего, опущу это в окончательном коде.

4. Также @AlexHowansky что вы подразумеваете под unless you're trying to execute the image file этим ? Изображения будут либо использоваться в профиле пользователя, либо храниться в галерее, и изображения из галереи будут загружаться для пользователей с помощью кнопки загрузки. Так что, я полагаю, это действительно означает исполняемый файл?

5. Если в файле есть «вредоносный код», и файл назван как изображение, и вы сохраняете его на своем сервере и передаете его пользователям с помощью IMG тега, то все, что они получат, — это значок сломанного изображения. Единственный способ, которым «вредоносное» изображение может причинить вам вред, — это если вы сделаете что-то подобное require или shell_exec на нем.