当前位置: 首页 > 知识库问答 >
问题:

如何使用ImageMagick防止图像炸弹?

赖浩荡
2023-03-14

我目前在PHP上使用Imagick库,并使用Image Magick的调整大小功能。我刚刚了解了减压炸弹以及ImageMagick是如何容易受到它的攻击的。

我已经检查了如何ping图像并验证图像的尺寸,而不实际将其加载到内存/磁盘中。限制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个答案

杨骁
2023-03-14

我得到的只是一个分段错误,没有抛出异常

我猜您的细分错误是因为资源设置太低,ImageMagick(和相关代理)无法运行。资源的值以字节为单位,而不是以兆字节为单位。

如果到达资源,Imagick会抛出异常。通常是类似于...

"缓存资源耗尽"

减压炸弹或拉链炸弹极难识别。通过ping-ing图像并设置资源限制所做的是正确的操作过程。我将大致概述一个解决方案,如。。。

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

如果您不信任解压缩,您可以在ping验证期间利用Imagick::getImageCompress来检查图像需要哪种压缩。压缩类型将是映射到以下枚举的整数...

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

卢深
2023-03-14

从ImageMagick-6.9.0-1开始,添加了“宽度”和“高度”资源限制。从命令行中,使用“-限制宽度32000”等。如果宽度或高度超过指定的限制,ImageMagick的PNG解码器将在不解压图像的情况下退出。

PNG解码器不会尝试解压缩宽度或高度超过限制的图像。

“区域”资源在ImageMagick(和Imagick)的早期版本中可用;但是PNG解码器不会基于“面积”限制拒绝图像(参见Danack的评论)。

在早于6.9.0的ImageMagick版本中,宽度和高度限制来自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版本中,默认情况下限制27亿行和列。

在Imagick中查找RESOURCETYPE_AREA(我在您引用的手册中没有看到_WIDTH或_HEIGHT,因此Imagick或其手册需要更新)。所以试试吧

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

设置100MegaPixel限制。希望Imagick的未来版本将支持RESOURCETYPE_WIDTH和RESOURCETYPE_HEIGHT,为解压炸弹漏洞提供更好的解决方案。请参阅Danack关于用当前版本的IMAGICK设置这些的回答。

乌学博
2023-03-14

设置“资源区域”限制仅设置图像不保存在内存中的大小,而是分页到磁盘的大小。如果您想使用该设置来实际限制可打开的最大大小映像,您还需要设置“资源磁盘”限制。

下面的代码正确地给出了从这里拍摄的图像炸弹的内存分配错误。

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

输出为:

异常:内存分配失败“”/图-100M-6000x6000。png'@error/png。c/MagickPNGErrorHandler/1630

如果要设置宽度和高度资源,并具有ImageMagick的版本

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

这些不必以编程方式设置,您可以通过随ImageMagick安装的policy.xml文件设置它们。ImageMagick读取该文件,如果程序中没有设置这些设置,则使用这些设置——这可能是更方便的设置方式,因为您可以根据每台机器更改它们。

这使我无法妥善处理它。

这使得你不可能在同一个过程中处理它。通过在后台任务中运行图像处理,您可以很好地处理它。

就我个人而言,我认为在一个由网络浏览器直接访问的服务器中使用Imagick是愚蠢的。将其作为后台任务运行(由类似http://supervisord.org/)以及通过需要处理的作业队列与后台任务通信。

这不仅解决了“糟糕的图像会破坏我的网站”的问题,还使监控资源使用变得更加容易,或者将图像处理转移到比网络前端服务器需要的CPU更快的机器上。

来源-我是Imagick扩展的维护者,最近我在Imagick自述中添加了以下内容:

安全

PHP扩展Imagick的工作原理是调用ImageMagick库。尽管ImageMagick开发人员非常小心地避免错误,但代码中不可避免地会出现一些错误。ImageMagick还使用许多第三方库来打开、读取和操作文件。这些库的编写者在编写代码时也很小心。然而,每个人都会犯错,不可避免地会有一些错误。

由于ImageMagick用于处理图像,因此黑客可能创建包含无效数据的图像,试图利用这些漏洞进行攻击。因此,我们建议如下:

1)不要在可从网络外部直接访问的服务器中运行Imagick。最好是使用它作为后台任务,使用类似于SupervisorD的东西,或者在不能在互联网上直接访问的单独服务器中运行它。

