CSRF については、一般に正規利用者の意図したリクエストであることを確認することが対策になります。いわゆる徳丸本で紹介されている、具体的な方法としては以下のとおりです。
- 秘密情報(トークン)の埋め込み
- パスワード再入力
- Referer のチェック
JSF には、この CSRF 対策のうち、最初の「トークンの埋め込み」が実装されています。JSF のうちの stateless view を利用していない場合という前提ですが、POST を使用しようとした場合、
javax.faces.ViewState
というキー名の hidden フィールドが自動的に埋め込まれ、その値が暗黙のうちに CSRF 対策トークンとして作用します。
逆に GET を使用した場合は、faces-config.xml
の protected-views
に対象ページを定義する前提で、同様のトークンがクエリパラメータとして付与されます。
これは、OWASP のいう CSRF 対策の以下のいずれか(たぶん前者)が使われています。
- Synchronizer (CSRF) Tokens
- Encrypted Token Pattern
ぼくはもともと、この javax.faces.ViewState
は純然たる CSRF 対策なんだろうと思っていたんですが、じつは CSRF は副次的な効果のようです。JSF (2.2) の仕様書には、以下のような記述があり、
javax.faces.ViewState
は「現在のビュー(current view) を表現する」ということが記述されています。
When a JavaServer Faces view is rendered, it will contain a hidden field with the identifier javax.faces.ViewState whose value contains the state for the current view.
JavaServer Faces Specification Version 2.2 14.1 Collecting and Encoding View State
この通り、JSF ではビューの状態を保存する際の ID、あるいは、保存したものそのものをこのフィールドに埋め込みます。結果、このフィールドの値が改竄された場合は、ビューを復元できない、という状況が発生し、結果として CSRF 対策になる、というもののようでした。