RESTfulなWebアプリのCSRF対策について考える
『安全なウェブサイトの作り方 改訂第3版』(PDF)によれば、CSRF脆弱性の根本的解決策は下記の3つしかありません。
- 処理を実行するページを POST メソッドでアクセスするようにし、その「hidden パラメータ」に秘密情報が挿入されるよう、前のページを自動生成して、実行ページではその値が正しい場合のみ処理を実行するようにする。
- 処理を実行する直前のページで再度パスワードの入力を求め、実行ページでは、入力されたパスワードが正しい場合のみ処理を実行するようにする
- Referer が正しいリンク元かを確認し、正しい場合のみ処理を実行するようにする
個人的には1が魅力的です。2と3はユーザビリティの低下が気になります(3はRefererを送信しないクライアントが排除されてしまう)。
ところが、RESTfulであろうとすると、1はステートフルなので採用がためらわれます(後のリクエストが前のリクエストに依存する。また、クライアントごとの機密情報をサーバが保持しなければならない)。ユーザビリティを犠牲にして、2か3を採用するのがREST的には正しそうです。
ところで、rest-discuss MLに:
CSRF is a both a browser and application security hole, but we (app devs) can only close the application hole. The browser is unsafe and will be for the immediate future, our best choice is too not rely on ambient authority and (if we want to remain RESTful) use unguessable URIs and HATEOAS.
という投稿もありましたが、クライアントごとに推測不可能なURIを割り当てたところで、その識別情報はサーバが保持するわけでしょう。結局、ステートフルになります。それで良いなら、1で充分な気がします。
追記(2008-05-27)
あ、そうだ。おかしな思いつきかもしれませんが、AtomPubではCSRFを考慮しないんだろうか。クライアントの実装によっては起きうると思うんですが…。そんなヘボいクライアントは誰も作らないかな。