CakePHPのデータをサニタイズする | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

サニタイズ言うなーという議論はさておいて、CakePHPにはSanitizeというクラスが存在します。

その名の通り、CakePHPで扱うデータから不正な文字を消してくれたりエスケープしてくれたりSQLセーフなデータとして返してくれたりします。

CakePHPでユーザーから送られてくるリクエストデータなどは取りあえずこれ通しとけってものなので、ぜひ覚えて使いたいクラスとなっています。



Sanitizeクラスの概要と使いかた


使い方も非常にシンプルで以下のようにしてSanitizeクラスの呼び込みとcleanメソッドを使えばデータを綺麗にしてくれます。


<?php
App::uses('Sanitize', 'Utility');

class FooController extends AppController {
    public function index($param) {
        $param = Sanitize::clean($param);
    }
}

サニタイズしたいデータが入った変数をcleanメソッドの引数として渡すだけでその変数を浄化してくれます。

配列にも対応していますので、その場合は再帰的に処理をしてくれます。

cleanメソッドはデータを浄化する一連の処理をしてくれるもので、個別の処理を呼び出すことも可能です。


Sanitizeクラスは、CakePHPのユーティリティとして、以下のパスに定義されています。


/path/to/cakephp/lib/Cake/Utility/Sanitize.php

それほど難しい処理をしていないので、中身を見ればどのような処理をしてくれるか理解できるかと思いますが、clean以外にも下記のメソッドが定義されています。


メソッド 用途
paranoid 半角英数字以外の文字を除去する(第2引数であえて許可したい文字を指定することができる)
escape SQLセーフなデータとして返す(エスケープ処理をする)
html データに含まれるHTMLタグを変換する(htmlentitiesとほぼ同義)。第2引数にremoveオプションを付けるとHTMLタグそのものを削除する
stripWhitespace 不要な改行コードやスペースを削除する
stripImages データに含まれるIMGタグを削除する
stripScripts データに含まれるSCRIPTタグを削除する
stripAll stripWhitespace、stripImages、stripScripts全ての処理を通す
stripTags データから特定のHTMLタグを除去する
clean 一連のサニタイズ処理を行う(オプション指定に付いては後述)

それぞれ、Sanitize::html($param)のように単体で呼び出すこともできます。

cleanメソッドは第2引数のオプションによって細かくサニタイズの処理を指定することができます。
オプションの配列に指定できるキーとそのデフォルト値は、プログラム内で以下のように定義されています。


$options = array_merge(array(
    'connection' => 'default',
    'odd_spaces' => true,
    'remove_html' => false,
    'encode' => true,
    'dollar' => true,
    'carriage' => true,
    'unicode' => true,
    'escape' => true,
    'backslash' => true
), $options);


それぞれのキーの意味は下記の通りです。


オプション 用途
connection DB接続名(app/Config/database.phpで指定している変数名)
odd_spaces 「0xCA」を含むおかしなスペースを標準的な半角スペースに置換する
remove_html HTMLタグを除去するかどうか(encodeオプションをTRUEにしないと動作しない)
encode HTMLタグを変換するかどうか
dollar ドルマークをエスケープするかどうか
carriage キャリッジリターンを削除するかどうか
unicode HTMLエンティティ化してしまったUnicodeの数値文字参照を正しいものに置き換えるかどうか
escape 内部のescapeメソッドを通すかどうか
backslash ユーザが入力したバックスラッシュを信頼できるバックスラッシュに置き換えるかどうか

デフォルトのオプションと照らし合わせて見ればわかりますが、データからHTMLタグの除去(remove_html)以外は全て処理をしてくれます。

一旦、Sanitize::clean()を通してしまい、必要の応じてアプリケーションごとの独自処理としてその他のデータの加工等をしていくのがよさそうです。

仕様の詳細は、マニュアル の方も確認してみてください。


ただ、サニタイズできたからデータが安全になったというわけではなく、やはりロジックの作りによりますので注意は当然必要です。

例えば、clean()によってSQLセーフなデータになったからといって下記のように直接SQLにユーザーから送られてくるパラメータを閉じ込めていいわけではありません。


$id = Sanitize::clean($id);
$data = $this->Foo->query("select name from foo where id = $id");

escape()によって余計な\マークをエスケープ処理してはくれますが、当然それだけでは上記のSQLインジェクションの問題を解決するわけではありません。

バインド変数を使うなど、適切な処理が必要です。


CakePHP内のデータをクリーンな状態にしたいという場合は、不正なデータの除去やHTMLエンティティの変換を自動でやってくれたりもするので、便利に使えるのではないでしょうか。