web-dev-qa-db-ja.com

アップロードされた実行可能ファイルのファイル拡張子を.pngに変更すると、安全になりますか?

私の同僚には、ユーザーが特定のサイズ内のものをアップロードできる個人用Webサイトがあります。

しかし、実際のアップロードの前に、ファイル拡張子を確認します。

if ( $type == 'image/gif'){
  $ext = '.gif';
} elseif ( $type == 'image/jpeg'){
  $ext = '.jpg';
} elseif ( $type == 'image/png' ){
  $ext= '.png';
}  else {
  $ext = '.png';  
}

彼は私に、すべてのファイルの画像を作成することにより、サーバーに害を及ぼすことはできないと言います。

例えば ​​:

  evilscript.evil

になるだろう:

evilscript.png

そしてそれによって役に立たなくなる。彼の主張に真実はありますか?

34
Peter verleg

アップロードされたファイルが害を及ぼす主な方法は2つあります:実行される(スクリプトまたはバイナリとして)か、アプリケーションで実行/使用され、エクスプロイトを悪用する(アップロードされたMP3など)。プレーヤー、既知の弱点を悪用する)。

つまり、アップロード後のファイルの処理にすべて依存します。誰かがPerlスクリプトをアップロードできても、サーバーがアップロードされたファイルを実行しないか、Perlがインストールされていない場合、何も起こりません。一般に、アップロードしたファイルが実行または解釈されないようにすると、安全です。

ファイルの名前を変更しても、1つのことにのみ役立ちます。一部のオペレーティングシステムでは、一部のファイル拡張子が特定のアプリケーションにリンクされている場合があります。ファイルの名前を変更すると、リンクされたアプリケーションでファイルが開かなくなる可能性があります。ただし、システムと設定によっては、アップロードされたファイルが脆弱なアプリケーションで開かれる可能性があります。上記の例にとどまる:アップロードされたファイルがMP3プレーヤーで開かれた場合、ファイル名をsong.pngに変更しても、プレーヤーの弱点を悪用することができます(プレーヤーに独自のファイルがある場合を除く)チェックのレイヤー。例:.mp3ファイルのみを受け入れます)。

名前を変更しただけでは、名前が変更されたファイルは突然の画像ではありません。 Unixおよび類似のシステムでは、ファイルのタイプ/ MIMEタイプを分析するfileコマンドさえあります。

結論:私の目には、あなたができることが1つだけあります。セットアップでは、アップロードされたファイルで何ができ、何ができるかについて非常に具体的にしてください。これらのファイルを受け入れるライブラリ、拡張機能、またはアプリケーションは、常に最新バージョンに更新する必要があります。

49
Draugr

いいえ。ファイルの名前を変更してもセキュリティは向上しません。

すべてのファイルをイメージにすることによりサーバーに害を与えることはできないと彼は私に言っています。

たとえば、evilscript.evilはevilscript.pngになります。

evilscript.evilの名前をevilscript.pngに変更しても、画像にはなりません。 名前を変更するだけです。通常、ファイル名は関係ありません。これは、データのブロックに付けられた名前にすぎません。

アップロードされたスクリプトを実行できる場合は、その名前に関係なく実行できます。それができない場合でも、スクリプトは実行されないため、悪意のあるスクリプトをアップロードしてもシステムに害はありません。

ただし、ファイルが誤って実行されるのを防ぐことができます。名前を変更できる唯一の保護は、Windowsエクスプローラー(または同様にファイル拡張子を使用するシェル)によって誤って起動されることからの保護です。誤ってvirus.exevirus.exe~に名前変更すると、誤ってタップしたときに実際に役立ちます Enter その上に。

Unixシェルは、拡張子の代わりにファイル形式を使用します。たとえば、スクリプトにevilscript.pngとして保存し、ファイルに「実行」権限がある場合は、Linuxシェルで実行できます。セキュリティの観点からは、一般に、ファイル名ではなくファイルのアクセス許可を制御する方が適切です。

12
enkryptor

サーバーへの直接攻撃からの保護と他のクライアントへの攻撃からの保護の2つの問題があります(サーバーへの攻撃につながる可能性があります)

最初にサーバー、クライアントがファイルを要求すると、サーバーはそれを提供するか、なんとかしてそれを実行するかどうかを決定する必要があります。この決定は、以下を含むさまざまな要因に依存する可能性があります。

  1. ファイル拡張子
  2. ファイルがあるディレクトリ
  3. 実行可能ビットが設定されているかどうか。

サーバー側でコンテンツ検査を実行しているWebサーバーについては知りませんが、存在する可能性を排除できません。

