Edited at

一部報道による「Ruby on Railsにcookie保存関連の脆弱性」について

More than 5 years have passed since last update.

ITmediaの記事が微妙だったので調べて見たのん。(面倒なので箇条書き)


元ネタ


何が問題とされているか (記事の主張)


  • デフォルトでは、cookieにセッションのハッシュ (データ) を保持している。(CookieStore)


    • Rails 2-3の場合は秘密鍵で署名されている = 書き換え不可

    • Rails 4の場合は暗号化されている = 書き換え・内容の読み取り不可



  • Cookieを読み取られる可能性がある。


    • XSS

    • セッションサイドジャッキング: うっかりSSLではない通信をさせると、Rails3以前では機密情報が漏洩する可能性がある。(Kickstarter など)



  • Cookieに保持されたセッション情報を破棄する手段が無い。


    • サーバ側で無効にしたつもりでも、悪意あるクライアントが古いcookieをセットした場合には (デフォルトだと) 有効なものとして扱ってしまう。

    • 暗号化された状態のcookieをそのまま送るだけで良い (復号する必要は無い)




CookieStoreが問題なのか?


  • XSSやセッションサイドジャッキングは、そもそもCookieStoreの問題では無い。


    • 暗号化されていたとしても、cookieに直接機密情報を保存すること自体はあまり良くない。

    • ちなみに、Rails 3以降でHttpOnlyがデフォルトのため、XSSでセッション情報を読み取ることはできない。



  • 他のsession_storeを使用した場合でも、サーバ側でセッションを無効化する仕組みは用意されているわけでは無い。


    • サーバが破棄したつもりのcookieを送信して、セッションを続けることができる

    • 期限切れの仕組みは自前で処理する必要がある (多分)



  • session_store に設定する :expire_after オプションは、cookie の有効期限を設定するだけで、session_store内のデータを無効化しない

CookieStoreの問題ではなく、無効化するべきセッションを正しく破棄していないという問題。


結論


  • session_store として何を使うかにかかわらず、クライアントがcookieを保持し続ける可能性を考慮してセッション処理を行う必要がある。

  • 適切にセッションを破棄する必要がある。


    • 最終アクセスから一定期間経過していた場合 (期限切れ処理)


      • 定期的に掃除ジョブを流す (cf. Session Expiry, Ruby on Rails Security Guide)

      • セッション取得時に期限切れのチェックをする


        • active_record_storeを使う場合は、ActionDispatch::Session::ActiveRecordStore を継承して、get_session 内に updated_at をチェックする処理を入れるなど。(他に良い方法があるかも?)



      • memcached で有効期限を設定する (Passengerを利用する場合は注意)

      • セッションのハッシュ内に最終アクセス日時や期限切れ日時を入れて、アクセスごとにチェックする e.g. session[:last_access] = DateTime.now (メタ情報を入れるのはスマートさに欠けるかも)



    • ログアウトした場合

    • パスワードを再設定した場合 (同一ユーザの全セッションを破棄)



デフォルト設定に難があるので、これは脆弱性と言われても仕方ないかもしれない。

CookieStoreを使っていてもセッションを破棄することはできるが、かなり面倒な処理になる。(多分) その際サーバにデータを保存することは必要なので、最初からactive_record_storeやmemcached_storeなどを使った方が良いと思う。


まとめ


  • CookieStoreちゃんのファンやめます

  • このあたり簡単に処理してくれるgem無いかなー (他力本願)


    • Rails側に破棄の仕組みが入るのが筋なんだろうけど。