bon*_*225 4 python malware python-imaging-library
我了解到 .PNG、.JPEG 和其他图像文件类型可能包含恶意软件。
我希望删除用户上传的图像中嵌入的潜在恶意软件。Python 中有没有一种方法可以从本质上“扁平化”图像,从而从本质上删除任何恶意内容?有点像您要截取图像的屏幕截图然后保存屏幕截图?或者也许存在一种不容易损坏的图像类型?
我已经将所有用户上传的内容托管在一个单独的域上,但我想知道是否可以更进一步。
在最简单的层面上,位图图像包含两件事:
元数据,即有关图像的信息,以及
像素数据,即像素颜色本身。
元数据包含关键信息,例如图像高度和宽度、通道数、每像素位数、图像的色彩空间及其压缩方式。它还包含可以说不太重要的补充信息,例如:
像素数据包含组成图像的像素网格的颜色(以及可能的任何透明度)。它经常被压缩。
请注意,以上只是简单的级别。我只提到了位图文件,而没有提及矢量文件(例如 SVG 文件),这些文件可能包含自己的一系列问题,例如“Billion Laughs DoS 攻击”,请参阅https://en.wikipedia.org/wiki/Billion_laughs_attack
另请注意,完全有可能将整个可执行程序附加到图像的末尾或中间,而不必扰乱图像读取器/显示程序,这些程序通常会忽略它们无法理解的信息,但会尽力理解使用他们做的零件。如果你想要一个例子,这里我用ImageMagick制作了一个红色图像,并将 128kB 的任意数据附加到末尾,并将其显示在 Mac 上的终端中,而macOS没有任何抱怨:
magick -size 1024x768 xc:red image.png # make red image
dd if=/dev/zero bs=128 count=1024 >> image.png # append 128kB of whatever I like - not actually malware in this case
open imge.png # use "xdg-open" on Linux
Run Code Online (Sandbox Code Playgroud)
另请注意,可以使用隐写术嵌入其他信息,例如劫持每个像素的最低有效位并使用它来传达消息或携带一些意外的有效负载,例如恶意软件或水印。由于它是最低有效位,因此通常在视觉上难以察觉。
所以,现在的问题是你希望做出什么样的权衡,或者换句话说,“你有多偏执?” 您决定从图像中删除的信息越多,您就越有可能无意中丢失以后需要的一些信息。如果剥离 EXIF 数据,您将不再知道图像是何时、何地或由谁拍摄的。如果剥离 ICC 颜色配置文件,您的图像在某些查看器中可能会显得褪色、过饱和或呈绿色。如果您剥离 IPTC 信息,并且合同要求您保留该信息,则可能会构成许可侵权。如果您删除地理参考信息,您的数据可能会变得毫无用处。如果删除注释,您可能会丢失屏蔽信息、版权或标签信息。如果将格式从 PNG/TIFF/GIF 更改为 JPEG,您将失去透明度和准确性。如果从 TIFF 更改为 PNG,您将失去存储 32 位、64 位或浮点数据以及超过 4 个通道的能力。如果从 JPEG 更改为 PNG,您可能会无意中使文件变大数十或数百倍。
因此,您可以采取的最偏执的操作几乎是将位图加载到内存中,以无法存储任何其他像素数据(例如 PPM 或原始 RGB(A) 字节)并将其重新保存为 JPEG 或 PNG。这将丢弃所有 EXIF/IPTC/地理数据和注释以及图像末尾或中间附加的任何无关数据。如果您想要一个具体的示例,您可以在终端中使用以下ImageMagick命令:
magick input.jpg -strip ppm:- | magick ppm:- result.jpg
Run Code Online (Sandbox Code Playgroud)
如果您使用 PIL/Pillow 和 Python,您可以这样做:
from PIL import Image
import numpy as np
# Load image
im = Image.open('image.jpg')
# Convert to format that cannot store IPTC/EXIF or comments, i.e. Numpy array
na = np.array(im)
# Create new image from the Numpy array and save
result = Image.fromarray(na).save('clean.jpg')
Run Code Online (Sandbox Code Playgroud)
如果您的图像是 PNG 格式,那么您就会增加复杂性 - 它可能是调色板图像,并且可能具有 Alpha/透明度信息,您可能希望保留它。这可能看起来像这样:
from PIL import Image
import numpy as np
# Load image
im = Image.open('image.png')
# Convert to format that cannot store IPTC/EXIF or comments, i.e. Numpy array
na = np.array(im)
# Create new image from the Numpy array
result = Image.fromarray(na)
# Copy forward the palette, if any
palette = im.getpalette()
if palette != None:
result.putpalette(palette)
# Save result
result.save('clean.png')
Run Code Online (Sandbox Code Playgroud)
如果您需要保留一些元数据,则需要考虑其他选项。