Как защитить скрипт загрузки изображений PHP от эксплойтов?

Я создал (используя скрипт и некоторую помощь от Stack и некоторую помощь от друзей, я очень мало знаю о PHP), простую страницу для местной некоммерческой публикации, где люди могут загружать фотографии.

Я не уверен в безопасности (из-за незнания, а не из-за небрежности), но я предпринял следующие шаги для защиты этой страницы:

• PHP-скрипт настроен только для приема файлов .jpg, .png и .tif для загрузки;
• вложенная папка, в которой сохраняется содержимое формы, имеет разрешения, установленные на уровне 700, а вложенная папка, в которой хранятся загруженные фотографии, имеет разрешения, установленные в 700;
• согласно документации, мой хост имеет следующую конфигурацию, чтобы гарантировать, что только .php-файлы выполняются как .php:

<FilesMatch \.php$> SetHandler php52-fcgi </FilesMatch> 

• Я поместил файл .htaccess в соответствующие (основной и сохраненный контент) папки:

 RemoveHandler .php RemoveHandler .inc RemoveHandler .pl RemoveHandler .cgi RemoveHandler .py RemoveHandler .fcgi 

Ночью, однако, кто-то нашел эту тестовую страницу и представил то, что кажется совершенно доброкачественным тестовым сообщением и маленьким .jpg. Это приватная тестовая страница с неинтуитивным URL, о котором знают только я и около трех других людей; никто из других не отправил это испытание.

Это, очевидно, меня беспокоит, что происходит что-то странное, и я беспокоюсь, что не знаю достаточно о безопасности, чтобы убедиться, что эта страница в безопасности.

Есть ли что-то очевидное, что мне не хватает?

При работе с загруженными вы должны иметь в виду, что все данные, которые вы можете найти в массиве $ _FILES, можно подделать. Он перемещается по HTTP, поэтому довольно легко придать образ / jpg mime исполняемому файлу.

1- Проверить истинный мим

PHP поставляется с некоторой функцией для проверки реального mime файла. Для этого вы должны использовать fileinfo

 $finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic"); $filename = "/var/tmp/afile.jpg"; echo $finfo->file($filename); 

2- Проверить свойства изображения

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

Используйте getImageSize (), чтобы получить всю необходимую информацию об изображении. Если он возвращает false, файл, вероятно, не является изображением, и вы можете его удалить. getImageSize также может дать вам тип mime, но я не знаю, можно ли ему доверять.

2.5 – Обратное изображение

Как было предложено пользователем628405, переработка изображения с помощью GD, вероятно, является более безопасной задачей.

 $img = imagecreatefrompng('vulnerable.png'); imagepng($img, 'safe.png'); 

Очевидно, что он должен быть адаптирован в соответствии с типом изображения. Просмотреть всю документацию в документации php.

3- Загрузить папку В дополнение к тому, что вы уже сделали:

Убедитесь, что ваша загрузочная папка недоступна из Интернета. Подтвердите загруженный файл и при необходимости переместите его в другую папку и переименуйте файл. Это предотвратит выполнение хакером вредоносного файла (его невозможно выполнить, если он не может быть достигнут URL-адресом).

Дальнейшее чтение: https://www.owasp.org/index.php/Unrestricted_File_Upload

Не полагайтесь на данные с клиента, включая тип контента!

Не сохраняйте загруженные файлы в корневом каталоге. Загруженные файлы должны быть доступны только через ваши скрипты для лучшего контроля.

Не сохраняйте загруженные файлы с их исходными именами файлов и расширениями! Сохраните эти данные в базе данных для последующего поиска.

Вы можете проверить тип файла MIME, но не волнуйтесь, пока ваш обработчик php может выполнять только файлы .php, и вы заботитесь о том, чтобы не сохранять загруженные .php-файлы в свой скрипт, вы не подвергаете утечка безопасности.

Это допустимо для файлов .php, а также для любого другого языка сценариев на сервере, установленного на вашем сервере.

Лучше всего сохранить белый список расширений, которые вы принимаете для сохранения в своей файловой системе.

Я бы проигнорировал тип MIME и расширение файла входящего файла. Их можно подделать.

Храните эти файлы в каталоге, если вы идете по этому проспекту.

Убедитесь, что этот каталог предназначен только для изображений (музыки), а затем получите скрипт, чтобы разместить на них правильное расширение, просмотрев формат файлов.

Также убедитесь, что этот каталог не может выполнять PHP (или что-то еще).

Это будет держать вас в безопасности.