How to prevent bombs from being displayed using ImageMagick?

I am currently using the Imagick PHP library and using Image Magick's resizing functions. I just learned about decompression bombs and how ImageMagick is vulnerable to it.

I checked how we can ping an image and check the dimensions of the image without actually loading it into memory / disk. It is also safer to limit the memory and disk limits of ImageMagick so that it doesn't just write a huge file to disk.

I read and I can do it with 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);

      

However, what happens is that after setting the disk and memory limit, if the image reaches that limit, all I get is a segmentation fault error, no exceptions are thrown. This makes it impossible to handle it correctly.

Update:

Here are the versions of the packages I am using:

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


source to share


3 answers


Setting the Resource Area limit only sets the size at which images are not stored in memory, but instead dumped to disk. If you want to use this option to actually limit the maximum size of the image that can be opened, you also need to set the "Disk Disk" limit.

The correct code below shows the memory allocation error for the images they made.

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";
}

      

Output:

Exception: Memory failure failed .. / picture -100M-6000x6000.png'@error/png.c/MagickPNGErrorHandler/1630

If you want to set width and height resource and have ImageMagick version> = 6.9.0-1 you should be able to use values ​​directly from WidthResource = 9, HeightResource = 10

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

      



These programs do not need to be installed programmatically, you can install them via the policy.xml file installed with ImageMagick. ImageMagick reads this file and uses these parameters if none are specified in the program, which may be a more convenient way to configure them, since you can change them to one machine.

This makes it impossible to handle it correctly.

This prevents you from handling it in the same process. You can handle this simply by doing image processing in a background job.

Personally, I think using Imagick on a server that is directly accessed by web browsers is nuts anyway. It is much safer to run it as a background task (managed by something like http://supervisord.org/ ) and communicate with this background task through the queue to be processed.

This not only solves the problem with "bad images", but also makes it much easier to monitor resource usage or offloads image processing to a computer with a faster processor than the web interface server is needed.

Source - I maintain the Imagick extension and I recently added it to the Imagick readme file:

Safety

The PHP Imagick extension works by calling the ImageMagick library. While the ImageMagick developers try to avoid bugs, it is inevitable that some bugs will be present in the code. ImageMagick also uses many third party libraries to open, read and manipulate files. The writers of these libraries also take care when writing their code. However, everyone makes mistakes and inevitably some mistakes are present.

Since ImageMagick is used for image processing, it is possible for hackers to create images containing invalid data in order to exploit these errors. Therefore, we recommend the following:

1) Do not run Imagick on a server that is directly accessible from outside your network. Better to either use it as a background using something like SupervisorD or to run on a separate server that doesn't have direct internet access.

Doing so will make it harder for a hacker to exploit the bug, even if it exists in the libraries that ImageMagick uses.

2) Run it as a very low privileged process. As much as possible, the files and system resources available to the PHP script that Imagick is called from should be locked.

3) Check that the image processing result is a valid image file before displaying it to the user. In the extremely unlikely scenario, a hacker is able to transfer arbitrary files to the Imagick output, verifying that it is an image file and not the source code of your application being sent is a sensible precaution.

+5


source


Starting with ImageMagick-6.9.0-1, "width" and "height" resource limits have been added. From the command line use "-boundary width 32000" etc. ImageMagick PNG decoder will exit without image decompression if the width or height exceeds the specified limit.

The PNG decoder will not attempt to decompress images whose width or height exceeds the limits.

The "area" resource is available in earlier versions of ImageMagick (and Imagick); however, the PNG decoder does not reject images based on the "area" limit (see Danack's comment).

In versions of ImageMagick earlier than 6.9.0, the width and height restrictions are taken from libpng and depend on the libpng version. Current versions of libpng (1.0.16 and later, 1.2.6 and later, 1.5.22 and later, and 1.6.17 and later) impose 1000,000 column and width limits. In versions 1.2.0 to 1.2.5, 1.5.0 to 1.5.23, and 1.6.0 to 1.6.16, the default was 2.7 billion rows and columns.



Look for RESOURCETYPE_AREA in Imagick (I don't see _WIDTH or _HEIGHT in the manual you referenced, so Imagick or its manual needs to be updated). So try

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

      

set a limit of 100 megapixels. Hopefully some future versions of Imagick will support RESOURCETYPE_WIDTH and RESOURCETYPE_HEIGHT to provide a better solution to the decompression bomb vulnerability. See Danack's answer for setting them up with the current version of IMagick.

+3


source


all i get is a segmentation fault, no exceptions are thrown

I am guessing your segment error is because resources are too low for ImageMagick (and associated delegates) to work. The resource value is in bytes, not megabytes.

Imagick throws an exception if the resource is reached. Usually something like ...

"cache resource exhausted "

Decompression bombs, or Zip Bombs , are extremely difficult to identify. What you are doing ping

is an image, and limiting resources is the right course of action. I would roughly describe the solution as ...

// 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)

      

If you don't trust decompression, you can use Imagick :: getImageCompression while pinging to check what compression is required for the image. The compression type will be an integer which will appear in the following enumeration ...

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 (written in PERL) offers a good starting point for default resource constraints and how they are tested against uploaded images (search ping

.)

+1


source







All Articles