Session Management について勉強開始。
翻訳は以前していた。
SessionManagementFilter
セッション管理するフィルター。
SecurityContextRepository
にSecurityContext
が無かったら何もしない- あったら
Authentication
を取り出す Authenticaiton
が匿名認証でない場合は、SessionAuthenticationStrategy
のonAuthentication()
が実行されるAuthentication
が null だったり匿名認証だったりした場合は、セッションタイムアウトしてないかチェックして、タイムアウトしてたら専用のハンドラ(InvalidSessionStrategy
)に処理を委譲する
SessionAuthenticationStrategy
認証が行われた時のセッションに関する処理を提供する。
典型的なのはセッション固定化攻撃対策のためにセッションIDを変更する処理とか。
リファレンスにはデフォルト実装は SessionFixationProtectionStrategy
って書いているけど、実際は実行環境のサーブレットのバージョンによって変わるっぽい。
3.1 未満なら SessionFixationProtectionStrategy
で、3.1 以上なら ChangeSessionIdAuthenticationStrategy
になるっぽい。
ChangeSessionIdAuthenticationStrategy
の方は、 3.1 で追加された HttpServletRequest.changeSessionId()
メソッドを使用している。
2つのクラスは AbstractSessionFixationProtectionStrategy
を継承していて、結局メインの処理はこっちにある。
SessionManagementFilter の価値は?
SessionAuthenticationStrategy
は UsernamePasswordAuthenticationFilter
でログインに成功したときにも利用されている。
セッション固定化攻撃対策のためのセッションID振り直しはそのときに行われていて、 SessionManagementFilter
では結局行われていない。
じゃあ、 SessionManagerMentFilter
の価値は???
リファレンスには、 Remember-Me や Pre-Authentication のような非対話型のログイン処理が行われた時に働くっぽい。
たしかに、 Remember-Me のときは動作していた。
※Pre-Authetication とは、別の認証システムによってすでに認証済みのユーザがアクセスしてきたようなケース
SessionManagementFilter の価値
以下は、全て推測
- なぜ
SessionStorategy
の処理はUsernamePasswordAuthenticationFilter
とSessionManagementFilter
の2か所で実行されているのか?UsernamePasswordAuthenticationFilter
の方は、ログインに成功するとすぐにリダイレクトを実行してしまい、後続処理が実行されない(SessionManagementFilter
が呼ばれない)ため。
- なぜ Remember-Me の認証が完了したあとに、
UsernamePasswordAuthenticationFilter
のように独自でSessionStorategy
の処理が呼ばれないのか?UsernamePasswordAuthenticationFilter
がリダイレクトするという点で特殊なため- Remember-Me や Pre-Authentication は認証終了後リダイレクトはしないっぽい
- よって後続の
SessionManagementFilter
が実行される - なので、個々の処理で個別に
SessionStorategy
を呼ぶのではなく、SessionManagementFilter
で漏れなく呼ぶようにしていると思われる
UsernamePasswordAuthenticationFilter
の前にSessionManagementFilter
がくるように並べれば、UsernamePasswordAuthenticationFilter
もカバーできるのでは?- ログイン成功後に実行しなければならない処理なので、それより前にあっては本末転倒
- Remember-Me でもセッション固定化攻撃ってあるの?
- 実際やってみたら、できた
- 攻撃者が A のブラウザでログイン画面にアクセス(セッションID_1 が発行される)
- 被害者が B のブラウザで Remember-Me を有効にしてログイン
- 被害者のブラウザに保存されたセッションID を、攻撃者がセッションID_1 で置き換える
- 何も知らない被害者がアプリにアクセスすると、 Remember-Me による自動ログインが実行される
- アプリはセッション情報のないセッションID が渡ってきたと思い、普通に Remember-Me の認証を実行する
- Remember-Me 認証が成功して、セッションID_1 が正規のセッションID になる
- 攻撃者はセッションID_1 でアプリにアクセスする
- 攻撃者のブラウザは被害者がログインしたときのセッションで表示される
- ということで、 Remember-Me の自動認証が成功したときもセッションID は振りなおす必要があり、
SessionManagementFilter
がその役割を担っていることになっている
と思う。