呼び出している部分を以下に示す。get_upload_file_name($orgfile);ファイルダウンロード時の対策Content-Typeを正しく設定する。画像の場合は、マジックバイトを確認する。必要に応じてContent-Dispositionヘッダを設定する。・Content-Typeを正しく設定するPDFファイルダウンロードによるXSS脆弱性のサンプルは、Content-Typeの間違いが原因だった。Content-Typeを正しく指定すれば脆弱性はなくなる。Content-Typeを正しく指定することはIEに限らずすべてのブラウザで必要である。ダウンロードスクリプト経由ではなくファイルを公開領域に保存する場合は、Webサーバの設定の確認をする。いう設定ファイルにContent-Typeの設定が保存されている。自分で設定した場合は、ブラウザ側で認識できるContent-Typeであることをチェックするすべきである。・画像の場合はマジックバイトを確認するダウンロードスクリプトを用いてファイルをダウンロードする際には、ダウンロード時にもマジックバイトを確認するようにすれば、なんらかの原因で不正なファイルがWebサーバに紛れ込んでいても確実な対策が可能となる。利用するダウンロードスクリプトの改良版を示す。attachment」を指定する方法がある。「application/octet-stream」にするとファイルタイプ上も「ダウンロードすべきファイル」とう意味になる。filename="sample.pdf"・その他の対策ここまでの対策は脆弱性を防止するための必要最小限のチェックである。マジックバイトのチェックのみでは利用者のブラウザで放蕩に表示できるかまでは確認できない。このため、Webアプリケーションの仕様策定時に以下のようなチェックを行うかどうか検討するとよい。ブラウザにとって未知のものとなり、XSSの可能性がある。この問題の対応は容易ではない。確実な対処として以下の方法がある。コンテンツを配信するサーバのドメインを別にする。Content-Dispositionヘッダを付ける。上記の方法には副作用があるため、確実性は劣るものの副作用のない対処としては以下の方法があります。アプリケーションが想定したURLかどうかをチェックする。コンテンツの閲覧に必要なアプリケーションの導入を利用者に注意喚起する。特有の仕様が影響している。IEはファイルタイプの判定にHTTPレスポンスのContent-Typeヘッダ以外に、URL上の拡張子やファイルの中身を利用している。その判定仕様は非公開だが、以下のような挙動が判明している。コンテンツが画像の場合Content-Typeの他に、画像ファイルのマジックバイトがファイルタイプの判定に利用される。マジックバイトとはファイルタイプ識別のためにファイルの先頭に置かれた固定の文字列である。JPEG、PNGのマジックバイトを下表に示す。\x89PNG\x0D\x0A\x1A\x0AIE7以前のデフォルト設定では以下のようにファイルタイプを判定する。・Content-Typeとマジックバイトが一致する場合Content-Typeが示すファイルタイプを採用する。・Content-Typeとマジックバイトが一致しない場合どちらも無視し、ファイルの内容からファイルタイプを推測する。ファイルの内容にHTMLタグが含まれていればHTMLと判定する場合もある。コンテンツが画像以外の場合IEのバージョンを問わず次のような仕様であると推測されている。IEが扱うことのできるContent-Typeの場合、Content-Typeに従って処理をする。IEが扱うことのできないContent-Typeの場合、URLに含まれる拡張子からファイルタイプを判定する。このルールは複雑であるので説明しない。前の記事で攻撃用URLの作成のためにPATHINFOとして「/a.html」を加えたのは、このURL中の拡張子からファイルタイプを判定する仕様を悪用するためである。影響を受けるページアプリケーション全体。成りすまし利用者の関与の度合い必要。リンクのクリックなど概要アップロードしたファイルを利用者がダウンロードする際に、ブラウザがファイルタイプを誤認する場合がある。アプリケーションがPNG画像を想定しているにもかかわらず画像のデータ中にHTMLタグが含まれていると、条件によってはブラウザがHTMLファいつと誤認して、画像ファイルに埋め込まれたらJavaScriptを実行する場合がある。これがファイルダウンロードによるXSSである。この脆弱性を悪用する攻撃者はHTMLやJavaScriptを仕込んだ画像ファイルやPDFファイルをアップロードして公開する。このファイルは通常の参照の仕方ではHTMLとは認識されないが、攻撃者がアプリケーション利用者に罠を仕掛けてアップロードしたファイルがHTMLとして認識されるように仕向ける。いずれもIE以外のブラウザでは必ずしも再現しない。●画像ファイルによるXSS画像ファイルに偽装したファイルにHTMLやJavaScriptを仕込んだものをアップロードする方法によってXSS攻撃が可能となる場合がある。画像によるXSSはIE8以降では対策されている。アップロードファイルによるサーバ側スクリプト実行の記事のスクリプト実行対策版アップローダでsample.pngというファイルをアップロードする。このファイルは拡張子はpngだが内容は以下のスクリプトである。<script>alert('XSS');</script>アップロード完了の画面において、img要素の部分は×印となる。リンクをクリックするとIE7では上記のJavaScriptが実行される。IE8ではスクリプトがテキストとして表示される。実際の攻撃では攻撃用のJavaScriptを仕込んだファイルを画像としてアップロードした上で、その画像を表示するURLを罠サイトに仕込む。img要素で画像として表示してもJavaScriptは実行されないので、iframe要素などを用いてHTMLとして表示させる。画像ファイルによるXSSの影響は通常のXSSと同じである。クッキー値の盗み出しによる成りすまし、Web機能の悪用、画像改変によるフィッシングなどが可能である。●PDFダウンロード画面によるXSS次の例はPDFのようなアプリケーションファイルのダウンロードサービスを想定している。ストレージサービスを簡略化したものである。ファイルをアップロードする画面はアップロードファイルによるサーバ側スクリプト実行の記事のものからform要素のactionだけを変更したものを使用する。同様にファイルを受け付けるスクリプトとダウンロードスクリプトは受け付けるファイルの拡張子をpdfに変更したものを使用する。以下にファイルを受け付けるスクリプトupload2.php(抜粋)とダウンロードスクリプトdownload2.phpである。basename($file));?>正常なPDFファイルをアップロードするとリンクが表示され、そのリンクをクリックするとPDFファイルをダウンロードできる(ファイル名の拡張子は.pdfにならないがダウンロードされるファイルの中身はPDFである)。攻撃の場合、例として以下のようにscript要素のみからなるHTMLファイルpdfという拡張子を持つファイル名にしてアップロードする。<script>alert('XSS');</script>この偽装PDFファイルをアップロードすると、正常なPDFファイルをアップロードした時と同様にリンクが表示される。リンクをクリックするとファイルダウンロードのダイアログが表示される。ここからは、攻撃者の視点で罠のためのURLを作成する手順を説明する。ダウンロード用リンクをマウスで右クリックしてコンテキストメニューを表示し、「ショートカットのコピー」を選択する。コピーした内容は以下。http://example.jp/download2.php?file=<ランダムな文字列>.pdfこれに下記のように「/a.html」という文字列を挿入する。挿入した文字列はPATHINFOと呼ばれるもので、見かけ上はファイル名のような形でパラメータを埋め込む方法である。a.htmlというファイルは存在しないので、パラメータとしてスクリプトに渡される。「/a.html」を挿入した意味については次回の記事の「脆弱性の原因」で説明する。http://example.jp/download2.php/a.html?file=<ランダムな文字列>.pdfこのURLをIEのアドレスバーに入力してEnterキーを押下するとJavaScriptが実行される。偽装画像の場合と異なりIE8でもJavaScriptが実行される(この記事を書いている時点で最新のIE11ではJavaScriptは実行されず、PDFの中身がテキストとして表示される。この脆弱性の根本原因はContent-Typeの間違いである。PDFの正しいContent-Typeは「application/pdf」だが、「application/x-pdf」と不正なContent-Typeを指定したことが直接的な原因である。概要アップローダの中には利用者がアップロードしたファイルをWebサーバの公開ディレクトリに保存するものがある。スクリプトを表す拡張子が指定できると、アップロードしたファイルをスクリプトとしてWebサーバ上で実行できます。外部から送り込まれたスクリプトが実行されると、OSコマンド・インジェクションと同様の影響があります。例として利用者が画像ファイルをアップロードし、それを公開する機能を考える。下記はアップロードする画面である(抜粋)。form要素のenctype属性の値"multipart/form-data"によりフォームデータの送信方式を指定しており、ファイルのアップロードが可能となる。value="アップロード"></form>下記はファイルを受け取って決まったディレクトリに保存した上で画面に表示するスクリプト(upload.php)である。?></a>をアップロードしました。?>"></body>この機能を使用して画像ファイルをアップロードすれば画像が表示される。攻撃では画像ファイルの変わりにスクリプトをアップロードする。例として以下のPHPスクリプトをアップロードする。/etc/passwd');?></pre>すると、アップロードされたファイルは画像ではないがimg要素の部分にIneternetExplorerの場合、×マークが表示される。アップロードファイルによるサーバ側スクリプト実行による影響は、OSコマンド・インジェクションと同じである。PHPスクリプトが動作するOSアカウントで実行可能な昨日すべて悪用可能である。脆弱性が生まれる条件は、以下の両方に該当することである。アップロードしたファイルを公開ディレクトリに保存する。スクリプトであることを示す拡張子を指定できる。対策アップロードされたファイルを公開ディレクトリに保存しないようにする。その場合、ダウンロードスクリプトを使用する。