我正在尝试在我的应用程序中实现附件,用户可以上传图像文件(png、jpg、jpeg(。我已经阅读了OWASP关于图像上传的建议,其中一个技巧是将输入图像转换为位图(只保留位图数据,并丢弃所有额外的注释(,然后将位图转换为您想要的输出格式。一个合理的方法是转换为PBM格式,然后转换为PNG。
图像保存为字节数组。
我正在尝试使用ImageIO库中的ImageTranscoder重写上传的图像。但我真的不确定它在做什么,是否所有可能的恶意代码都从图像中删除了,因为似乎只有元数据在被重写。
对于如何实现删除图像文件中所有可能的恶意代码的目标,有什么建议和最佳实践吗?
您不需要像PBM这样的中间文件格式,因为BufferedImage
(这是Java中表示内存中位图的标准方式(只是普通像素数据。您可以从编码的";任何东西";从解码位图到编码PNG。
你可以做你描述的最简单的方法是:
ImageIO.write(ImageIO.read(input), "PNG", output);
这是一个相当幼稚的代码,对于许多真实世界的文件来说会中断,或者可能只是默默地不输出任何内容。您可能希望至少处理最常见的错误情况,因此如下所示:
BufferedImage image = ImageIO.read(input);
if (image == null) {
// TODO: Handle image not read (decoded)
}
else if (!ImageIO.write(image, "PNG", output)) {
// TODO: Handle image not written (could not be encoded as PNG)
}
其他需要考虑的事项:以上将删除元数据中的恶意代码。然而,可能会有专门为DoS制作的图像(小文件解码为巨大的内存表示、TIFF IFD循环等等(。这些问题需要在用于各种输入格式的图像解码器中解决。但至少您的输出文件应该是安全的。
此外,恶意代码可能存储在ICC配置文件中,这些代码可能会转移到输出映像中。您可以通过强制将所有图像转换到内置的sRGB颜色空间,或者在没有ICC配置文件的情况下编写图像来避免这种情况。
PS:ImageTranscoder
接口适用于希望保留尽可能多的元数据的情况(这就是为什么它只有元数据的方法(,并允许将元数据从一种文件格式转换为另一种格式(有人可能会认为名称应该是MetadataTranscoder
(。