私は人々がヘルプチケットを記入できるPHPのウェブサイトを持っています。チケットのスクリーンショットをアップロードできます。gif、psd、bmp、jpg、png、tifのアップロードを許可します。アップロードを受信すると、PHPスクリプトはファイル拡張子を無視します。MIME情報のみを使用してファイルタイプを識別します。これらのファイルタイプの場合、ファイルの最初の12バイト内に常に格納されます。
誰かがいくつかのGIFをアップロードしましたが、ブラウザで表示すると、ブラウザはそれが無効であると言って、私のウイルススキャナーはそれが注射(またはそのようなもの)であると私に警告しました。これらのGIFを含むzipファイルについては、以下を参照してください。
ヘッダー情報をチェックするだけでは十分ではないと思います。画像は完全に有効である可能性があると聞きましたが、エクスプロイトコードも含まれています。
だから私は2つの基本的な質問があります:
- 誰かが(有効なGIF MIMEタイプを維持しながら)GIFに悪いものを注入した方法を知っていますか?これを知っていれば、アップロード時に確認できるかもしれません。
- 誰かがこのようなファイルをアップロードするのを防ぐにはどうすればよいですか?
- 共有ホスティングを使用しているため、サーバー側のウイルススキャナーをインストールできません。
- オンラインのウイルススキャンWebサイトに情報を送信するのは遅すぎる可能性があります。
- これらをチェックするPHPクラスを使用して自分自身をチェックする方法はありますか?
- GDを使用した画像のサイズ変更は、有効でない場合は失敗しますか?それとも、エクスプロイトはすり抜けてサイズ変更された画像に含まれるのでしょうか?それが失敗した場合、それが理想的です。なぜなら、サイズ変更をテクニックとして使用して、それらが有効かどうかを確認できるからです。
更新:皆さん、これまでのところ返信していただきありがとうございます。アップロードされたGIFをサーバーで検索しようとしています。見つけたらこの投稿を更新します。
更新2:興味のある人のためにGIFを見つけました。パスワード「123」で暗号化したzipファイルに入れました。ここにあります(このホスティングサイトには複数の[ダウンロード]ボタンがあることに注意してください。そのうちのいくつかは広告用です)http://www.filedropper.com/badgifs。5060.gifと呼ばれるものは、私のアンチウイルスによってトロイの木馬(TR / Graftor.Q.2)としてフラグが立てられています。これらのファイルは、最初の12バイトのMIMEチェックを実装する前にアップロードされたことに注意してください。だから今、私はこれらの特定のもののために安全です。しかし、正しいMIMEタイプの背後に隠れているエクスプロイトを検出する方法を知りたいのです。
重要な説明: 私は、これらのファイルをダウンロードしてそれらを見るPCへのリスクについてのみ懸念しています。 ファイルは私のサーバーにとってリスクではありません。それらは実行されません。それらは、拡張子が「.enc」のクリーンな名前(16進ハッシュ出力)を使用して保存され、fwriteフィルターを使用して暗号化された状態でディスクに保存します。
// Generate random key to encrypt this file.
$AsciiKey = '';
for($i = 0; $i < 20; $i++)
$AsciiKey .= chr(mt_rand(1, 255));
// The proper key size for the encryption mode we're using is 256-bits (32-bytes).
// That's what "mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)" says.
// So we'll hash our key using SHA-256 and pass TRUE to the 2nd parameter, so we
// get raw binary output. That will be the perfect length for the key.
$BinKey = hash('SHA256', '~~'.TIME_NOW.'~~'.$AsciiKey.'~~', true);
// Create Initialization Vector with block size of 128 bits (AES compliant) and CBC mode
$InitVec = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
$Args = array('iv' => $InitVec, 'key' => $BinKey, 'mode' => 'cbc');
// Save encoded file in uploads_tmp directory.
$hDest = fopen(UPLOADS_DIR_TMP.'/'.$Hash.'.enc', 'w');
stream_filter_append($hDest, 'mcrypt.rijndael-128', STREAM_FILTER_WRITE, $Args);
fwrite($hDest, $Data);
fclose($hDest);