サーフェスイメージファイルが実際のイメージファイルであることを確認するスクリプト

サーフェスイメージファイルが実際のイメージファイルであることを確認するスクリプト

イメージファイル(つまり、.jpg、.bmpなどの一般的なイメージファイル拡張子を持つ)として表示されるディレクトリ内のすべてのファイルが実際にイメージファイルであることを確認するシェルスクリプトを作成したいと思います。

最近、ハッカーがディレクトリにファイルを作成し、それを.jpgファイルにマスクすることができる問題が発生しました。ディレクトリ内のすべてのファイルが実際のjpg、gif、またはpngファイルであることを確認するシェルスクリプトを作成したいと思います。

答え1

file完全に信頼できない入力を提供するときは、非常に注意して使用する必要があると思います。たとえば、RHEL 5 はfile次のことを認識します。

GIF87a
<?php
echo "Hello from PHP!\n";
?>

「GIF画像データ、バージョン87a、15370 x 28735」へ。 PHPインタプリタは問題なくこの入力を実行します。問題ありません」ローカルファイルには次のものが含まれています。「(LFI)問題。

第二に、file(でもstrings)実際に入力ファイルを解析して知りたいことを教えてくれます。これらパーサーが複雑そして問題がある

私はidentifyコマンドを提案しますイメージマジシャン母音。上記の簡単な例にだまされずに画像ファイルを正しく解析するのでfile

答え2

クイックファーストパスで、file画像キャプションをすばやく検出するコマンド:

if file "$FILE" |grep -qE 'image|bitmap'; then
  echo "File '$FILE' has the headers of an image"
fi

bitmap(識別するには2番目のシフトが必要です。Windows BMPファイルlibmagicは、ビットマップイメージを説明するために「イメージ」という単語を使用しないためです。 )

しかし、filePHPベースの偽の画像を使用してだますことができます。ブルース・エディガーの回答:

$ 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

Imagemagickを使用して識別

これイメージマジシャンスイートルームの特徴確認するCLI フロントエンドを持つスクリプトは、特定のイメージの一部のメタデータを返します。予想されるメタデータがないと失敗するため、この目的に適しています。

$ 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

多数のファイルをすばやくスキャンするには、両方のファイルを一緒に使用することをお勧めします。

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

(これを行うと、出力はidentifyOblivionにリダイレクトされます。終了コードでキャプチャされ、正常に完了したかどうかに興味があるためです。)

それでも欺くことはできません。

次の例では、最後に同じPHPコードを追加した単純な1x1白いGIFを使用しています。私はPHPを知らず、これが実際に実行されるかどうかはわかりませんが、PHPはマークアップ<?php … ?>外のすべてに文字通り「テキスト」を印刷するテンプレート言語なので、与えられたコードは次のように実行されると仮定します.ペイロードの前に少しのゴミがあります。

$ { echo 'R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBAD'
    echo 's8P3BocCBlY2hvICJIZWxsbyBmcm9tIFBIUCEiOyA/Pgo='
  } | base64 -d > fake2.gif
$ strings fake2.gif
GIF87a
;<?php echo "Hello from PHP!"; ?>
$ file fake2.gif
fake2.gif: GIF image data, version 87a, 1 x 1
$ identify fake2.gif
fake2.gif GIF 1x1 1x1+0+0 8-bit sRGB 2c 68B 0.000u 0:00.000

GIFアノテーションでもこれを行うことができるので、画像として完全に有効になります。

$ hd fake3.gif
00000000  47 49 46 38 39 61 01 00  01 00 80 00 00 ff ff ff  |GIF89a..........|
00000010  ff ff ff 21 fe 20 3c 3f  70 68 70 20 65 63 68 6f  |...!. <?php echo|
00000020  20 22 48 65 6c 6c 6f 20  66 72 6f 6d 20 50 48 50  | "Hello from PHP|
00000030  21 22 3b 20 3f 3e 00 2c  00 00 00 00 01 00 01 00  |!"; ?>.,........|
00000040  00 02 02 44 01 00 3b                              |...D..;|
00000047

私はGIFを選択して対応するコメントシステムを利用しましたが、単に画像の後ろにペイロードを接続するだけでこの検出技術をバイパスすることができます。欺くよりも難しくfile(実装に応じて)可能証拠を残してください(画像のジャンク)。

答え3

@Adam Katzが一緒に書いたコマンドに従って、-qgrep出力を抑制するために使用されたオプションのために常に戻りコード0が提供されたため、システムが失敗し続けることがわかりました。これを削除すると機能しますが、認識コマンドの出力が画面全体に広がっていることを意味します。

私はデフォルトでXubuntu 22.04.1 LTSに付属のGNU bashバージョン5.1.16(1)リリース(x86_64-pc-linux-gnu)とGNU grep 3.7を使用しています。

私のソリューションは、テスト内で必要なコマンドを実行するAdamsのソリューションと同じように動作します。

[[ ( $(file "$file" | grep -E 'image|bitmap') != ""  ) \
&& ( $(identify $file | grep error) -eq 0 ) ]] \
&& echo "File $file appears to be an image" \
|| echo "File $file appears to be a fake"

Adamの投稿が私に役立つように、誰かに役立つことを願っています。

関連情報