#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
на нем.