- 「修正できない(されない)脆弱性」「修正されていない脆弱性」プログラムの脆弱性原因などを記載したページです。ベストプラクティス的な項目も含めています。これらの仕様自体が問題とは言えないまでもセキュリティ上の問題の原因(アタックベクタの一部)となり得る仕様はプログラマと知っておくべきなので掲載しています。register_globals=onの場合にリモートファイルのインクルードが可能となるなど、PHPの設定を変更する事によりプログラムが脆弱になるケースが数多く報告されています。*1これらの設定や仕様が直接のセキュリティホールになる事はありませんが脆弱性の原因となる事が多い項目をあげています。
- 修正される可能性がある脆弱性はPHP/脆弱性リスト/PHP5を参照してください。
フィードバックを歓迎します。yohgaki@ohgaki.netまたはブログのコンタクトからお願いします。
修正できない(されない)脆弱性 †
ファイル関連関数のファイル名パラメータがバイナリセーフでない †
- 脆弱性:PHPの文字列型はバイナリセーフですが、OSのファイルシステムコールのファイル名引数はバイナリセーフではありません。C言語では\0が文字列の終端を表すため\0で文字列が終了したものとして扱われます。つまりコーディングによってはNULLバイト攻撃に脆弱になります。
- 回避策:substr($str, -1, 4)、preg_match('/ext$/', $str) でファイル名をチェックする場合等、PHPの文字列とほとんどの関数はバイナリセーフであることに注意しセキュリティホールを作らない。
POSIX正規表現関数がバイナリセーフでない †
- 脆弱性:POSIX正規表現関数(ereg*関数)はバイナリセーフでないため\0以降の文字列を無視する。PHPの文字列はバイナリセーフであるためNULLバイト攻撃が可能となる場合がある。
- 回避策:バイナリセーフな正規表現を利用する場合はmb_ereg*またはpreg_*関数を使用する。
- POSIX正規表現ライブラリの仕様であるため修正されない(と思われる)バイナリセーフな関数と組み合わせて使うとセキュリティホールを作ってしまう場合がある。
log_errors=offがデフォルト †
- 脆弱性:エラー情報が記録されない。セキュアなシステムはエラーは全て保存されるべき。
- 適切なエラーログの保存先は環境によって異なる為、デフォルト値を設定することが難しい。この問題はソースからインストールした場合に発生する問題です。ディストリビューションやインストールする管理者によって設定されなければならない項目です。
モジュールを利用したopen_basedir/safe_modeの回避 †
- 脆弱性:モジュール関数や機能の中にはopen_basedir設定などに関係なくファイルを開いたり書き込みが可能。例えば、データベースコマンドを利用したファイルの読み書きなど。
- 回避策:open_basedirをセキュリティ確保機能として使用しない。元々open_basedir, safe_mode共にフェイルセーフ機構であり共有環境でのセキュリティを提供する物ではない。SELinux等利用する。
default_charsetが設定されていない †
- 脆弱性:2000年2月のCERTアドバイザリにも記載されているように動的コンテンツを送信するWebサーバは文字エンコーディングを必ず指定するべきです。ブラウザの文字エンコーディングの認識状態によって意図しないJavaScriptを実行されない為に文字エンコーディング指定が必要です。*2PHPユーザがどの文字エンコーディングを使用しているか不明であるためデフォルト値が設定できないのでデフォルトでは未設定です。
- 回避策:default_charsetを必ず設定する。
アクセスを続けると無期限に同じセッションIDが使用されづつける †
- 脆弱性:長期間同じセッションIDを使用し続けるとセッションIDが盗まれた場合のリスクを増大させる。
- 回避策:session_regenerate_id()で新しいセッションIDを作成する
- アプリケーションによってはシステムが勝手にセッションIDを変更すると動作しなくなるケースが考えられる。この為、自動的/機械的に新しいセッションIDを一定期間毎に作成できない。
PHPが埋め込み型としてしか動作しない †
- 脆弱性:埋め込み型としてしか動作しないため、リモート・ローカルスクリプトの実行バグに対して非常に脆弱
- 回避策:とにかくバグを作らない。allow_url_include=offも必ず設定する
- スクリプトモードでの実行をサポートする提案が何度かなされていますが、実現していません。
PHPがApacheモジュールとして動作している場合、ログ改ざんが可能 †
- 脆弱性:モジュールとして動作しているので、ファイルディスクリプタを見つけ出す事によりApacheのログ改ざんが可能
- 回避策:CGIで利用する。
- PHPだけの問題ではありません。mod_perl/mod_python/mod_rubyでも同じです。システムの仕様上の問題であるので、モジュールとして動作している限り回避できません。
symlinkによるopen_basedir/safe_modeの回避 †
- http://www.hardened-php.net/advisory_082006.132.html
- 脆弱性:シンボリックリンクを作成することによりopen_basedir制限を回避できる
- 回避策:php.iniのdisable_functionsにsymlinkを追加する。(元々open_basedir, safe_mode共にフェイルセーフ機構であり共有環境でのセキュリティを提供する物ではない)
- safe_modeはPHP6で廃止されます。symlinkの他にも、safe_mode/open_basedir設定を回避する方法は数多く知られています。
修正されていない脆弱性 †
パーミッシブなセッション管理 †
- 脆弱性:外部から提供された未初期化セッションIDをそのままセッションIDとして初期化するため、「セッションの固定化攻撃」が可能となる。
- 回避策:PHP/patch/StrictSessionを利用するか、セッションセーブハンドラを記述して未初期化のセッションIDが送信された場合はセッションIDを再生成する。
- PHP6からはストリクトなセッション管理が行われる
session.use_only_cookies=0がデフォルト †
- 脆弱性:URLなどに指定されたセッションIDを利用してセッションが初期化される。(パーミッシブセッション管理。1に設定すればURL、POST中のセッションIDは無視される)
- PHP/patch/StrictSession
- 回避策:セッション開始前にsession.use_only_cookies=1にini_set()で設定する。PHP/patch/StrictSessionを利用する。
php://inputがrequire/include文で利用可能 †
- 脆弱性:php.iniでallow_url_fopen/allow_url_includeを無効に設定しても、php://inputは利用可能となり脆弱なPHPスクリプトにはPOSTメソッドを利用してスクリプトインジェクションが行える。
- 回避策:スクリプトインジェクション脆弱性を正しく修正する。
- 備考:allow_url_includeはPHP6から利用可能またはPHP/patch/allow_url_includeを利用。現時点ではallow_url_includeではphp://inputからの攻撃を防げない。
expose_php=onがデフォルト †
- 脆弱性:export_php=onの場合、PHPのバージョンも含めてHTTPヘッダに記載される。INI_SYSTEMに設定されているためサーバ設定でのみ変更可能。
- 回避策:システムレベルのphp.ini設定でexpose_php=offに設定する。
error_reporting=E_ALL & ~ E_NOTICEがデフォルト †
- 脆弱性:E_NOTICEを無視するコーディングは脆弱なコードの発見、攻撃を検知を難しくする。
- 回避策:error_reporting(E_ALL)をスクリプトの最初に実行する。
- php.ini-recomendedではE_ALL
strip_tags()が属性を削除しない †
- 脆弱性:strip_tags関数はタグのみ削除する。onmouseover, style等を利用したJavaScriptインジェクション攻撃には脆弱。
- 回避策:タグの属性は別途削除する。
display_errors=onがデフォルト †
- 脆弱性:エラー情報が攻撃に有用な情報を与える。
- 回避策:ini_setでoffに設定する。
- php.ini-recomendedではoff。