サーバーで理想的には、ユーザーが指定したファイルを最初にスクリプトの実行が許可されているディレクトリに配置しないでください。ただし、ファイル拡張子が制限されていると、ファイルが誤って誤って終了する場合に備えて、「深層防御」ポリシーが有効です。場所。

サーバーがファイルを提供することを決定した場合は、送信するMIMEタイプを決定する必要があります。 Afaictサーバーは通常、ファイル拡張子に基づいてMIMEタイプを選択します。次に、クライアントはファイルをどう処理するかを決定する必要があります。これは、サーバーから送信されたMIMEタイプに基づく必要がありますが、実際には、ファイル拡張子またはファイルの内容の検査に基づく場合があります。

ブラウザがファイルをクライアント側のスクリプトを含む可能性のあるタイプとして処理することを選択した場合、ファイルの提供元のドメインが重要になります。ファイルがメインドメインから提供される場合、スクリプトは設定したCookieを読み取り、それらを使用してユーザーを偽装する可能性があります。

ファイル拡張子の制限はセキュリティ戦略の一部であるべきですが、それだけではありません。スクリプトの実行、コンテンツマッチングの拡張の強制、および別のドメイン名の使用を禁止するディレクトリへの保存は、全体的な防御戦略の一部と見なす必要があります。

2
Peter Green

アップロードされたファイルの唯一の拡張子を確認するだけでは不十分です。例: この質問 の回答を確認してください。

提案:ファイルのタイプを見つけるより信頼できる方法があります。友人がUnixマシンでサーバーを実行している場合は、「 file 」コマンドを使用してファイルの内容を検査し、フォーマットを判別できます。

2
George Gkitsas

これは安全です。

常に実行可能コードを画像内に密輸することができます。

  • PHPコードを別の拡張子でアップロードするだけです。
  • EXIFなどのメタデータに入れます。
  • 特定の色のピクセルを使用して、そのバイナリ表現が希望のPHPコードであるようにします。これは、再エンコード後も存続します(実際にこのコードを実際に見たとき、次のようにして悪用しました: https:/ /www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/ )。

したがって、ファイルのcontentsがユーザー指定の場合は安全でないとすでに想定しているはずです。画像を再エンコードしても、フォーマットを変換しても、それはまだ画像なので、流血しないでください。 Webサーバー(ApacheやNginxなど)がPHPインタープリターを介して実行する場合、誰かがPHPをトリガーして厄介なことをする方法を見つけるでしょう。拡張機能をいくつかのホワイトリストに登録された拡張機能の1つに強制することで、Webサーバーにそれがイメージ(実行可能ではない)であり、インタープリターを通過しないようにすることができます。

もちろん、注意すべきいくつかの関連するリスクがあります。

  • ユーザーがファイル名にnullバイトまたはその他の面白いものを含める可能性があり、結局、拡張子を選択できる場合があります。
  • ユーザーがファイル名を選択できるようにすると、ユーザーがパストラバーサルを使用しようとする可能性があります。
  • Webサーバーの設定を間違えると、拡張機能に関係なくすべてがインタープリターを介して実行されます(これは以前に見たことがあります:PHPが文字通り出力するものをすべて出力するため、これはサイレントバグです認識できないため、画像はPHP解釈)の前後で同じに見えます。
  • ファイルには特定のデコーダーのエクスプロイトが含まれている可能性があります。たとえば、管理者が画像を表示し、脆弱なPNGビューアを備えたブラウザーを使用していることがわかっている場合、その脆弱性を悪用するPNG画像をアップロードできます。

最初の2つは簡単に解決されます。ユーザーにファイル名を選択させないか、少なくとも^[a-zA-Z0-9_-]*$(英数字、アンダースコア、ハイフン)などの確実に安全な文字のセットをホワイトリストに登録しないでください。

3つ目は、「test.png」というファイルをどこかに配置し、<?php echo "test1";を挿入することで確認できます。 curl経由でファイルをリクエストすると、完全なコードが表示されます。 「test1」しか表示されない場合は、脆弱です。

最後に、最後のものは確認するのが難しく、やや範囲外です。サーバー側でウイルススキャナーを使用することもできますが、ウイルススキャナーはいくつかの一般的なケースを検出するだけであり、通常、脆弱性について最初に知っていれば、脆弱性のすべてのバリアントを検出できません。ユーザーは、理想的にはシステムを更新し、脆弱なソフトウェアを実行しないようにする必要があります。ただし、セキュリティの高い環境にいる場合は、多層防御を適用し、イメージを再エンコードするなどの操作を行う必要があります。おそらく、ユーザーに仮想マシンでのイメージの表示のみを許可するなどです。ただし、この質問の範囲外です。 。

概要:軽減されているとは示されていないが、投稿されたコードスニペットのみを考慮する場合、その部分は安全であるいくつかの関連する攻撃があります。

1
Luc