PHPのセッション管理はセッションの固定化(Session Fixation)に脆弱であることは広く知れらていると思っていました。先日、php-users(ja)のMLに「Hardened PHPプロジェクトのStefanさんのパッチにSQLite Sessionモジュール用のセッションセーブハンドラパッチを追加したパッチを公開しました」と投稿しました。しかし、ダウンロード数等から推測するとセッションの固定化のリスクが正しく認識されていないのではないかと思えます。
セッション固定化のリスクを分かりやすく説明するには具体的な攻撃のシナリオを紹介した方がわかり易いのでいくつか説明します。以下の説明はデフォルト状態のPHPインストールでSession Fixation対策を行っていないのPHPアプリケーションに対して可能な攻撃の一例です。
1. メールによる攻撃
PHPアプリケーションで作成されたアカウントの乗っ取りは非常に簡単です。例えば、攻撃対象のアプリケーションのURLが
http://example.jp/
だとします。このページはセッション管理が必要なページだとします。攻撃者は
http://example.jp/?PHPSESSID=abcdefg
の様なURLをメールに送信し攻撃対象者にクリックさせます。これだけでセッションIDが
abcdefgになります。攻撃対象者がこのサイトのアプリケーションにログインするとabcdefgがセッションIDになるので攻撃者もセッションIDをabcdefgに設定してアクセスするだけで攻撃対象者のアカウントでWebサイトを利用できるようになります。
2. WebのURLによる攻撃
ログインが必要なサイトのURLが次のURLだとします。
http://example.com/login/
攻撃者はURLにセッションIDを記述したURLリンクを作成します。
http://example.com/login/?PHPSESSID=abcdefg
攻撃対象者がこのリンクをクリックするとセッションIDがabcdefgに設定されているので攻撃者はこのセッションIDを利用してサイトにアクセスできるようになります。
攻撃手法2を利用した場合、複数のユーザが同じセッションIDになってしまい攻撃されている事が直ぐに判明してしまうのでは?と思われるかも知れません。攻撃者が攻撃に利用するサイトでセッション管理を行い、各ユーザ毎に別のセッションID(攻撃者が生成したID)を割り当てれば同じユーザが同じセッションIDにならないので攻撃されている事は分からなくなります。攻撃者は既に判明しているセッションIDが利用可能(アカウントが乗っ取れる状態。つまり攻撃対象がログインしていないか)になっていないか後で確認するだけです。
http://wiki.ohgaki.net/index.php?PHP%2Fpatch%2FStrictSession
のパッチは上記の攻撃全てを防ぐ事が可能なパッチなのですが、このブログを書いた時点では30ダウンロード(そのうち2回くらいは自分自身)しかありません。
自分の作ったアプリケーションでは独自に保護しているのでPHPのセッション管理がセッションの固定化に脆弱であっても影響を受けませんが、全てのPHPユーザが同じような対策を行っているとは思えません。オープンソースのPHPアプリケーションのほとんどがセッションIDの固定化攻撃に対して全く防御対策を施していない事からも多くのPHPアプリケーションがセッションID固定化に脆弱な状態で運用されていると容易に予想できます。
セッションIDの固定化に脆弱なPHPアプリケーションを利用している友人や同僚のアカウントを拝借する(特定のターゲットを目的とするスピアフィッシングですね)のは非常に簡単です。
もしかして私の予想に反して多くのPHPユーザはPHPがセッションIDの固定化問題に対処済みなのでしょうか?それともほとんどのユーザはPHP4?
追記:
ログイン後にのみ重要なデータを参照したり処理するアプリ(普通のアプリはそうだとは思いますが)の場合、ログイン後にsession_regenerate_id()でセッションIDを作り直せばログイン後のセッションは保護されるのでセキュリティ上の問題はほぼ発生しません。session_regenerate_id()は比較的最近に実装された関数ですが、この為に作られています。このパッチはURLのセッションIDは全て受け入れたくない場合に有効です。