PHPのセッション固定攻撃
英語でSession Fixationというらしいのだが、正確にはSession ID Fixation(セッションID固定攻撃)だと思う。
セッションを固定?というのではほとんど意味が通じないのだが、要するに「セッションIDを攻撃者が決めた値になるように固定してしまう」ことで「セッションIDを盗むのと同じ結果」が得られるというもの。
PHPの標準セッション管理は「ユーザーがIDを渡すとそのIDが未使用でもそのまま使ってしまう」ので、注意しないとセッションIDを固定されてしまう。
一番ひどい場合はGET変数でセッション名と値の組を送られただけで固定されるし、セッションIDの送信をクッキーのみに限定しても手順を踏めばやっぱり固定できる。
セッションの開始時に「指定されたIDのセッションはない」という返答を返してくれないのが一番の問題。普通に指定されたIDで新しいセッションを作ってしまう。*1
どうも簡単な対処方法はないようなので、私は「セッションを新規作成する際にセッション変数に一定の形でデータを書き込む」ことにしている。
セッションを開始したらまずそのデータを確認し、データがあれば続行する。データがない場合は一度セッションIDを再生成したあと、既定のデータを配置して続行する。
正常に新規作成されたセッションではセッション変数にそのデータが存在するが、外から与えられたセッションIDではセッション変数は空になっている。これを利用して固定されていないかどうかを確認するわけだ。セッションIDを固定しようとする試みがあっても、それをスルーして別のセッションIDで処理を始めてしまうわけだ。
まぁ、そのためだけに変なセッション変数を作るのも馬鹿らしいので、セッションの初期化時に「アクセス元のIPアドレス」等のアクセス制御に必要な情報を書き込むことにしてある。
そういう情報なら「ユーザーからのデータで上書きされる」ような操作を書いてしまうことがないので、まぁ安全。
実装の内容がばれていれば、同じhttpdで稼働する別のアプリケーションからダミーのデータを送り込まれる可能性があるが…それは既にセッション固定攻撃じゃない(笑)
*1:というか、「セッションを開始する」命令はあるけど、「新規セッションを作成する」という命令や「保存されているセッションを復元する」命令はないのが問題。切り分けられていれば、当然エラーを吐くようになっていただろう。