年末年始でセキュリティ分野を学習し、年明けにウェブ・セキュリティ基礎試験(通称:徳丸基礎試験)を受験することにしました。
そこで勉強した内容を備忘録として残します。
今回はセッションハイジャックについて、概要や原因・一般的な対策をまとめます。
セッションハイジャックとは何なのか?
セッションハイジャックとは、第三者がサービス利用者のセッションIDを悪用して利用者に成り済ますことです。
第三者が利用者のセッションIDを知る方法として次の3つがあります。
- セッションIDの推測:
セッションIDの生成方法に規則性を見つけて利用者のセッションIDを推測する方法 - セッションIDの盗用:
Webアプリの脆弱性を突いて外部からセッションIDを盗み出す方法 - セッションIDの固定化:
攻撃者が用意したセッションIDを利用者のブラウザに強制的に設定する方法
セッションハイジャックはどこでどうやって発生するのか?
↑に書いたセッションハイジャックの3つの方法それぞれの原因を順番に解説します。
セッションIDの推測
セッションIDの推測は、セッションIDの生成ロジックが単純なアルゴリズムの場合に起こりえます。
セッションIDはユーザID・IPアドレス・日時・乱数などを組み合わせたり加工したりして生成されることが多いです。
そのうちユーザIDや日時などは外部からでも推測可能なため、脆弱性の原因となりうるのです。
セッションIDの盗用
XSSやHTTPヘッダ・インジェクションなどの攻撃によりセッションIDが盗まれるのが典型的です。
なおXSSについては以下の記事で別途まとめています。HTTPヘッダ・インジェクションも後でまとめる予定です。
これらの攻撃以外に、URLにセッションIDを埋め込んで管理している場合も盗まれるリスクに晒されてしまいます。
Refererヘッダを経由してURLを外部から確認できるからです。
そのためURLにセッションIDを含めてしまうと、RefererによってセッションIDも外部サイトへ漏洩していることになります。
攻撃者はそのRefererを元に利用者のセッションIDを特定できちゃうんです。
セッションIDの固定化
セッションIDの固定化は、セッションIDを外部から強制できてしまうことが根本的な原因です。
ただし現実的にはセッションIDの強制そのものは防ぎきれません。理由は以下のとおりです。
- 攻撃手法が多岐にわたる
- ユーザー自身がセッションの固定化を誘発してしまうこともある(信頼できないソースのリンクをクリックなど)
- セッションIDの正当性をサーバー側では判別できない
だから外部からのセッションIDの強制が発生したとしてもセッションハイジャックを防ぐ対策が必要となります。
セッションハイジャックはどうやったら防げるのか?
おさらいですが、セッションハイジャックが起きる要因として以下の3つがあります。
- セッションIDの推測:
セッションIDの生成方法に規則性を見つけて利用者のセッションIDを推測する方法 - セッションIDの盗用:
Webアプリの脆弱性を突いて外部からセッションIDを盗み出す方法 - セッションIDの固定化:
攻撃者が用意したセッションIDを利用者のブラウザに強制的に設定する方法
3つそれぞれの対策について書いてみます。
セッションIDの推測の対策
セッションIDの推測を防ぐためには、セッション管理の機能をWebサービス側で自作せず、フレームワークやライブラリが提供する機能を使うことが最大の対策です。
自前で隙のないセッションID生成・管理の機能を実装するのは技術的にかなり難易度が高く、時間もかかるしリスクも大きいからです。
Ruby on RailsやDjangoなどをはじめとする多くのフレームワークはセッション管理の機能を標準的に備えています。
これを活用するのが安全性・効率性の観点でベストです。
どうしても自前で作るのであれば、暗号論的擬似乱数生成器(予測困難な乱数生成器のイメージ)を使って十分な桁数のセッションIDを生成するしかありません。
しかし、繰り返しになりますが、自前でセッション管理の機能を作るのはとても危険です。
セッションIDの盗用の対策
セッションIDの盗用を防ぐには、URLにセッションIDを埋め込まず、Cookieへ格納することが有効です。
そうすればRefererにセッションIDも含まれないためURLからセッションIDが盗まれることはありません。
セッションIDの固定化の対策
セッションIDの固定化を防ぐための対策として、ログイン後にセッションIDを変更することが一般的です。
認証に成功した後でセッションIDを変更してしまえば、その前段階で攻撃者があらかじめ設定したセッションIDを無効化できるからです。
もしも開発言語やミドルウェアの都合でセッションIDの変更ができない場合は、トークンを使用してセッションハイジャック対策を施すことも可能です。
トークンはログイン時に生成され、ブラウザのクッキーやローカルストレージとサーバー側のセッションの両方に保存されます。
そしてログイン時にはサーバーへのリクエストにトークンも含め、リクエスト側のトークンとサーバー側のトークンが一致するか確認します。
そのため外部からセッションIDを強制されても、そのセッションIDからトークンを知ることはできないため、セッションハイジャックを防止できるのです。
また認証前にセッションを使っているとセッションIDの固定化を完全に対策することはできません。
なので、ログイン前にはセッション管理機能を使わず、hiddenパラメータで秘密情報を管理することが望ましいです。
とはいえ現実的には認証前でもセッションを使わないとユーザー体験に影響が出てしまうケースもあるため、その場合はセッションに秘密情報をセットするたびにセッションIDを変更することが対策となります。
まとめ
セッションハイジャックの概要と対策について理解できました。
コメント