スクリプトインジェクションや盗聴によりセッションIDを盗んで利用するまでにはある程度時間が必要です。セッションIDの有効期限が短ければ、セッションIDが悪用される前に有効期限が切れて悪用できない可能性が高くなります。
しかし、セッションIDの有効期限が短すぎると、フォームの入力中に有効期限が切れてしまう等の問題が発生します。一般的なWebサイトであれば30から60分前後で有効期限が切れるようにするとよいでしょう。
PHPの場合、「セッションIDの有効期限切れ=ユーザセッションの無効化」をしなくてもセッションIDを変更できるsession_regenerate_id関数が用意されています。
- session_regenerate_id関数
- bool session_regenerate_id ( [ bool delete_old_session ] )
例えば、Web開発フレームワークCakePHPのセッション管理機構には、リクエストのたびにセッションIDを変更するオプションがあります。この場合、セッションIDはリクエストのたびにsession_regenerate_id関数により変更されます。利用されたIDは使い捨てのIDとなり、万が一盗まれても悪用される可能性が非常に少なくなります。仮に悪用された場合でも、ユーザのセッションが切れるので、悪用された可能性があることも分かります。
ただし、ユーザがWebアプリケーションを利用している最中にセッションIDを変更すると問題が発生する場合もあるので注意が必要です。例えば、クロスサイトリクエストフォージェリを防止する簡易な方法としてセッションIDを利用している場合、セッションIDがリクエストのたびに変更されるとアプリケーションが動作しなくなります。セッションIDがフォーム送信前後で変わると正規のユーザが送信したリクエストでも不正なリクエストとして処理されてしまいます。
セッションIDをクロスサイトリクエストフォージェリ対策に利用しているアプリケーションの場合、セッションID自体を一意なカギとして利用するのではなく、セッション変数として保存した十分に長いランダム文字列を一意なカギとして利用するようアプリケーションを改修すると、セッションIDを頻繁に変更できるようになります。
当たり前のことですが、ログインした際には必ず新しいセッションIDを利用するようにします。PHPのセッション管理機構はセッションの固定化の一種であるセッションアダプションに脆弱なので、ログイン時にセッションIDを変更しないと簡単にセッションを乗っ取られてしまう可能性があります。
最後に、ログアウト機能は必須です。ログアウトした場合、セッションを破棄します。自動ログイン機能を実装している場合、自動ログイン用の鍵も一緒に削除すべきです。ログアウト機能がない場合、共有PCやブラウザを借りた場合に自分のセッション情報の削除ができないと盗聴などにより被害にあう可能性が高くなります。
対策のまとめ
- セッションIDは出来る限り頻繁に変更する
- ログイン時には必ず新しいセッションIDを割り当てる
- ログアウトした場合は必ずセッションIDを無効化する
- 上位ドメインのクッキーを削除してもよい場合は削除する
- セッションアダプションに脆弱でないセッション管理機構を使用する
- セッションIDをCSRF対策に利用しない
- ログアウトを実装し、セッションを破棄する