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:というか、「セッションを開始する」命令はあるけど、「新規セッションを作成する」という命令や「保存されているセッションを復元する」命令はないのが問題。切り分けられていれば、当然エラーを吐くようになっていただろう。