Разработка на PHP: Как реализовать метод проверки загружаемого файла (изображения) на наличие вредоносного PHP-кода в метаданных (EXIF)?
При загрузке изображений на сервер злоумышленники нередко внедряют вредоносный PHP-код прямо в EXIF-метаданные файла. Если такой файл будет обработан или исполнен сервером, это может привести к серьёзным последствиям — от утечки данных до полного захвата сервера. Рассмотрим, как реализовать надёжную проверку.
**1. Чтение EXIF-данных с помощью exif_read_data()**
PHP предоставляет встроенную функцию `exif_read_data()`, которая позволяет извлечь все метаданные из изображения:
php
$exifData = @exif_read_data($filePath, null, true);
Функция возвращает многомерный массив со всеми секциями EXIF. Важно использовать оператор `@` для подавления предупреждений при некорректных файлах.
**2. Поиск PHP-кода в метаданных**
После получения EXIF-данных необходимо рекурсивно обойти все поля и проверить наличие характерных PHP-конструкций:
php
function containsMaliciousCode(array $data): bool {
$patterns = [
‘/<?php/i',
'/<?=/i',
'/evals*(/i',
'/base64_decodes*(/i',
'/systems*(/i',
'/execs*(/i',
'/passthrus*(/i',
'/shell_execs*(/i',
'/preg_replaces*(.*/e/i',
];
foreach ($data as $value) {
if (is_array($value)) {
if (containsMaliciousCode($value)) return true;
} else {
foreach ($patterns as $pattern) {
if (preg_match($pattern, (string)$value)) return true;
}
}
}
return false;
}
**3. Дополнительная проверка через бинарное содержимое файла**
EXIF — не единственное место для инъекции. Стоит также проверить сырое содержимое файла:
php
$content = file_get_contents($filePath);
if (preg_match('/<?php/i', $content) || preg_match('/<?=/i', $content)) {
// Файл содержит PHP-код
return false;
}
**4. Пересохранение изображения для очистки метаданных**
Надёжный способ — пересоздать изображение через GD или Imagick. Это уничтожает все метаданные:
php
$image = imagecreatefromjpeg($filePath);
imagejpeg($image, $cleanFilePath, 90);
imagedestroy($image);
**5. Комплексная стратегия защиты**
— Всегда проверяйте MIME-тип через `finfo_file()`, а не через `$_FILES['type']`.
— Храните загруженные файлы вне директории `public` или запретите их исполнение через `.htaccess` (`php_flag engine off`).
— Переименовывайте файлы при сохранении, удаляя оригинальное расширение.
— Используйте белый список допустимых MIME-типов.
— Регулярно сканируйте директорию загрузок антивирусными инструментами (например, ClamAV через `exec`).
Комбинирование всех перечисленных методов обеспечивает многоуровневую защиту от инъекций через загружаемые изображения.
