3

(この質問への回答から:.rar, .zip files MIME Type)ほとんどの人が PHP で zip ファイルをapplication/ziporとしてチェックすることを知っていますapplication/octet-streamが、これについていくつか質問があります。

  • チェックするだけで安全ですかapplication/octet-streamapplication/octet-streamzipだけでなく、より多くのファイルタイプを説明するために使用できることを考えると!)。他の方法でもファイルをチェックできることはわかっていますが、すべてをできるだけシンプルに保つように努めるべきだと考えました
  • できるだけ多くの異なる実際の zip タイプを確認しようとしました。しかし、予期しない結果をもたらすものもあります。mime-type が である 1 を見つけましたがapplication/x-external-editor、PHP はそれを処理するのに問題があります (唯一のエラーは ですがWarning: ZipArchive::close() [ziparchive.close]: Invalid or unitialized Zip object) - これはどこかに文書化されていますか? x-PHP が対応できる実際の MIME タイプのリストはありますか?

編集

以下の質問に答えます。

  • を使用して MIME タイプをチェックしています$_FILES['fileatt']['type']が、 を使用しmime_content_type()ても同じ結果が得られます。異なる zip ファイルは、次のいずれかのようです: 'application/zip''application/x-compressed''application/x-zip-compressed'、。MIME タイプが であると検出されたときにエラーが発生した理由がわかりませんでした。'application/x-compressed''multipart/x-zip'application/x-external-editor
  • zip 拡張機能がインストールされており、アップロード時に zip ファイルからすべてのファイルを抽出しています。エラーを確認することは考えていませんでした。

また、よくわからない別のことも発見しました。PHPが次のように読み取るファイルで次のコードを使用するとapplication/x-external-editor

if($zip->open($_FILES[fileatt]['tmp_name'])===TRUE)
{
    echo "success";
} else {
    echo "error";
} 

「エラー」を出力しますが、ファイルタイプを次のようにチェックします

$res = $zip->open($_FILES[fileatt]['tmp_name']);
if($res)
{
    echo "success";
} else {
    echo "error";
} 

「成功」を出力します。このコードでは、ブール値は==ではなくを効果的に使用していると想定しています===が、なぜこれが違いを生むのでしょうか?

エラー:

$res = $zip->open($_FILES[fileatt]['tmp_name']);
if($res===TRUE)
{
    echo "success";
} else {
    echo $res;
} 

印刷19- どのエラー ( http://uk3.php.net/manual/en/ziparchive.open.php ) が 19 を参照していますか?!

4

1 に答える 1

3

MIME タイプは決して信用しないでください。これは、クライアントによって簡単に偽装される可能性があります。彼らはexeを提出し、必要に応じてMIMEタイプを与えることができtext/plainました.

すべての zip ファイルは、標準のローカル ファイル ヘッダー署名 (0x04034b50) で始まるため、ファイルの最初の 4 バイトが zip 署名バイトと一致することを確認できます。詳細については、PKZIP Appnoteを参照してください。

zip 拡張機能を有効にしている場合は、さらに進んで zip を開いて読み取って、完全に有効な zip ファイルであることを確認できます。

このようなものはうまくいきます:

$zip = zip_open('/path/to/file.zip');
if (is_int($zip)) {
    echo "Error $zip encountered reading the file, is it a valid zip?";
} else {
    echo "Thanks for uploading a valid zip file!";
}

zip_open正常に開かれた場合はリソースを返します。それ以外の場合は、ファイルの読み取り中に発生したエラーを表す整数を返します。

編集:いくつかの質問について詳しく説明するには:

About application/octet-stream: おっしゃる通り、非常にジェネリックなタイプです。これは、基本的にすべてのものである 8 ビット データを含むファイルを意味します。 application/zip事実上の標準の MIME タイプですが、一部のクライアントは、あなたが発見したように他の値を使用します。また、クライアントが使用するファイルの種類を簡単に偽装できるという事実を考えると、それは何でもapplication/zipかまいません$_FILES['fileatt']['type']

AFIK は、単にファイル拡張子を調べて、システム上のmime.typesファイルまたは PHP に組み込まれmime_content_type()た mime タイプにマップします。誰かがファイルに拡張子を付けたとしても、 . 特定の拡張子がファイル ヘッダーを調べる可能性があると思います。.zipexeapplication/zip

Zip::open()TRUEファイルが正常に開かれたかどうか、または整数のエラー コードを返します。したがって、はゼロ以外の整数を にキャストするため、==ゼロ以外の整数は を使用して true と評価されるため、エラーに対して誤検知が発生します。からのリターンをチェックする場合は、成功をチェックするために常に使用する必要があります。エラー コードの意味については、ページ下部のコメントを参照してください==TRUEZip::open$res === true

結論: 既に zip を解凍していると言ったので、MIME タイプに基づいて検証するのはそれほど面倒ではないかもしれませんが、代わりに、ファイルを開いて の戻り値に基づいて実行する方が簡単ですopen。true が返された場合、ファイルが有効な zip であることがわかります (もちろん、ファイルの後半にエラーがある可能性がありますが、少なくとも zip ファイルに似たものがアップロードされています)。

それがあなたを助けることを願っています。

于 2012-05-11T20:43:01.103 に答える