Подход к безопасности загрузки изображений PHP
Я создаю PHP скрипт, чтобы заменить текущий, который будет подвержен большому воздействию различных рынков/стран.
Этот script между другими предлагает функцию загрузки фотографий.
После многого чтения о проблеме я последовал описанному ниже подходу.
Я был бы глубоко признателен за ваши замечания относительно его безопасности.
- Фотография загружается в приватную папку 777 за пределами веб-корневого каталога.
- Выполняется проверка для белых перечисленных расширений (разрешено только jpgs, gifs, png) все остальное удалено.
- Использование getimagesize для проверки размеров min-max и достоверности фотографий.
- Проверка соответствия типа файла и файла.
- Изменение размера загруженной фотографии на размеры std (с помощью imagecopyresampled).
- Сохранение созданных файлов как jpg.
- Удаление исходного файла.
- Сохранить фотографии с новым (не случайным именем), т.е. img51244.jpg.
- Переместить новые фотографии в подкаталоги переменных общей папки (777 разрешений) в соответствии с не предсказуемым алгоритмом. I.e.,
img10000.jpg
будет сохранен в photos/a/f/0/img10000.jpg
, а img10001.jpg
будет сохранен в photos/0/9/3/img10001.jpg
. Это делается по другим причинам (использование субдоменов для статического содержимого служит или используется CDN).
script будет выполняться на выделенном сервере Linux.
Ответы
Ответ 1
- Каталог с chmod 0777 является, по определению, общедоступным для других пользователей, зарегистрированных на вашем сервере, а не частных. Правильные разрешения будут 700 и будут принадлежать
apache
(или любому пользователю, на котором работает ваш веб-сервер). Я не уверен, почему вы не использовали бы временный каталог php default здесь, так как он также находится за пределами корня веб-сайта.
- Белый список - хорошая идея. Будьте осторожны, чтобы иметь правильную реализацию. Например, regexp
/.png/
действительно соответствует apng.php
.
- Этот шаг - отличная идея. Он в основном проверяет файловую магию.
- Не обязательно. На двух предыдущих шагах мы определили правильность формата расширения и файла. Если вам нужен правильный MIME-тип, который будет указан клиентом, вы также должны убедиться, что данный тип MIME и один из указанных выше эквивалентны.
Шаги с 5 по 8 не связаны с безопасностью.
Шаг 9: Я предполагаю, что ваш сайт позволяет каждому видеть каждую фотографию. Если это не так, у вас должна быть схема URL-адресов с существенно более длинными URL-адресами (например, хэш-образ изображения).
Ответ 2
Вы также должны проверить размер загруженного файла, поскольку getimagesize иногда может превышать доступную оперативную память. Также полезно предположить, что ваш script может сбой в любой момент (например, когда электричество идет вниз), поэтому вы должны выполнить некоторые процедуры очистки, чтобы удалить левые ненужные файлы.
Ответ 3
Это довольно полный подход, но я не вижу механизма предотвращения выполнения кода.
Вы должны убедиться, что содержимое изображения никогда не включается (с вызовом include или require) или выполняется через eval().
В противном случае может быть запущен PHP-код, включенный в конец файла.
Вы также можете попытаться обнаружить php-код внутри содержимого изображения (с файлом_get_contents, а затем с помощью регулярного выражения для поиска "<? php" ), но я не смог найти 100% -ный безопасный способ устранения подозрительного кода без разрушения некоторые (действительные) изображения.