2011-06-26 22 views
24

アップロードしたファイルが画像ファイル(例:png、jpg、jpeg、gif、bmp)か別のファイルかどうかを確認したいのですが、問題は、Uploadifyを使用してファイルをアップロードしていて、MIMEタイプを変更し、アップロードするファイルタイプに関係なくMIMEタイプとして「テキスト/ 8進」または何かを与えることです。アップロードされたファイルがMIMEタイプのない画像であるかどうかを確認するにはどうすればよいですか?

アップロードされたファイルは、画像が離れてPHPを使用してファイルの拡張子をチェックするからであるかどうかを確認する方法はありますか?

答えて

32

あなたは非画像上のサイズのためにゼロを返すgetimagesize()を使用することができます。

+2

私が知る限り、これは実際にこれを行うために受け入れられたハックです。彼らが存在すれば、より良い方法を聞くことに興味があります。 –

+0

ドキュメントは、7要素の配列を返します。どの要素がイメージかどうかを確認する必要がありますか? –

+0

は幅と高さがゼロと1です。 –

3

あなたは画像フォーマットを把握するmagic numberため、ファイルの最初の数バイトをチェックすることができます。

6

ファイルの先頭にあるマジックナンバーを確認すると、画像の種類を確認できます。

例:すべてのJPEGファイルは、「FF D8 FF E0」ブロックで始まります。ここで

magic numbers

+6

安全ではない、攻撃者は最初のバイトを「FF D8 FF E0」にしてから、実行可能なPHPコードを追加してください – Reacen

+2

Reacen、何も安全です、PHPコードJPGメタデータセクションを使用して有効なJPGファイルに注入することができます。 – rcode

3

詳細は画像の実際の型を取得するためにexif_imagetypeを使用してみてくださいです。ファイルは、それはエラーがスローされますが小さすぎると、それはそれを見つけることができない場合はfalse

37

を返します場合は対象についての私の考えは単純です:すべてアップロードされた画像は悪です。

悪意のあるコードを含む可能性があるだけでなく、特にメタタグのために、私は隠れたメタタグを使って保護された画像を見つけて、その著作権で遊ぶためにウェブを閲覧するクローラについて認識しています。おそらく少し編集的ですが、ユーザーがアップロードした画像が著作権問題を支配していないため、私はそれを真剣に考慮します。これらの問題を取り除くために

、私は体系的GDを使用してPNGにすべてアップロードされた画像を変換します。これは多くのメリットがあります:イメージは最終的な悪質なコードとメタタグからきれいです。私はすべてのアップロードされたイメージのための1つのフォーマットしか持っていません、私は自分の標準に合うようにイメージサイズを調整することができます... 画像が有効かどうかイメージを変換用に開くことができない場合(イメージ形式を気にしないimagecreatefromstringを使用)、イメージを無効と見なします。

簡単な実装は次のようになります。

function imageUploaded($source, $target) 
{ 
    // check for image size (see @DaveRandom's comment) 
    $size = getimagesize($source); 
    if ($size === false) { 
     throw new Exception("{$source}: Invalid image."); 
    } 
    if ($size[0] > 2000 || $size[1] > 2000) { 
     throw new Exception("{$source}: Too large."); 
    } 

    // loads it and convert it to png 
    $sourceImg = @imagecreatefromstring(@file_get_contents($source)); 
    if ($sourceImg === false) { 
     throw new Exception("{$source}: Invalid image."); 
    } 
    $width = imagesx($sourceImg); 
    $height = imagesy($sourceImg); 
    $targetImg = imagecreatetruecolor($width, $height); 
    imagecopy($targetImg, $sourceImg, 0, 0, 0, 0, $width, $height); 
    imagedestroy($sourceImg); 
    imagepng($targetImg, $target); 
    imagedestroy($targetImg); 
} 

はそれをテストするには:

header('Content-type: image/png'); 
imageUploaded('http://www.dogsdata.com/wp-content/uploads/2012/03/Companion-Yellow-dog.jpg', 'php://output'); 

これが受け入れ答えよりもハックの同じ種類があるので、これはまさにあなたの質問に答えていません、私はそれバグ検討する - しかし、私はあなたにUploadifyが本当にMIMEタイプを変更した場合、少なくとも

+0

私は@Alain Tiembloと全く同意します。「アップロードしたすべての画像をgdを使ってpngに体系的に変換します。これがセキュリティの方法です。 – PauloASilva

+0

確かに、私の同僚の一人は、アニメーションGIFを許可している場合、これはうまくいかないと指摘しました。真実。 –

+0

私はあなたに同意しますが...誰もがGIFを悪用できることを知っています([例](http://www.phpclasses.org/blog/post/67-PHP-security-exploit-with-GIF-images.html) ))。おそらく、GIFをサポートする必要がある場合は、フォーマットをフィルタリング/サニタイズするために多少の時間と労力を費やす必要があります。 – PauloASilva

5

:-)、それを使用するために私の理由を与えます。

  • finfo_open()
  • mime_content_type()
  • exif_imagetype():なぜならPHPで MIMEタイプベースの機能での作業からそのブロックの開発者が それは、全く意味がありません。

これは、ファイルの最初の6バイトに基づいてMIMEタイプを返す小さなヘルパー関数です。

/** 
* Returns the image mime-type based on the first 6 bytes of a file 
* It defaults to "application/octet-stream". 
* It returns false, if problem with file or empty file. 
* 
* @param string $file 
* @return string Mime-Type 
*/ 
function isImage($file) 
{ 
    $fh = fopen($file,'rb'); 
    if ($fh) { 
     $bytes = fread($fh, 6); // read 6 bytes 
     fclose($fh);   // close file 

     if ($bytes === false) { // bytes there? 
      return false; 
     } 

     // ok, bytes there, lets compare.... 

     if (substr($bytes,0,3) == "\xff\xd8\xff") { 
      return 'image/jpeg'; 
     } 
     if ($bytes == "\x89PNG\x0d\x0a") { 
      return 'image/png'; 
     } 
     if ($bytes == "GIF87a" or $bytes == "GIF89a") { 
      return 'image/gif'; 
     } 

     return 'application/octet-stream'; 
    } 
    return false; 
} 
2

finfo_fileでファイルを調べることはできませんか?

$finfo = finfo_open(FILEINFO_MIME_TYPE); 
$mimetype = finfo_file($finfo, $filename); //should contain mime-type 
finfo_close($finfo); 

この答えは、テストされていないが、Uploadifyフォーラムにthis forum discussionに基づいています。

また、finfoは"try to guess the content type and encoding of a file by looking for certain magic byte sequences at specific positions within the file"であるはずです。私の考えでは、これは、Uploadifyが間違ったMIMEタイプを指定していても動作するはずです。

関連する問題