ファイルの実際の拡張子/タイプをプログラムで判断するにはどうすればよいですか?
-
20-08-2019 - |
質問
私はサーバーへのユーザーのアップロードを処理するスクリプトに取り組んでいますが、追加のセキュリティ層として次のことを知りたいと思っています。
ファイルの実際の拡張子/ファイルタイプを検出し、別の拡張子でマスクされた別のファイルタイプではないことを確認する方法はありますか?
各タイプ/拡張子にバイトスタンプまたは何らかの一意の識別子はありますか?
誰かがアップロードしているファイルに別の拡張子を適用していないことを検出できるようにしたいと考えています。
ありがとう、
解決
そうでもない、ノーます。
あなたは、各ファイルの最初の数バイトを読み、既知のファイルタイプの有限集合のヘッダとしてそれを解釈する必要があります。ほとんどのファイルは個別のファイルヘッダ、最初の数バイトやMP3の場合は最初の数キロバイト単位でのメタデータのいくつかの並べ替えを持っています。
あなたのプログラムは、単にあなたの受け入れファイルタイプごとにファイルを解析しようとする必要があります。
私のプログラムのために、私は、try-catchブロックではImageMagickにアップロードされた画像を送信し、それが吹くまでなら、私はそれが悪いイメージだったと思います。私は一般的攻撃ベクトルで外部プログラム、に任意の(ユーザーが供給)は、バイナリデータをロードしていますので、これは、安全でないとみなされるべきです。ここで、私は自分のシステムに何もしないためにはImageMagickを信頼しています。
私はあなたがどんな攻撃ベクトルを避けるために、使用する予定の重要なファイルタイプ用に独自のハンドラを書くことをお勧めします。
編集:私はあなたのためにこれを行うにはいくつかのツールがあるPHPで見る
また、MIMEタイプは、ユーザーのブラウザがするファイルを主張するものです。これらを読んで、あなたのコードでそれらに基づいて行動することが便利と便利ですが、誰がする偽のMIMEヘッダ簡単にあなたが悪いのファイルを送信するためには、安全な方法ではありません。これは、PNGにbarfingからJPEGを期待し、あなたのコードを維持するために、フロントラインの防衛の一種だが、誰かが.exeファイルにウイルスを埋め込み、それJPEGという名前の場合は、MIMEタイプを偽装されていない理由はありません。
他のヒント
PHPは、使用しているPHPのバージョンに応じて、そのMIMEタイプを決定するために、ファイルの内容を読み取るいくつかの方法があります
のFileinfoの機能を見てくださいのあなたは、PHP 5.3を実行している場合+
$finfo = finfo_open(FILEINFO_MIME);
$type = finfo_file($finfo, $filepath);
finfo_close($finfo);
また、古いバージョンのために mime_content_type のを確認します。
$type = mime_content_type($filepath);
あなたが本当に安全になるようにしたい場合は、単にファイルの種類を確認することは十分ではないことに注意してください。誰かが、例えば、一般的なレンダラの脆弱性を悪用し、有効なJPEGファイルをアップロードすることができます。これを防ぐために、あなたはよく維持ウイルススキャナが必要になります。
PHP には、 スーパーグローバル $_FILES サイズやファイルタイプなどの情報を保持します。型は拡張子ではなく、ある種のヘッダーから取得されているように見えますが、私は間違っている可能性があります。
その例は上にあります w3schools サイト.
機会があれば騙せるかどうか試してみたいと思います。
アップデート:
おそらく他の誰もがこれを知っていたでしょうが、$_FILES はだまされる可能性があります。次のようにして判断できました。
$arg = escapeshellarg( $_FILES["file"]["tmp_name"] );
system( "file $arg", $type );
echo "Real type: " . $type;
基本的にはUnixのものを使用します ファイル 指示。おそらくもっと良い方法があると思いますが、私はしばらく PHP を使っていません。私は通常、可能であればシステムコマンドの使用を避けます。
それはまだ偽造することができます。私はあなたがいないことを保証する(またはしない)が、自動的にサーバにアップロードされたファイルを実行します。
私はまた、ウイルス/スパイウェアスキャナを持っている、そしてそれはあなたのために仕事をさせます。
あなたは拡張子を変更した場合は、タイプをMIME与え、コードの下に使用することができ、その後も
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo $mime = finfo_file($finfo, $_FILES['userfile']['tmp_name']);
finfo_close($finfo);
Windowsユーザー:ただのphp.iniを編集し、この行のコメントを外します:
extension=php_fileinfo.dll
新しいphp.iniのを有効にするためにApacheを再起動してください。
の* nix、ファイルの最初の2バイトで(「マジックナンバー」を参照)を説明します。 Windowsでは、...時々、これは(「ヘッダ情報」)trueになります。それは、最終的には、あるO.S.依存ます。
一般に実行可能ファイルは、最初のバイトの「署名」を有します。私はそれは難しいけれども、実際にファイルの種類が本当に何であるかを確認するために見つけます。
あなたはどのようなファイルの種類を期待していますか?たぶん、あなたはそれはあなたが期待して他のすべてを拒絶するものに準拠していることを確認することができます。
その他は、すでに私は正解だと思うのFileInfoを、言及しているが、私は、これは念のためにあなたには、いくつかの理由のために1つを使用することはできません追加します。ほとんど(すべて?)* nixのディストリビューションと呼ばれるコマンドをfile
含まれ、そのファイルが出力されますその型で実行した場合。それは、人間が読める形式(デフォルト)またはMIMEタイプに出力するスイッチがあります。あなたのスクリプトがアップロードされたファイル上で、このプログラムを起動し、結果を読んで持つことができます。繰り返しますが、これは好ましいアプローチではありません。 Windowsであれば、このユーティリティは、Cygwinのを介して利用されます。
単に十分なMIMEタイプをチェックしていますか? 私は、ファイルに拡張子を変更すると、それはMIMEタイプです変化しないと仮定しています!
MIMEは、ここで行くために十分強力な指標を入力しますか?
これまでの回答のすべてをお寄せいただきありがとうございます。
チェックのMIMEタイプだけで十分か?私はこの拡張子を変更するとファイルが変わりませんでMIMEタイプ?はMIMEタイプは、強い指標エルミタージュ国立美術館と。
この変化により契約内容の変更が出てくるんですが、それを使用します。
- を提供する場合は、投稿、ダウンロードそのものに関していかないんでを実行することを示しています。
- だが取り扱うwebサーバ、そしてその可能性を展望するとともにどのようにウェブサーバの実装が対象で、これらのコメントです。
- の場合は画像では表示は、対象者の画像図書館排除できます。だけます。
- ようなものpdfファイルに影響を与えないサーバーしたというだけでなく、コンピュータのアクセスするファイルです。
- ができ渡された関数のように"システム()"しているOSの挙動--そのなかで"ダブルクリックし、ファイルの拡張子がいても検討する。