Как предотвратить изображение бомбы с ImageMagick?

В настоящее время я использую библиотеку Imagick на PHP и использую функцию изменения размера Image Magick. Я только что узнал о декомпрессионных бомбах и о том, как ImageMagick уязвим к нему.

Я проверил, как мы можем пропинговать изображение и проверить размеры изображения, фактически не загружая его в память / диск. Также безопаснее ограничить ограничения памяти и диска ImageMagick, чтобы он не просто записывал огромный файл на диск.

Я прочитал, и я могу сделать это с помощью setResourceLimit ().
http://php.net/manual/en/imagick.setresourcelimit.php

IMagick::setResourceLimit(IMagick::RESOURCETYPE_MEMORY , 100);
IMagick::setResourceLimit(IMagick::RESOURCETYPE_DISK , 100);

$thumb = new Imagick('image.png');
$thumb->resizeImage(320,240,Imagick::FILTER_LANCZOS,1);

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

Обновить:

Вот версии пакета, которые я использую:

dpkg -l | grep magick
ii  imagemagick-common                    8:6.6.9.7-5ubuntu3.3              image manipulation programs -- infrastructure
ii  libmagickcore4                        8:6.6.9.7-5ubuntu3.3              low-level image manipulation library
ii  libmagickwand4                        8:6.6.9.7-5ubuntu3.3              image manipulation library
ii  php5-imagick                          3.1.0~rc1-1                       ImageMagick module for php5

3

Решение

Установка предела «Область ресурса» устанавливает только размер, при котором изображения не хранятся в памяти, а вместо этого переносятся на диск. Если вы хотите использовать этот параметр для фактического ограничения максимального размера изображения, которое может быть открыто, вам также необходимо установить ограничение «Ресурсный диск».

Приведенный ниже код правильно отображает ошибку выделения памяти для снятых бомб отсюда.

try {
Imagick::setResourceLimit(Imagick::RESOURCETYPE_AREA, 2000 * 2000);
Imagick::setResourceLimit(Imagick::RESOURCETYPE_DISK, 2000 * 2000);

$imagick = new Imagick("./picture-100M-6000x6000.png");
$imagick->modulateImage(100, 50, 120);
$imagick->writeImage("./output.png");

echo "Complete";
}
catch(\Exception $e) {
echo "Exception: ".$e->getMessage()."\n";
}

Выход:

