舞台裏

Qiita が表でこっちが裏。こっそりやっていく。

SessionManagementFilter の価値がようやくわかった気がする

Session Management について勉強開始。

翻訳は以前していた。

SessionManagementFilter

セッション管理するフィルター。

  • SecurityContextRepositorySecurityContext が無かったら何もしない
  • あったら Authentication を取り出す
  • Authenticaiton が匿名認証でない場合は、 SessionAuthenticationStrategyonAuthentication() が実行される
  • Authentication が null だったり匿名認証だったりした場合は、セッションタイムアウトしてないかチェックして、タイムアウトしてたら専用のハンドラ(InvalidSessionStrategy)に処理を委譲する

SessionAuthenticationStrategy

認証が行われた時のセッションに関する処理を提供する。
典型的なのはセッション固定化攻撃対策のためにセッションIDを変更する処理とか。

リファレンスにはデフォルト実装は SessionFixationProtectionStrategy って書いているけど、実際は実行環境のサーブレットのバージョンによって変わるっぽい。

3.1 未満なら SessionFixationProtectionStrategy で、3.1 以上なら ChangeSessionIdAuthenticationStrategy になるっぽい。
ChangeSessionIdAuthenticationStrategy の方は、 3.1 で追加された HttpServletRequest.changeSessionId() メソッドを使用している。

2つのクラスは AbstractSessionFixationProtectionStrategy を継承していて、結局メインの処理はこっちにある。

SessionManagementFilter の価値は?

SessionAuthenticationStrategyUsernamePasswordAuthenticationFilter でログインに成功したときにも利用されている。
セッション固定化攻撃対策のためのセッションID振り直しはそのときに行われていて、 SessionManagementFilter では結局行われていない。
じゃあ、 SessionManagerMentFilter の価値は???

リファレンスには、 Remember-Me や Pre-Authentication のような非対話型のログイン処理が行われた時に働くっぽい。
たしかに、 Remember-Me のときは動作していた。

※Pre-Authetication とは、別の認証システムによってすでに認証済みのユーザがアクセスしてきたようなケース

SessionManagementFilter の価値

以下は、全て推測

  • なぜ SessionStorategy の処理は UsernamePasswordAuthenticationFilterSessionManagementFilter の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 がその役割を担っていることになっている

と思う。