blogPHPでWEB+DBシステムの開発をやっています。界隈で話題になっています。アプリケーションの作り方の問題ということで、以前から作る側が注意を払う必要がありました。アプリケーションでも同様の問題が発生する可能性があります。知っている人には常識なのですが、まだ知らない人もいるかと思うので、CakePHPにおける対策方法を書いてみます。下記コードはCakePHP2系を想定していますが、考え方はCakePHP1系でも同じです。脆弱性は、フォーム(多くはFormHelperで作成)からPOSTで送信された値をモデルに渡す時に発生します。以下のようなフォームの場合、一見するとnameだけが送信されるように見えます。このフォームをブラウザで表示して入力内容を送信すれば、もちろんnameだけが送信されます。フォームというかHTTPリクエストは自在に改変できるので、nameの他にemailでもpasswordでも何でも送ることができます。?>コントローラで見ると、edit()メソッド内で、$this->request->dataの値をそのままUser#save()に渡しています。サンプルコードなどではよくある書き方ですが、$this->request->dataに本来想定していないパラメータが含まれていても(上記フォームで言うところのname以外)、usersテーブルにカラムが存在すれば、送信された内容がそのままデータベースに保存されてしまいます。}}これを悪用すると、本来入力フォームでは変更して欲しくないカラム(例えば管理者フラグや権限、もしかするとポイント数など)を外部から操作することが可能となります。Model#save()では、与えられた引数にプライマリーキー(多くはid)が含まれていると、その値にマッチするレコードをupdateしてしまいます。新規追加フォームのつもりが、任意のレコードを変更されてしまう可能性があります。この問題、実は意識しておかないと結構影響が大きいです。SecurityComponentをコントローラの$componentsに記載しておけば、自動的にフォーム改ざんチェックが有効となるので、フォームを改ざんして任意のパラメータを送信してもエラーとなり、アクションメソッドが実行されません。save()に渡す値を設定する対策1でも対策にはなるのですが、本質的な問題は$this->request->dataに意図しないパラメータを含まれているのにそのまま処理してしまうことです。そこで、処理対象のパラメータのみを抽出して、save()には抽出したパラメータを渡すようにします。$dataに処理対象のパラメータだけをセットして、save()には$dataを渡しています。これにより意図しないパラメータが送られてきても、save()に渡されることはありません。save()の第三引数に更新対象カラムを渡すsave()の第三引数に処理対象カラムを指定することで、意図しないカラムへの更新を防ぐという方法があります。下記のようにsave()の第三引数にarray(‘name’)を指定して、nameのみを更新対象とします。この方法なら更新されるカラムはnameに限定することができます。$this->request->data[‘User’]にidが含まれていると、そのidに該当するレコードが更新されるという問題が残ります。更新カラムはnameのみですが、その対象レコードは任意に指定されてしまいます。}便利機能には注意を$this->request->dataをそのままModel#save()に渡して処理する。この方法は簡単だし、スマートに見えます。上で見てきたように意識しておかないと意外な落とし穴にはまります。このあたりは手を抜かずにきっちりと処理対象パラメータのみを抽出してsave()に渡すという方法が問題も起こりづらいし、挙動も把握しやすいと思います。意識していなかった人はご注意を。