en en en en ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja en ja ja ja ja ja ja ja ja ja nl ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja en ja ja en ja ja ja ja ja ja ja ja zh ja zh ja ja ja zh ja ja en ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja fr en ja en ja ja ja pt zh kn ja ja ja ja ja ja ja ja en es en es pt ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja en ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja zh ja ja ja ja ja ja ja ru ja ja ja en
極める!Security Component (CakePHP Advent Calendar 2010 24日目) : akiyan.com
1 この記事はCakePHP Advent Calendar 2010 24日目に向けて書きました
CakePHP Advent Calendar 2010に参加したい!と思ったときには既に遅し、トリの24日しか空いておらず、トリっぽい記事なんて書けないわーと思っていました。が、主催のcakephperさんより「べつにトリっぽくなくていいですよ」との温かい言葉を頂いたので、前々から書きたかったSecurityコンポーネントの話を書いてみます。対象バージョンは1.3.6 Stableです。
僕の前の23日目はyashioさんの【CakePHP】メディアビューの使い方(CakePHP Advent Calendar 2010) Ooooooops!でした。記事一覧については、CakePHPフォーラムのAdvent Calendarスレッドに記事ごとにコメントが投稿されていますのでぜひ御覧ください。
Securityコンポーネントは多くの機能を備えています。
リクエストメソッド(GET/POST等)チェッカ
この中で突出してハマるのが、パラメータ改ざん対策です。そして、パラメータ改ざん対策はCSRF対策と同時に動作するので、CSRFだけを利用することができません。このため、あまりのハマりっぷりに嫌気が差したのか、「CSRF対策をしたいだけなので、Securityコンポーネントの利用をやめて自作した」という実例があるくらいだったりします。(ただしCSRF対策の実装も一長一短なので、パラメータ改ざんは関係ないかもしれません)
Security Componentの基本動作
Securityコンポーネントを読み込むと、POSTメソッドのリクエストに対してCSRF対策とパラメータ改ざん対策がデフォルトで動作します。CSRF対策では、Formヘルパーで作られたフォーム画面以外(悪意のあるサイト等)からのPOSTを弾き、パラメータ改ざん対策ではFormヘルパーで正しく作られたフォーム部品(input, select等)以外からのPOSTを弾くようになります。
このどちらかで弾かれた場合は、デフォルトでは空白の画面が出力されます。$this->Security->blackHollCallBackを設定すれば、任意の画面に差し替えが可能です。
そして、この「デフォルトが空白」という仕様が、Securityコンポーネントの不可解さを助長させている原因のひとつです。debug値に関係なく空白ページが出力されてしまうので、Securityコンポーネントが原因なのかわからず、わかったとしてもどのセキュリティチェックに引っかかったのかまではわかりません。まあ、訓練されたSecurityコンポーネントユーザーであれば、真っ先にパラメータ改ざんチェッカだとあたりをつけますがw
なお、Securityコンポーネントを読み込みつつ、CSRF対策とパラメータ改ざん対策を停止するには、コントローラのbeforeFilter内で$this->Securty->validatePost = false;すればよいです。
CSRF対策は、セッショントークンでフォーム画面からの送信をチェックしている
CSRF対策の基本動作は、セッショントークンによって行われます。
まず、SecurityComponentが読み込まれた時点で、セッションに毎回異なるトークンが保存されます。保存されたトークン値は$form->create()時にhidden値として埋めこまれ、POSTされたときにセッションの値と照合されます。このチェックにより、悪意のあるサイトから勝手にPOSTすることができなくなります。
パラメータ改ざん対策は、フォーム部品情報をハッシュで確認している
パラメータ改ざん対策は、フォーム部品情報のハッシュをhidden値に含めて、POSTデータと整合性をチェックしています。ハッシュ値は$form->end()時にhidden値として埋めこまれます。個人的には初めて見る、興味深い実装です。
このチェックより、悪意のあるユーザーがフォームに存在しないキーを予測して、意図しないDBのフィールドを書き換えるなどの攻撃を防ぐことが出来ます。例えばUser.statusのような、ユーザーが通常変更できないフィールドなどです。
同じような機能として、Model::save()の第三引数にに書き換え可能なフィールドのホワイトリストを渡して書き換えるフィールドを制限することができます。ですが、Securityコンポーネント使用時はそもそもビューで作成していないフィールドのデータが渡ってくることはなくなるので、これは不要となります。より安全にしたいということであれば指定すればよいですが、一つのアクションでビューが複数あるときなどは、ホワイトリストの指定も複数に渡ってしまうので、ビューに任せるほうがコントローラをシンプルに保てるなどの利点もあります。
パラメータ改ざん対策で受付可能なフォーム部品、そうでない部品
では実際に、受付可能なフォーム部品と、不可能な部品の例を見てみましょう。
受け付けるフォーム部品
見慣れたフォーム部品ですね。
echo $form->create('User', array('url' => array('controller' => 'users', 'action' => 'edit'))); echo $form->input('User.name', array('type' => 'text')); echo $form->submit(); echo $form->end();
受け付けないフォーム部品
手書きフォームは全てNGです。こういうフォームが一つでもあると、blackHoleに吸い込まれます。(POSTメソッドに限りますよ)
" method="post">
細かいことですが、formの閉じタグも$form->end()で書かないとダメです。$form->end()でフォーム部品情報のハッシュが出力されているからです。
Formヘルパーを使ったとしても受け付けてくれない書き方
さてここが一番のポイント。なんと、Formヘルパーを使ったとしても受け付けてくれない場合があります。まだハマったことの無い方は覚えておいて損はありません。
name属性の指定は不可
$form->input('User.name', array('type' => 'text', 'name' => 'user_name')); // name属性を指定しているとダメ
第一引数の書き方次第では不可
$form->input('User.genre.' . (int)$i, array('type' => 'checkbox')); // この書き方はダメ
$form->input('User.' . (int)$i . '.genre', array('type' => 'checkbox')); // OK
数字じゃなければこれもOK
$form->input('User.genre.' . $genre_name, array('type' => 'checkbox')); // $genre_nameがis_int falseであればOK
これは見つけるのに苦労しましたね...。
hidden値の書き換えは、原則不可
これも大いにハマったのですが、type=hiddenなvalue値をJavaScriptなどで書き換えたりすると、通常は受け付けてくれません。hiddenで埋め込んだ値の書き換え防止機能が働いてしまうのです。(hidden書き換え防止自体は便利です)
input('User.age', array('type' => 'hidden', 'value' => '') ?>   function set_user_age(age) { $('#UserAge').val(age); // 書き換えダメ! }
書き換え可能にするには、コントローラのbeforeFilter内でdisabledFieldsをセットしてCSRFチェックの対象から外す必要があります。beforeFilter内で行う理由は、チェックの動作がアクションメソッドの実行前に行われるからです。
例えばUser.ageをチェックから外すには、以下のように書きます。
function beforeFilter() { $this->Security->disabledFields = array('User.age'); }
しかしbeforeFilterはコントローラ一括で動作してしまうので、アクションごとに設定するには場合分けが必要になってしまい、複雑になってしまいます。そこで、微妙さはどっこいどっこいですが、個人的にはdisplay:noneなtextフォームを作ってhiddenの代用としたりしています。
動作の詳細は、今のところソース読めとしか...
これらの動作については、公式ドキュメントには残念ながら記載されていません。Securityコンポーネントを使いこなすには今のところソースを読むのが最も近道という状態です。
色んな意味で難易度の高いSecurityコンポーネントですが、それでもコアヘルパーの一つであり、CSRF対策やパラメータ改ざん対策は使いどころも多いので、気合を入れて使いこなしてみるのもいいと思います。Securityコンポーネントなんか怖くないよ!と言えると、他のCakePHPerからちょっとばかし畏怖の目で見られるかもしれませんw
Advent Calendarは記事を書くいいきっかけ
最後に。Advent Calendar向けに記事を書いてみて思いましたが、こういった締切りのあるイベントへの参加表明で執筆を自己強制するのは悪くないですね。個人的に忙しい時でブログの更新頻度が落ちていたので、いいきっかけになりました。Advent Calendar参加者同士の一体感も感じられるので、楽しいです。来年も何か参加したいですね。
というわけで、CakePHP Advent Calendar 2011の1日目となる方にバトンを放り投げて終わりにしたいと思います。お疲れさまでした!メリークリスマス!
"CakePHP Advent Calendar 2010を開催!" フォーラム - CakePHP Users in Japan
CakePHP: 高速開発 php フレームワーク。 Home
cakephp_jp_advent_cal_2010 (Advent Calendarで書かれた記事のRSS)
カテゴリ:ホーム » ブログ » IT » プログラミング » 極める!Security Component (CakePHP Advent Calendar 2010 24日目)
前の記事:F-04CのSTAR SPLASHカラーがかわいすぎる
後の記事:2011年、あけましておめでとうございます!
コメント / トラックバック
コメント / トラックバック 2 件
CakePHP2 でパラメータ改ざん対策。フォームの入力値以外を変更しない方法 | oki2a24 より:
2012-09-24 10:02
[...] 極める!Security Component (CakePHP Advent Calendar 2010 24日目) : akiyan.com TwitterFacebook印刷関連記事 [...]
2012-12-14 13:13
2年前の記事にツッコミで恐縮なのですが一部誤りではないかと思ったのでコメントさせて頂きます。
受け付けないフォーム部品の所で「blackHoleに吸い込まれます」とされている例ですが、実際は_validatePost内の
if (empty($controller->data)) {
return true;
によりチェックをすり抜けます(なのでCSRFが成立する可能性があります)。
例示されている手書きフォームのような場合$controller->dataが空になるためです。
そもそもヘルパー使ってない時点でまずいよねって話ではあるのですが「セキュリティコンポーネントをオンにして動いてるから安心」とならないパターンもありうるということで一応細かいことながら突っ込ませて頂きました。
なお、動作確認は1.3.13で行いましたが、1.3.6から該当箇所は変更がないので同じように動作すると思われます。
akiyan.com とは
個人サイト。管理人は秋田真宏。ニックネームは「akiyan」。
「今までの認識を覆(くつがえ)す、わかりやすい記事を書く」ことを目標にしているサイトです。話題の中心は生活とウェブ技術系です。
UberEATSの配達員をリリース当日にやってみた
iPhone の修理補償のためにAppleCare+や携行品保険に入ってはいけない
UR賃貸住宅が最強なことを惜しみなく紹介
あなたの知らない照明術
ためしてガッテンのカレー特集がすごい!
5泊5000円台の貸しふとんで、お客様用ふとんを持たない暮らし
ブログカテゴリ・月別一覧
エンターテイメント (199)
ビジネス・政治経済 (175)
生活・ライフスタイル (246)
2022-09-14 海岸や河川でバーベキューができるか調べる方法
2022-02-02 SequelizeでJSONフィールドをupdateする場合はsetメソッドを使う
2022-01-24 SwitchBotロックをSiriショートカットで「解錠」はできない
2022-01-04 テスラモデル3にTPMSセンサー無しで社外品ホイールとスタッドレスタイヤ を取り付けました
2022-01-01 サーフィンを始めました
2022-01-01 テスラモデル3ロングレンジに乗り換えたらアプデが楽しみになった
2021-12-29 歯列矯正を始めてからよく食べてるもの、完全食、フリーズドライお粥、豆腐 etc
2021-12-28 日光市ワーケーション補助金は最低1名から、申請はメールでOK
2021-11-19 2021年に買ってよかったもの
2021-08-12 自治体コロナワクチン予約は早朝チェックで最速で受けられる
akiyan.com 管理人メモ
自衛隊イラク日報 バグダッド日誌/バスラ日誌 一覧
エンコードマニアックス
オンラインCSS自動整形
はてなブックマーク人気エントリー
Copyright 1997,2022 akiyan.com, All rights reserved.