这样做会使黑客很难利用漏洞,即使ImageMagick使用的库中存在漏洞。

2) 将其作为非常低权限的进程运行。调用Imagick的PHP脚本可以访问的文件和系统资源应该尽可能地被锁定。

3) 在向用户显示图像文件之前,请检查图像处理的结果是否为有效的图像文件。在极不可能的情况下,黑客能够通过管道将任意文件传输到Imagick的输出,检查它是否是图像文件,而不是正在发送的应用程序的源代码,这是一种明智的预防措施。

 类似资料:
  • 问题内容: 有没有办法用javascript / jquery防止图像加载?我正在从带有图像的html列表构建幻灯片。因此,我想收集所有src数据,然后阻止加载图像。因此,稍后当用户真正需要图像时,我便会加载它。 我在Google上找到了一些延迟加载脚本,但找不到阻止图像加载的方式。 提前致谢。 Edit1: 从答案看来,不可能使用javascript来防止图像加载。 这是一个执行延迟加载的脚本。

  • 问题内容: 如果使用此代码,则div的圆角不会剪切图像(结果是图像的方形角覆盖了div的圆角): 有谁知道如何获得一个圆形的div来防止子图像溢出? 问题答案: 这可能会或可能不会在您遇到的情况下起作用,但请考虑使图像成为CSS背景。在FF3中,以下工作正常: 我不确定还有另一种解决方法-如果您对图像本身应用边框(例如,较深),则会遇到同样的方形角问题。 编辑: 尽管在“为图像添加边框”情况下,图

  • 问题内容: 有谁知道在不使用Javascript的情况下在Firefox中同时使图像不可拖动和不可选择的方法吗?似乎微不足道,但这是问题所在: 1)可以在Firefox中拖动并突出显示: 2)因此,我们添加了此内容,但是在拖动时仍可以突出显示图像: 3)因此,我们添加了此内容以解决突出显示问题,但是反直觉地, 图像再次变得可拖动。 很奇怪,我知道!使用FF 16.0.1 那么,有谁知道为什么添加“

  • 问题内容: 我正在Node.js(+ express 4)上开发一个Web应用程序,用户可以通过将其上载到服务器来设置其个人资料图像。我们已经限制了文件的模仿类型和最大文件大小,因此用户上传的png或jpeg图片不能超过200KB。 问题是我们想将上传的图片分辨率(服务器端)调整为200x200,以改善页面加载并节省磁盘空间。经过研究,所有答案都指向使用任何基于ImageMagick或Graphi

  • 问题内容: 如果使用“ fill_parent”或“ weight”拉伸视图或按钮,如何防止在ImageView或ImageButton中自动缩放位图? 例如,这将在屏幕顶部创建一个等距分布的4按钮工具栏时很有用,但是即使我使用scaleType =“ center”,按钮内部的图像也会不断拉伸,这应该避免根据文档缩放,但事实并非如此。 任何见解表示赞赏! 谢谢, 问题答案: 我发现使用andro

  • 问题内容: 我有一个可用作地图键的类型,但我想防止这种情况的发生。我以为如果该类型包含一个私有成员,则其他软件包将无法实现,但这似乎仍然可行。使类型不能用作映射键的最佳方法是什么? 问题答案: 我认为禁止将类型用作键没有任何好处。它只是一个可能会使用或可能不会使用的选项,其类型不会因为您禁止将其用作地图键而变得更好,更小或更快。 但是,如果您想这样做:规格:地图类型: 该比较操作符 ==和=必须为