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

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

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

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

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

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

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

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


person SamGoody    schedule 30.01.2011    source источник
comment
Какие вопросы безопасности вас беспокоят? Возможность пользователей просматривать изображения, которые не должны быть доступны только избранным пользователям? Вредоносное ПО? Что-то другое?   -  person Quentin    schedule 31.01.2011
comment
Я не могу оценить риски - имел в виду, что я хотел бы понять, связаны ли риски с тем, что кто-то может увидеть изображения, не предназначенные для них, или это может открыть меня для атакующих атак на сервер. Если бы я знал о рисках, мне было бы лучше.   -  person SamGoody    schedule 31.01.2011


Ответы (4)


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

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

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

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

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

person T.Rob    schedule 31.01.2011
comment
... или просто выполните chmod -X ./images, чтобы избежать всех проблем на стороне сервера. - person Earlz; 31.01.2011
comment
Это защищает их от выполнения операционной системой и некоторыми обработчиками MIME, но не всеми обработчиками MIME, и не защищает от уязвимостей переполнения буфера. - person T.Rob; 31.01.2011
comment
Ух ты. Спасибо за информацию, и за то, что нашли время, чтобы написать это так ясно. Можно ли где-нибудь найти список всех известных уязвимостей? - person SamGoody; 31.01.2011
comment
Окончательный сайт — cve.mitre.org, хотя там только перечислены уязвимости. Многие уязвимости существуют из-за выбора конфигурации или дизайна архитектуры, и список CVE не сообщает об этом. Решение таких проблем требует глубокого знакомства с технологиями компонентов платформы и привычки быть в курсе проблем безопасности на этой конкретной платформе. - person T.Rob; 31.01.2011

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

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

person Alister Bulman    schedule 30.01.2011
comment
Хорошие моменты, особенно об использовании каталогов для ускорения работы. +1 - person Pekka; 31.01.2011

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

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

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

person Pekka    schedule 30.01.2011
comment
+1 за это. Если изображения являются общедоступными для всех, нет причин обертывать доставку сценарием. В противном случае да, вы должны обслуживать их со сценарием, чтобы проверить, что вам нужно проверить (например, зарегистрированный статус и право собственности пользователя), прежде чем доставлять контент. Чао! - person lomanf; 31.01.2011

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

//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();
person Earlz    schedule 31.01.2011