FuelPHP でのセキュリティ対策(2)
FuelPHP Advent Calendar 2011 の 22日目です。
昨日は、@madmamor さんの「FuelPHPのTasks」でした。
今日は、FuelPHP でのセキュリティ対策の続きです。前回の記事をまだお読みでない場合は、「FuelPHP でのセキュリティ対策(1)」をご覧ください。
ところで、前回の「URI フィルタ」ですが、これってどういうセキュリティ上のメリットがあるんでしょうね?考えたのですが、いまいち、よくわかりません。おわかりの方いらっしゃいましたら教えてください。
SQL インジェクション対策
FuelPHP では、Query Builder (クエリビルダー) を使った場合、自動的に値がエスケープされるようになっています、とドキュメントされています。
Query Builder とは、CodeIgniter での Active Record クラスのようなやつで、以下のようなコードです。
<?php // Will execute SELECT `name` as `the_name` FROM `users`; $result = DB::select(array('name','the_name'))->from('users')->execute(); // Will execute SELECT * FROM `users` WHERE `id` = 1 $result = DB::select()->from('users')->where('id', '=', 1)->execute(); // Will execute INSERT INTO `users`(`name`,`email`,`password`) // VALUES ("John Random", "john@example.com", "s0_s3cr3t") list($insert_id, $rows_affected) = DB::insert('users')->set(array( 'name' => 'John Random', 'email' => 'john@example.com', 'password' => 's0_s3cr3t', ))->execute();
要するに、SQL を生書きする DB::query() メソッドを使わなければ、自動的にエスケープされるので、Query Builder にバグがない限り SQL インジェクションは起こらないということになります。
【注意】現在の FuelPHP の PDO ドライバは、文字エンコーディングの設定に SET NAMES を使っているというバグがありますので注意してください。
FuelPHP に含まれる ORM パッケージも Query Builder を使っているため同じようにエスケープされます。
入力フィルタ
ここからは、デフォルトでは有効でないセキュリティ機能です。
入力フィルタは、$_GET、$_POST、$_COOKIE を処理する機能です。デフォルトでは何も指定されていません。
app/config/config.php
<?php …略… /** * Security settings */ 'security' => array( …略… /** * This input 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. */ 'input_filter' => array(), …略…
例えば、文字エンコーディングをチェックしてみましょう。
まず、Security クラスを拡張し (「FuelPHPのcoreクラスを拡張してみる。」参照)、check_encoding() メソッドを追加します。
app/classes/security.php
<?php …略… public static function check_encoding($value) { if (is_array($value)) { array_map(array('Security', 'check_encoding'), $value); return $value; } if (mb_check_encoding($value, \Fuel::$encoding)) { return $value; } else { die('Invalid input data'); } }
そして、config.php でメソッドを指定します。
app/config/config.php
<?php …略… /** * Security settings */ 'security' => array( …略… /** * This input 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. */ 'input_filter' => array('Security::check_encoding'), …略…
CSRF 保護
FuelPHP の CSRF 保護機能は、Cookie を使ったトークン方式です。
使うためには、保護するページの直前のページにトークンを hidden フィールドで追加します。
<input type="hidden" name="<?php echo Config::get('security.csrf_token_key'); ?>" value="<?php echo Security::fetch_token(); ?>" />
FuelPHP の Form クラスを使うと以下のように記述できます。
<?php echo Form::hidden(Config::get('security.csrf_token_key'), Security::fetch_token()); ?>
そして保護するページのコントローラのアクションで、以下のように Security::check_token() メソッドでトークンをチェックします。
<?php …略… if ( ! \Security::check_token()) { die('Invalid input data'); }
なお、トークンを保存する Cookie の名前や有効期限は、config.php で変更可能です。
FuelPHP でのセキュリティ対策(3) へ続きます。
明日は、まだ誰が担当するか決まっていません!誰かお願いします。
FuelPHP Advent Calendar 2011
@akibe さんの「FuelPHPをNginxで動かしてみる」に決まりました!