web-dev-qa-db-ja.com

PHPでアップロードされたファイルのファイルタイプを確認する方法

PHPウェブサイトで、彼らが示唆する唯一の本当のチェックは、is_uploaded_file()またはmove_uploaded_file()here を使用することです。もちろんあなたは通常、さまざまな理由から、ユーザーがどのような種類のファイルもアップロードすることは望ましくありません。

このため、私はしばしば「厳密な」MIMEタイプチェックを使用しました。もちろん、これは非常に欠陥があります。これは、多くの場合、MIMEタイプが間違っており、ユーザーがファイルをアップロードできないためです。偽造や変更も非常に簡単です。それに加えて、ブラウザとOSはそれぞれ異なる方法で処理します。

別の方法は、拡張子を確認することです。これはもちろん、MIMEタイプよりも簡単に変更できます。

画像のみが必要な場合は、getimagesize()のようなものを使用しても機能します。

他の種類のファイルはどうですか? PDF、Word文書、またはExcelファイル?それともテキストのみのファイルですか?

編集:mime_content_type または Fileinfo およびsystem( "file -bi $ uploadedfile ")は間違ったファイルタイプを提供しますが、他にどのようなオプションがありますか?

47
Darryl Hein

mime_content_type または Fileinfo をご覧ください。これらは組み込みのPHPファイルの内容を見てファイルのタイプを判別するためのコマンドです。上記の2ページのコメントも確認してください。他にも良い提案があります。

個人的には、本質的にsystem("file -bi $uploadedfile")であるものを使用して幸運に恵まれましたが、それが最善の方法であるかどうかはわかりません。

33
davr

私見、すべてのMIMEタイプのチェック方法は役に立たない。

MIMEタイプapplication/pdfを持つ必要があるとしましょう。標準メソッドはPDFヘッダーのようなもの(%PDF-またはそのようなsmth。)を見つけようとし、成功すると「OK、これはPDFファイルのようです」を返します。 。しかし、実際にはこれは何の意味もありません。 %PDF-1.4のみを含むファイルをアップロードすると、MIMEチェックに合格します。

ファイルに期待されるMIMEタイプがある場合、つまりMIMEタイプのチェックに常に合格します。そうでない場合、結果は未定義です。

14
Sudden Def

PHP 5.2と互換性のあるmime_content_typeを使用しました。これは、Fileinfo(PHP 5.3が必要です)もsystem()、これはプロバイダーによって無効になっています。たとえば、ファイルがテキストファイルかどうかを確認します。

if (strcmp(substr(mime_content_type($f),0,4),"text")==0) { ... }

「PHPディレクトリとサブディレクトリリスナーとファイルビューアーとダウンローダー」で完全な例を見ることができます: http://www.galgani.it/software_repository/index.php

2
if(isset($_FILES['uploaded'])) {
    $temp = explode(".", $_FILES["uploaded"]["name"]);

    $allowedExts = array("txt","htm","html","php","css","js","json","xml","swf","flv","pdf","psd","ai","eps","eps","ps","doc","rtf","ppt","odt","ods");

    $extension = end($temp);
    if( in_array($extension, $allowedExts)) {
       //code....

    } else {
        echo "Error,not Documentum type...";
    }
}

私はあなたが受け入れるファイルタイプの固定ホワイトリストを持っていると思います。

これらのタイプごとに、それらがその形式の有効な例であることを検証するために、さまざまな手法を使用する必要があります。

関連する質問が2つあります。

  • それは正しいタイプかもしれないように大まかに見えますか? (JPEGでは、前述のようにヘッダーを確認できます。多くのUnixベースの形式では、「マジッククッキー」を確認できます。)

  • 実際にそのタイプの有効な例ですか(たとえば、XMLに似た形式であれば、DTDに対して検証できます)。

回答は、Zipファイルと比較してPDFでかなり異なるため、各形式について、それぞれに個別の質問をする必要があると思います。

2
Oddthinking

これが関数file_mime_type iZendから:

function file_mime_type($file, $encoding=true) {
    $mime=false;

    if (function_exists('finfo_file')) {
        $finfo = finfo_open(FILEINFO_MIME);
        $mime = finfo_file($finfo, $file);
        finfo_close($finfo);
    }
    else if (substr(PHP_OS, 0, 3) == 'WIN') {
        $mime = mime_content_type($file);
    }
    else {
        $file = escapeshellarg($file);
        $cmd = "file -iL $file";

        exec($cmd, $output, $r);

        if ($r == 0) {
            $mime = substr($output[0], strpos($output[0], ': ')+2);
        }
    }

    if (!$mime) {
        return false;
    }

    if ($encoding) {
        return $mime;
    }

    return substr($mime, 0, strpos($mime, '; '));
}
1
iZend

PHP> = 5.3.0の場合、phpのfinfo_filefinfo_file )ファイルに関するファイル情報を取得する関数。

PHP <5.3.0の場合、システムのfileコマンドを使用してファイル情報を取得できます。

したがって、1つの関数で作成するだけです。

var_dump(mime_type("wiki templete.txt"));   // print string(10) "text/plain"

function mime_type($file_path)
{
    if (function_exists('finfo_open')) {
        $finfo = new finfo(FILEINFO_MIME_TYPE, null);
        $mime_type = $finfo->file($file_path);
    }
    if (!$mime_type && function_exists('passthru') && function_exists('escapeshellarg')) {
        ob_start();
        passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($file_path)), $return);
        if ($return > 0) {
            ob_end_clean();
            $mime_type = null;
        }
        $type = trim(ob_get_clean());
        if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
            $mime_type = null;
        }
        $mime_type = $match[1];
    }
    return $mime_type;
}

MimeTypes

0
Kris Roofe