2013年5月14日
CSRFDefender的なやつでコンテンツフィルタはしないほうがいいんじゃないかという話
本日の組長のお話。
Ark::Plugin::CSRFDfenderに機能追加したりいろいろバグっていたりしたのに手を入れていたのだが、それに対して組長に意見を頂いた話。結論はタイトルの通り。
CSRF対策をフレームワーク側で入れるのは良いと思うが、フィルタしてformに自動的にhiddenを埋め込むのはあんまよろしくないんじゃないかという話です。
CSRFDefender的なやつには以下のような機能があるが、それぞれに関して述べる。
- POST, PUT, DELETE時に自動でtokenチェックしてエラー画面強制表示
- 自動的にコンテンツフィルタしてform要素にhiddenを埋め込む
POST, PUT, DELETE時に自動でtokenチェックしてエラー画面強制表示
OK。安全側に倒している。
自動的にコンテンツフィルタしてform要素にhiddenを埋め込む
あまり好ましくない。厳密に安全側に倒すのが難しい。
例えば、formのaction要素に外部URLが入っていた場合に簡単にtokenが外部サイトに漏洩してしまう危険性がある。(例えば検索窓など)
- methodがGETのフォームはフレームワーク側でフィルタしない
- 外部URLに直接POST指定とかするな!
という話ではあるが、意図しない使い方をされることで逆に危険になるような設計は好ましくない。
form.actionはJSで上書きもできてしまうので、フィルタ処理側でそのformがhiddenを埋め込むべきか否かを厳密に判断するのは実質不可能に近い。
どうするのが良いのか?
自動tokenチェックをしてCSRFエラー画面で「あなたの予想に反して、このページが見えているでしょうか?」的なことと対応ガイドラインが表示されるようになっていれば、hidden漏れに開発時に気づける。ので、開発者が手でhiddenを都度埋め込めば良い。そのためのヘルパー関数をpluginが準備しておくのも良いと思います。
コンテンツフィルタ機能は便利っちゃあ便利なので、リスクを承知した上で、その機能 をオンできるようになっているのは有りだとは思いますが、デフォルトでその挙動になってるのは危ないんじゃでしょうか。
Ark::Plugin::CSRFDefenderは非互換にはなりますがその方向で修正する予定です。
余談ですが、csrf_tokenはsession_idで十分だという話もあったりますが、上記のように漏洩リスクがあるので、session_idを元にハッシュ化したものをtokenにしたりする方が良いのかなとかなんとなく思いました。
【追記】tokuhiromにそもそも漏れても問題ないようなtokenを使ったほうが良いんじゃないかという指摘をもらいました。それならば、自動的にコンテンツフィルタを入れていて、tokenが漏れたとしても大きな問題にならないので。こういう機能において、漏れては困るようなtokenを埋める処理を入れるのが筋悪って話ですね。
結論
めんどうくさいWebセキュリティ