Исключение: сбой выделения памяти `./picture-100M-6000×6000.png ‘@ error / png.c / MagickPNGErrorHandler / 1630

Если вы хотите установить ресурс width и height и иметь версию ImageMagick> = 6.9.0-1, вы сможете использовать значения непосредственно WidthResource = 9, HeightResource = 10

//Set max image width of 2000
Imagick::setResourceLimit(9, 2000);
//Set max image height of 1000
Imagick::setResourceLimit(10, 1000);

Они не должны быть установлены программно, вы можете установить их через policy.xml файл установлен с ImageMagick. ImageMagick читает этот файл и использует эти настройки, если они не заданы в программе, что может быть более удобным способом их настройки, поскольку вы можете изменить их для каждой машины.

Это лишает меня возможности справиться с этим должным образом.

Это делает невозможным для вас справиться с этим в том же процессе. Вы можете справиться с этим просто отлично, запустив обработку изображения в фоновом режиме.

Лично я считаю, что в любом случае использование Imagick на сервере, доступ к которому напрямую осуществляется через веб-браузеры, является чокнутым. Гораздо безопаснее запускать его как фоновую задачу (управляемую чем-то вроде http://supervisord.org/) и связь с этой фоновой задачей через очередь заданий, которые необходимо обработать.

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

Источник — я поддерживаю расширение Imagick, и недавно я добавил это в readme Imagick:

Безопасность

Расширение PHP Imagick работает, вызывая библиотеку ImageMagick.
Хотя разработчики ImageMagick стараются избегать ошибок, это
неизбежно, что некоторые ошибки будут присутствовать в коде. ImageMagick
также использует много сторонних библиотек, чтобы открывать, читать и манипулировать
файлы. Авторы этих библиотек также заботятся, когда пишут
их код. Однако все делают ошибки и неизбежно
присутствуют некоторые ошибки.

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

1) Не запускайте Imagick на сервере, который напрямую доступен из
вне вашей сети. Лучше либо использовать его в качестве фона
Задача, используя что-то вроде SupervisorD или запустить его в отдельном
сервер, который не имеет прямого доступа в интернет.

Это сделает хакерам трудным использование ошибки, даже
если он должен существовать в библиотеках, которые использует ImageMagick.

2) Запустите его как процесс с очень низкими привилегиями. Как можно больше
файлы и системные ресурсы, доступные для скрипта PHP, который Imagick
вызывается из должен быть заблокирован.

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

5

Другие решения

Начиная с ImageMagick-6.9.0-1, добавлены ограничения ресурсов «ширина» и «высота». В командной строке используйте «-limit width 32000» и т. Д. PNG-декодер ImageMagick будет работать без распаковки изображения, если ширина или высота превышает указанный предел.

Декодер PNG не будет пытаться распаковывать изображения, ширина или высота которых превышает пределы.

Ресурс «area» доступен в более ранних версиях ImageMagick (и Imagick); однако декодер PNG не отклоняет изображения, основываясь на пределе «площади» (см. комментарий Danack).

В версиях ImageMagick ранее 6.9.0 ограничения ширины и высоты берутся из libpng и зависят от версии libpng. В текущих версиях libpng (1.0.16 и новее, 1.2.6 и новее, 1.5.22 и новее и 1.6.17 и новее) установлены ограничения в 1 000 000 столбцов и ширины. В версиях с 1.2.0 по 1.2.5, с 1.5.0 по 1.5.23 и с 1.6.0 по 1.6.16 ограничения составляли по умолчанию 2,7 млрд строк и столбцов.

Ищите RESOURCETYPE_AREA в Imagick (я не вижу _WIDTH или _HEIGHT в руководстве, на которое вы ссылались, поэтому либо Imagick, либо его руководство необходимо обновить). Так что постарайтесь

IMagick::setResourceLimit(IMagick::RESOURCETYPE_AREA , 100M);

установить предел в 100 мегапикселей. Надеемся, что некоторые будущие версии Imagick будут поддерживать RESOURCETYPE_WIDTH и RESOURCETYPE_HEIGHT, чтобы обеспечить лучшее решение для уязвимости декомпрессионной бомбы. Посмотрите ответ Danack о настройке их с текущей версией IMagick.

3

все, что я получаю, является ошибкой сегментации, никакие исключения не брошены

Я предполагаю, что ошибка вашего сегмента в том, что ресурсы слишком малы для работы ImageMagick (и связанных с ним делегатов). Значение ресурса указывается в байтах, а не в мегабайтах.

Imagick делает бросить исключение, если ресурс достигнут. Обычно что-то вроде …

«ресурс кеша исчерпан«

Декомпрессионные бомбы или Zip-бомба, чрезвычайно трудно идентифицировать. Чем вы занимаетесь ping-изображение изображения и установка лимитов ресурсов — правильный путь действий. Я бы в общих чертах обозначил решение как …

// Define limits in application settings, or bootstrap (not dynamically!)
define('MY_MAGICK_MEMORY_LIMIT', 5e+8);
// Repeat for AREA, DISK, & etc.

// In application
$image = new Imagick(); // allocate IM structrues
// Set limits on instance
$image->setResourceLimit(Imagick::RESOURCETYPE_MEMORY, MY_MEMORY_LIMIT);
// Repeat for RESOURCETYPE_AREA, RESOURCETYPE_DISK, & etc.

$filename = 'input.png';
if($image->ping($filename)) {
// Validate that this image is what your expecting
// ...
try {
$image->read($filename); // <-- Bomb will explode here
$image->resizeImage(320,240,Imagick::FILTER_LANCZOS,1);
} catch( ImageickException $err ) {
// Handle error
}
}
unset($image)

Если вы не доверяете декомпрессии, вы можете использовать Imagick :: getImageCompression во время проверки ping проверить, какое сжатие требуется для изображения. Тип сжатия будет целым числом, которое будет соответствовать следующему перечислению …

typedef enum
{
UndefinedCompression,
B44ACompression,
B44Compression,
BZipCompression,
DXT1Compression,
DXT3Compression,
DXT5Compression,
FaxCompression,
Group4Compression,
JBIG1Compression,
JBIG2Compression,
JPEG2000Compression,
JPEGCompression,
LosslessJPEGCompression,
LZMACompression,
LZWCompression,
NoCompression,
PizCompression,
Pxr24Compression,
RLECompression,
ZipCompression,
ZipSCompression
} CompressionType;

MagickStudio (написано на PERL) предлагает хорошую отправную точку для ограничения ресурса по умолчанию, и как они проверено против загруженные изображения (поиск Ping.)

1
По вопросам рекламы [email protected]