Безопасное обслуживание изображений


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

Вместо этого он рекомендует хранить изображения над корнем и обслуживать их с помощью fread или fputthrough.

Я не могу понять, каковы будут риски или почему они будут устранены при использовании сценария.
Накладные расходы такого сценария звучат нелепый.

Я понимаю, что изображения должны быть проверены перед сохранением на сервере, и с этой целью я использую imagemagick для незначительного преобразования и сохранения в формате jpeg, что должно избавить от любых загрязнений, насколько я могу предположить.

Итак, вопросы к великим умам по SO:

  1. Существуют ли какие-либо проблемы с безопасностью при локальном хранении изображений с удобными для отслеживания путями?
  2. Безопасен ли мой метод проверки изображений с помощью мгновенных сообщений?
  3. Есть ли причина использовать PHP для обслуживания изображений?
  4. Действительно ли накладные расходы при использовании PHP существенны?
  5. Будет ли использование CDN иметь значение в плане безопасности (я не хочу)?
  6. Я что-то упускаю?

Спасибо всем!

Author: T.Rob, 2011-01-31

4 answers

Я подозреваю, что ваш друг имеет в виду не просто предоставление изображений, а скорее конкретное предоставление пользовательских изображений. При обслуживании пользовательского контента существует ряд проблем с безопасностью. В случае изображений существует несколько способов использовать загрузку изображений, чтобы заставить веб-сервер выполнять код. Некоторые из наиболее известных из них включают:

  • Файл "GIFAR". По сути, это объединенный файл GIF и файл jar. Потому что индекс информация для GIF-файла находится в начале, а для файла jar - в конце, два типа файлов можно объединить, и в результате получится как допустимый GIF, так и допустимый JAR.
  • Несколько расширений файлов. Веб-серверы поддерживают несколько расширений файлов, чтобы обеспечить такие возможности, как интернационализация. Например, файл с именем page.html.fr может соответствовать версии страницы на французском языке. Файл с расширением image.php.jpg или даже image.php.123 может быть исполняемым как PHP-скрипт, в зависимости от конфигурация сервера.
  • Переполнение буфера. Форматы файлов изображений обычно содержат заголовок в начале, который описывает размер и формат файла. Занижение размера может позволить злоумышленникам организовать атаку на переполнение буфера.

Все эти примеры приводят к возможности выполнения кода в качестве веб-сервера. Хотя функциональность сайта требует возможности загружать файлы, хранить их в каталогах, которые не доступны напрямую по URL-адресу это затрудняет их использование. Аналогично, использование сценария для их обслуживания, а не обработчиков MIME веб-сервера гарантирует, что изображения будут обрабатываться как поток данных, а не как потенциально исполняемый файл.

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

У меня нет хороший ответ на вопрос, решит ли использование imagemagick проблемы безопасности. По крайней мере, обязательно используйте текущую версию, потому что быстрый поиск выявил ряд известных уязвимостей. Помните, что файлы, о которых вам нужно беспокоиться, могут привести к сбою imagemagick, даже если они не используют одну из известных уязвимостей, поэтому убедитесь, что у вас ДЕЙСТВИТЕЛЬНО хорошая система отслеживания ошибок.

 9
Author: T.Rob, 2011-01-31 03:12:15

Если изображения не являются частными, т.Е. вы можете видеть их достаточно легко, вы просто не хотите, чтобы кто-то читал их все по своему желанию, может быть достаточно присвоить каждому из них уникальное имя.

Если их больше нескольких тысяч (и это кажется вероятным), то создание иерархии каталогов, в которой они хранятся, также может помочь ускорить доступ, одновременно увеличивая пространство поиска настолько, что они не будут найдены случайным поиском. Например: файл под названием 347168a5d9b4ac5eb386e396f68b2231.jpg может быть помещен в каталог: /images/34/71/68/347168a5d9b4ac5eb386e396f68b2231.jpg Многоуровневый каталог ускоряет доступ, предотвращая сканирование тысяч записей каталога, а случайное имя (хранящееся в базе данных, прикрепленной к списку изображений пользователя в галерее) предотвращает поиск случайных файлов.

 7
Author: Alister Bulman, 2011-01-30 21:53:45

Накладные расходы такого сценария звучат нелепо.

Здесь то же самое. Если изображения общедоступны, я не вижу абсолютно никаких причин для этого.

Если они не общедоступны (т.Е. должны быть доступны только зарегистрированным пользователям), то нет способа обойти описанный вашим коллегой способ (или использовать X-Sendfile после выполнения проверки входа в систему, что экономит часть накладных расходов, если установлено необходимое программное обеспечение). Но если это не так в данном случае накладные расходы, необходимые для этого, являются сумасшедшими.

 5
Author: Pekka 웃, 2011-01-30 21:39:43

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

//check if image should be accessed by the current request...

$fh=fopen($my_image,"rb");

if($fh==NULL){
        exit();
}
rewind($fh);
header("Content-Type: image/png");
header("Content-Length: " . filesize($fn));
fpassthru($fh);

fclose($fh);
exit();
 0
Author: Earlz, 2011-01-31 03:26:59