2010-09-04 2 views
10

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

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 находится в папке для закачанных файлов, так что любые файлы в этом каталоге не могут разобрать PHP файлов:

php_admin_value engine Off 

4) Переименовать файл пользователя на что-то заранее определенный. И.Е.

$filename = 'some_pre_determined_unique_value' . $the_file_extension; 

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

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

Спасибо,

+0

Не могли бы вы использовать strip_tags на файл изображения, чтобы удалить PHP теги? –

ответ

20

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

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

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

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

+6

Отличный ответ. Я просто добавлю, что в качестве дополнительной защиты подавайте изображения из другого сайта, кроме домена, в котором вы устанавливаете файлы cookie. Таким образом, даже образ каким-то образом имеет исполняемый код на стороне клиента, одна и та же политика происхождения браузера будет нести большой вред. –

+0

@sri отличная идея, не подумал об этом! –

+0

@SripathiKrishnan, как настроить удаленный домен для изображений. Любая ссылка .. для вашего ответа – sid

1

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

4

Что касается вашего номера 2), не просто проверьте на FALSE. getimagesize также вернет тип 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"); 
} 
+0

+1 пропустил один «хотя (die command line 3). – Thomas

+0

woops. Хороший улов. Ответ исправлен и спасибо. –

+1

Возможно, файл будет действительным gif и содержать php-код одновременно. Таким образом, getimagesize() выиграл – Stann

Смежные вопросы