Railsでは、sessionメソッドで保存した情報は自動的に安全が保たれるが、cookiesメソッドに保存する情報は残念ながらそのようにはなっていない。特に、cookiesを永続化すると、セッションハイジャックという攻撃を受ける可能性がある。この攻撃は、記憶トークンを奪って、特定のユーザーになりすましてログインするというもので、以下の4つの方法がある。
(1) 管理の甘いネットワークを通過するネットワークパケットからパケットスニッファという特殊なソフトウェアで直接cookieを取り出す。
(2) データベースから記憶トークンを取り出す。
(3) クロスサイトスクリプティング (XSS) を使う。
(4) ユーザーがログインしているパソコンやスマホを直接操作してアクセスを奪い取る。
Railsチュートリアルでは、これらのセッションハイジャックに対して、以下の方法での対策を取っている。
(1) 管理の甘いネットワークを通過するネットワークパケットからパケットスニッファという特殊なソフトウェアで直接cookieを取り出す。
=> Secure Sockets Layer (SSL) をサイト全体に適用して、ネットワークデータを暗号化で保護し、パケットスニッファから読み取られないようにする。
(2) データベースから記憶トークンを取り出す。
=> 記憶トークンをそのままデータベースに保存するのではなく、記憶トークンのハッシュ値を保存するようにします。
(3) クロスサイトスクリプティング (XSS) を使う。
=> Railsによって自動的に対策が行われる。具体的には、ビューのテンプレートで入力した内容を、すべて自動的にエスケープする。
(4) ユーザーがログインしているパソコンやスマホを直接操作してアクセスを奪い取る。
=> さすがにシステム側での根本的な防衛手段を講じることは不可能だが、二次被害を最小限に留めることは可能。具体的には、ユーザーが (別端末などで) ログアウトしたときにトークンを必ず変更するようにし、セキュリティ上重要になる可能性のある情報を表示するときは、デジタル署名 (digital signature) を行うようにする。
また、これらのセキュリティ上の考慮事項を元に、Railsチュートリアルでは次の方針で永続的セッションを作成している。
- 記憶トークンにはランダムな文字列を生成して用いる。
- ブラウザのcookiesにトークンを保存するときには、有効期限を設定する。
- トークンはハッシュ値に変換してからデータベースに保存する。
- ブラウザのcookiesに保存するユーザーIDは暗号化しておく。
- 永続ユーザーIDを含むcookiesを受け取ったら、そのIDでデータベースを検索し、記憶トークンのcookiesがデータベース内のハッシュ値と一致することを確認する。
参考:Railsチュートリアル