【问题标题】:Verify sane image dimensions in Java without ImageMagick or ImageIO在没有 ImageMagick 或 ImageIO 的情况下验证 Java 中的正常图像尺寸
【发布时间】:2015-11-29 08:07:46
【问题描述】:

我有一个用 ImageMagick 处理图像的东西。 ImageMagick 有一个可重现的错误,导致它或多或少地将系统锁定在某些错误的大图像上:

https://hackerone.com/reports/390

为了避免这种情况,我在将图像发送到 ImageMagick 之前使用 ImageIO 来加载图像,因为 ImageIO.read() 在发现荒谬的像素数时会爆炸(它会抛出异常消息:“width*高度 > Integer.MAX_VALUE!")。

问题在于 ImageIO 不像 ImageMagick 那样容忍损坏或格式不正确的图像,我不想追究和处理 ImageMagick 可以很好地处理的已知和未知边缘情况。

我希望在不使用 ImageMagick 的加载或 ImageIO.read() 的情况下验证 JPEG、PNG、TIF、ICO 和 GIF 图像的合理尺寸。如果需要,我可以限制为 50 MP。

【问题讨论】:

  • 而 ImageMagick 的 ping 方法对你不起作用?
  • @emcconville 虽然我自己肯定更喜欢使用 ImageIO 而不是 ImageMagick,但我认为只选择一个库更有意义。 ImageMagick 的 ping 听起来应该可以完成这项工作。
  • 我同意@haraldK。也许OP可以澄清。您是在寻求构建容错系统的建议,还是寻求消除此类库依赖的技术?正如 haraldK 指出的 in his answer,构建自己的将是一项巨大的工作,并且仍然容易受到其他 DoS 攻击(例如图像数据中的 zipbombs 阻碍)。
  • ImageMagick 的 ping(加载基本文件信息)在这里没有帮助,因为它以通常的方式确定图像的尺寸。我的目标是防止 ImageMagick 在加载此处引用的“有毒”图像时锁定系统:Dubiously Large Image
  • 目前依赖ImageMagick及时替换的太多了。

标签: java image imagemagick javax.imageio


【解决方案1】:

使用 ImageIO 获取ImageReader,然后查询ImageReader 的宽度和高度,而不实际加载图像。

try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
    Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
    if (readers.hasNext()) {
        ImageReader reader = readers.next();
        reader.setInput(stream);

        // Get width/height of first image in file
        // (alternatively, use getNumImages() and loop over all images)
        int w = reader.getWidth(0);
        int h = reader.getHeight(0);

        if (w * h > SANE_MAX_SIZE) {
            // TODO: Handle image too large
        }
    }
}

不过,您可能仍然会遇到 ImageIO 容错性较低的问题。

我建议使用我自己的 TwelveMonkeys ImageIO 插件(支持 TIFF、ICO 并添加更好的 JPEG 支持),但我想您也可以使用 Apache Commons Imaging 或其他库。

最后的手段是自己编写代码来解析所有这些格式。但我认为,与现有解决方案相比,错误更少的可能性很小,无需您付出相当大的努力...... ;-)

【讨论】:

  • 恐怕这不会捕捉到这里提到的“有毒”图像:hackerone-attachments.s3.amazonaws.com/production/000/000/128/… 通过 ImageReader 报告的尺寸仍然正常,ImageMagick 仍然会尝试为 4000 兆像素分配内存加载中。
  • 你所说的“报告为理智”是什么意思?此图像为 64250 x 64250 像素。代码中的wh 将反映这一点,但它不会报告任何内容。我不知道你对“理智”的限制是什么,这就是为什么我把它留给你来实现,但是一旦你知道了限制就很容易做到。
  • @Tremelune 更新了答案,让事情变得更加清晰。
  • 有趣。我一定是第一次搞砸了我的测试,因为我没有看到报告为 64250 的宽度和高度。再看一遍,太阳和十二只猴子 JPEGReaders 都正确地报告了这一点。
猜你喜欢
  • 2010-12-06
  • 2022-11-18
  • 2014-03-19
  • 2013-02-28
  • 1970-01-01
  • 2012-05-22
  • 2018-09-22
  • 1970-01-01
  • 2012-01-29
相关资源
最近更新 更多