| « PHP 5.1/4.4用のセキュリティパッチ | Google Source Code Bug Finder » |
ログイン後にsession_regenerate_id()を実行するだけで十分か?
忙し過ぎてタイムリーにブログが書けないです。最近セッション管理の問題が一部で話題になっていました。そこの中に以下のような議論がありました。
ログイン後にsession_regenerate_id()を実行すれば外部からのセッションIDを受け入れても安全
確かにログイン後のセッションIDは本来セッションIDが持つべき属性
- 一意な値であること
- 第三者に予測不可能であること
を持っています。
しかし、ログイン後にセッションIDを再生成するだけでは不十分な場合は2つ直ぐに思いつきます。
- CSRF(XSRF)防御にセッションID(だけ)を利用している場合
- 外部に出力したデータの改ざん防止にセッションID(だけ)を利用している場合
これらの仕組みはログイン後にのみ利用する機能ではありません。フォーム送信は認証無しで行うことは多いです。ウィザード型の入力フォーム(検証済みの前のページの入力値を次ページに保存する方法が最も柔軟な処理方法)も認証前に使用されます。
私はCSRF(XSRF)防御にはフォームに予測不可な一意なIDを割り当てる方式を、検証済みデータの改ざん防止にはセッションID+マジック文字列(予測できない秘密の文字列)を利用しています。CSRF(XSRF)対策には影響ないですし、セッションIDを利用してセキュリティを維持する仕組みであっても必ずマジック文字列を使用しているので危険な状態にはなりません。しかし、全てのアプリケーションがこのような対策を取っているとは思えないので外部からのセッションIDを受け付けない厳格なセッションID管理を導入するのはセキュリティ上意味があります。
ほとんどのアプリケーションはログイン後にsession_regenerat_id()を実行するだけで十分な安全性を確保することが可能ですが一部のアプリケーションはそれでは不十分であることは知っておいたほうが良いと思います。
追記:2001年からウィザード型フォームで前のページのデータを安全に保存するため等に利用できる関数をZendのコードギャラリに載せています。ウィザード型フォームはこのような関数を使用し検証済みの値のメッセージダイジェストを取っておけと繰り返し入力値を検証する必要性がなくなります。
4 コメント
どの辺りで折り合いつけるかは難しい。
サイトのドメイン名によるのでしょうが。
つまり意図的に設定されたIDでのセッションは偶然IDが一致しない限り同じセッションは盗めません。ただし、アプリケーションが対応していないとセッションが開始できないのでDoSは可能になります。
昔、TLDがcom, net, org, edu, milくらいだった頃を想定してブラウザの仕様が決まっている&下位ドメインが設定したクッキーを無視して上位ドメインのクッキーを送る、という状態が悪いのです。明らかにセキュリティ上問題な仕様なのですけど随分長いあいだ放置されています...
# この問題、修正される前に攻撃用のための知識が
# 広がりすぎるとDoSやセッションハイジャックが
# 横行しそうなので静かにしておいたほうが良い
# ような気が....
# とりあえずccTLDユーザ、共有サーバユーザでサ
# ブドメインだけ違うユーザは要注意、とここに書
# いても効果薄いですよね....
# SESSIONモジュール用のmore strict session patchでも
# 書くかな...
# setcookie('PHPSESSID','',0, '/', 'co.jp');
# と同等コードを付けるだけなので。
> いくらセッションIDを設定できてもクライアント側で
> 設定したセッションIDではセッションは開始されません。
そんなことありません。攻撃者がサーバから有効なセッションIDを取得して、それを被害者のブラウザに設定するのです。そのシナリオが session fixation の基本形ですよ。