FuelPHP でのセキュリティ対策(1)
FuelPHP Advent Calendar 2011 の 20日目です。
昨日は、@regepan さんの「FuelPHPでメールフォーム雑感。」でした。今日は、FuelPHP でのセキュリティ対策について解説します。1回では終わりそうにないので、何回か続く予定です。
では、FuelPHP での主要なセキュリティ対策について解説していきます。この記事は FuelPHP 1.1 を前提としています。
FuelPHP では、デフォルトのセキュリティ機能として以下が用意されています。
また、デフォルトではありませんが、以下のセキュリティ機能もあります。
Validation については、4日目の @fukata さんの「[FuelPHP]Validationの使い方」で解説されています。
それでは、具体的にそれぞれの機能を見ていきましょう。
出力フィルタ
出力フィルタは、ビューへ渡す変数を自動的に処理する機能です。デフォルトでこの機能はオンになっています。
設定ファイル config.php の security.output_filter で処理する関数やメソッドを指定します。デフォルトでは Security::htmlentities が設定されており、ビューへ渡される変数は、原則として、このメソッドで処理されます。
app/config/config.php
<?php …略… /** * Security settings */ 'security' => array( …略… /** * This output filter can be any normal PHP function as well as 'xss_clean' * * WARNING: Using xss_clean will cause a performance hit. How much is * dependant on how much input data there is. */ 'output_filter' => array('Security::htmlentities'), ), …略…
具体的な実装は Security::htmlentities のコードを見るとわかりますが、最終的に、ビューに渡される文字列は htmlentities() でエスケープされることになります。
オブジェクトを渡した場合は、__toString() メソッドを持っていないとエラーになります。
例外として、config.php の whitelisted_classes でビューに渡せるクラスを設定できます。ここに設定したクラスのオブジェクトはそのままビューに渡され、自動での出力フィルタリングはされませんので注意してください。安易にここにクラスを追加しないようにしましょう。
app/config/config.php
<?php …略… /** * Security settings */ 'security' => array( …略… /** * With output encoding switched on all objects passed will be converted to strings or * throw exceptions unless they are instances of the classes in this array. */ 'whitelisted_classes' => array( 'Fuel\\Core\\Response', 'Fuel\\Core\\View', 'Fuel\\Core\\ViewModel', 'Fuel\Core\Validation', 'Closure', ) ), …略…
【注意】なお、Security::htmlentities では、最終的な処理が htmlentities() 関数でなされますが、何故か第2引数は ENT_COMPAT になっていますので注意してください。
また、第4引数は false になっています(PHP のデフォルトは true)。第4引数は double_encode の指定であり、false はダブルエンコードしないという設定です。
$value = htmlentities($value, ENT_COMPAT, \Fuel::$encoding, false);
HTML をビューに渡したい場合
ビューに渡す変数は上記のように自動でエスケープされるわけですが、場合により HTML を渡したいこともあります。その場合には、View クラスの set_safe() メソッドを使うと、エスケープされずにビューに文字列を渡せます。
Controller を継承した場合は、
$view = View::forge('form/index'); $view->set_safe('error_html', $val->show_errors()); return $view;
Controller_Template を継承した場合は、
$this->template->content = View::forge('form/index'); $this->template->content->set_safe('error_html', $val->show_errors());
のようになります。ビューでは $error_html という変数にエスケープされない値が代入されています。
URI フィルタ
URI フィルタにより、入力された URI は自動的に処理されます。
デフォルトでは htmlentities が指定されていますが、これは、Security::htmlentities で処理されるという意味になります。
app/config/config.php
<?php …略… /** * Security settings */ 'security' => array( …略… 'uri_filter' => array('htmlentities'), …略…
この処理により、コントローラに渡される時点では URI は、すでに HTML エスケープされています。
以下のようなテストコードで確認してみましょう。
app/classes/controller/uri.php
<?php class Controller_Uri extends Controller { public function action_index($a = '', $b = '') { $data['a'] = $a; $data['b'] = $b; Debug::dump($data); return Response::forge(View::forge('uri', $data)); } }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>FuelPHP Framework Test</title> </head> <body> <div id="header"> </div> <div class="container"> a: <?php echo $a; ?><br /> b: <?php echo $b; ?><br /> </div> </body> </html>
http://localhost/fuel/uri/index/a&b/b%3C%3E にアクセスしてみます。
コントローラの時点ですでにエスケープされていることがわかります。
また、エスケープされた値をビューに渡していますが、double_encode が false で処理されるため、ビューでも二重にはエスケープされません。
FuelPHP でのセキュリティ対策(2) へ続きます。
Advent Calendar の明日は、@madmamor さんの「FuelPHPのTasks」の予定です。お楽しみに!