Безопасные возможности загрузки изображений пользователей в PHP

Я реализую пользовательский инструмент для загрузки изображений для своего сайта. Система должна позволять любым пользователям загружать только файлы JPEG и PNG. Я, конечно, беспокоюсь о безопасности, и поэтому мне интересно, как многие умные люди, чем я, испытывают следующие проверки для разрешения загрузки:

1) Первый белый список допустимых расширений файлов в PHP, чтобы разрешить только PNG, png, jpg, JPG и JPEG. Извлеките расширение файла пользователя с помощью функции, например:

return end(explode(".", $filename)); 

Это должно помочь запретить пользователю загружать что-то вредоносное, например .png.php. Если это пройдет, перейдите к шагу 2.

2) Запустите функцию php getimageize () в файле TMP. Через что-то вроде:

 getimagesize($_FILES['userfile']['tmp_name']); 

Если это не возвращает false, продолжайте.

3) Убедитесь, что файл .htaccess помещен в каталог uploads, так что любые файлы в этом каталоге не могут анализировать файлы PHP:

 php_admin_value engine Off 

4) Переименуйте файл пользователя в заранее определенное. IE

 $filename = 'some_pre_determined_unique_value' . $the_file_extension; 

Это также поможет предотвратить внедрение SQL, поскольку имя файла будет единственной определяемой пользователем переменной в любых запросах.

Если я выполню вышеизложенное, насколько уязвим для атаки, я все еще? Прежде чем принимать файл, я должен надеяться, что 1) разрешено только jpg и png, 2) проверено, что PHP говорит, что это допустимое изображение, 3) отключил каталог, в котором находятся изображения из исполняемых файлов .php, и 4) переименовал файл пользователя в нечто уникальный.

Благодаря,

Related of "Безопасные возможности загрузки изображений пользователей в PHP"

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

Если вы хотите полностью убедиться, что контент чист, подумайте об использовании GD или ImageMagick, чтобы скопировать входящее изображение 1: 1 в новый, пустой.

Это немного уменьшит качество изображения, потому что контент будет сжат дважды, но он удалит любую информацию EXIF, присутствующую в исходном изображении. Пользователи часто даже не знают, сколько информации попадает в раздел метаданных файлов JPG! Информация о камере, положение, время, используемое программное обеспечение … Это хорошая политика для сайтов, на которых размещаются изображения, чтобы удалить эту информацию для пользователя.

Кроме того, копирование изображения, вероятно, избавит вас от большинства эксплойтов, которые используют ошибочные данные изображения, чтобы вызвать переполнение в программном обеспечении для просмотра, и внедрить вредоносный код. Такие манипулируемые изображения, вероятно, просто окажутся нечитаемыми для GD.

Что касается вашего номера 2), не просто проверьте FALSE . getimagesize также вернет тип mime изображения. Это, безусловно, более безопасный способ проверки правильного типа изображения, чем просмотр типа mime, который клиент предоставляет:

 $info = getimagesize($_FILES['userfile']['tmp_name']); if ($info === FALSE) { die("Couldn't read image"); } if (($info[2] !== IMAGETYPE_PNG) && ($info[2] !== IMAGETYPE_JPEG)) { die("Not a JPEG or PNG"); } 

Все проверки выглядят хорошо, номер 3 в частности. Если производительность не является проблемой или вы делаете это в фоновом режиме, вы можете попробовать получить доступ к изображению с помощью GD и увидеть, действительно ли это изображение, а не просто куча дерьма, который кто-то пытается заполнить вашим сервером.