判断文件是否为图像的脚本

bre*_*son 5 shell-script files images

我想创建一个 shell 脚本来检查以确保目录中的所有文件都是图像文件。

我们最近遇到了一个问题,黑客能够在目录中生成一个文件并将其屏蔽为 .jpg 文件。我想创建一个 shell 脚本来检查目录中的所有文件,以确保它们是真正的 jpg、gif 或 png 文件。

Bru*_*ger 8

我认为file在提供完全不受信任的输入的情况下使用时要非常小心。例如,RHEL 5file将识别这一点:

GIF87a
<?php
echo "Hello from PHP!\n";
?>
Run Code Online (Sandbox Code Playgroud)

如“GIF 图像数据,版本 87a,15370 x 28735”。PHP 解释器执行该输入没有问题。没有麻烦是“本地文件包含”(LFI)问题的基础。

其次,file(甚至strings)实际上解析输入文件来告诉你你想知道什么。这些解析器很复杂并且有问题

我将建议identify使用ImageMagick套件中的命令。它不会被我上面的简单示例所迷惑,它只会正确解析图像文件,因此与file.


Ada*_*atz 7

作为快速的第一遍,该file命令可以快速检测图像标题:

if file "$FILE" |grep -qE 'image|bitmap'; then
  echo "File '$FILE' has the headers of an image"
fi
Run Code Online (Sandbox Code Playgroud)

bitmap如果您想识别Windows BMP 文件,则需要第二个替代项,因为 libmagic 不使用“图像”一词来描述位图图像。)

但是,我们可以file利用Bruce Ediger 的回答中基于 PHP 的假图像来欺骗:

if file "$FILE" |grep -qE 'image|bitmap'; then
  echo "File '$FILE' has the headers of an image"
fi
Run Code Online (Sandbox Code Playgroud)

使用 Imagemagick 识别

ImageMagick的套房有一个标识使用CLI前端,将返回给定的图像上的一些元数据的脚本。当预期的元数据不存在时它会失败,因此它非常适合此目的:

$ echo 'GIF87a<?php echo "Hello from PHP!"; ?>' > fake.gif
$ file fake.gif && echo image detected || echo no image detected
fake.gif: GIF image data, version 87a, 16188 x 26736
image detected
Run Code Online (Sandbox Code Playgroud)

为了更快地扫描大量文件,我建议将两者放在一起:

if file "$FILE" |grep -qE 'image|bitmap' \
&& ! identify "$FILE" >/dev/null 2>&1; then
  echo "File '$FILE' is a fake image!"
fi
Run Code Online (Sandbox Code Playgroud)

(这会将 的输出重定向identify到遗忘中,因为我们只关心它是否能够成功完成,这由其退出代码捕获。)

即使这样仍然可以被欺骗

以下示例使用简单的 1x1 白色 GIF,并在末尾添加了相同的 PHP 代码。我不知道 PHP,我不确定这是否会实际运行,但由于 PHP 是一种模板语言,它将文字“文本”打印到其<?php … ?>标签之外的任何内容,我假设这将按原样运行给定的代码,在有效载荷之前只有一些垃圾。

$ identify fake.gif && echo image detected || echo no image detected
identify-im6.q16: negative or zero image size `fake.gif' @ error/gif.c/ReadGIFImage/1402.
no image detected
Run Code Online (Sandbox Code Playgroud)

这也可以通过 GIF 注释来完成,以作为图像完全有效:

if file "$FILE" |grep -qE 'image|bitmap' \
&& ! identify "$FILE" >/dev/null 2>&1; then
  echo "File '$FILE' is a fake image!"
fi
Run Code Online (Sandbox Code Playgroud)

我选择了 GIF 并利用了它的评论系统,但是在任何图像之后连接有效负载也应该可以绕过这种检测技术。这只是比愚弄更难,file并且(取决于实现)它可能会留下一些证据(图像中的垃圾)。