CakePHP1.3系でhttpsを経由するととセッションIDの再作成が出来ない問題の対応方法

問題点

CakePHP1.3系ではSecurity.levelをhighに設定するとセッション固定化攻撃対策のためのセッションIDの再作成(regenerate)が行われますが、その際にhttps→httpというページ遷移を行うとセッションが切れてログアウトしてしまいます。

理由はhttpsでアクセスされた場合、(Security.level等の設定に関係なく)CakeSessionクラス内でiniを書き換え自動的にsecure属性を付加しているからです。


// cake/libs/cake_session.php 475あたり
if ($iniSet && env('HTTPS')) {
    ini_set('session.cookie_secure', 1);
}

このため、regenerateされたタイミングで発行されたセッションクッキーは次にhttpのページが表示された際にサーバー側に送られず、セッションが切れてしまいます。

すべてのページがhttpsでアクセス出来るのであれば問題ないのですが、諸々の事情によりログイン画面等必要な部分のみhttpsでアクセスしたい場合上記の問題が発生します。

Security.levelをlowまたはmediumに設定すれば、httpアクセス時に発行されたセッションIDが使い続けられるので結果的にセッションは切れずに済むのですが、同じセッションIDが使い続けられるため、セッション固定化攻撃を受けた際のセキュリティリスクが高くなります。

対応方法

上述の挙動は全てcake/libs/cake_session.phpに書かれているため、コアクラスの挙動を上書きする必要があります。
とはいえ、コアクラスを書き換えるのは望ましくないため、こちらで記述されている方法を使ってapp以下に配置した同クラスで上書きします。

(参考)CakePHP フレームワークのソースをapp/で置き換える – Shin x blog

cake/libs/cake_session.phpをapp/libs/cake_session.phpにコピーした上で、app/config/bootstrap.phpに以下のコードを追加します。


App::import('Core', 'CakeSession', array('file' => APPLIBS .'cake_session.php'));

そして、コピーしたapp/libs/cake_session.phpを編集して以下の部分を修正します。


// 上述のsecure属性の付加をコメントアウト
//       if ($iniSet && env('HTTPS')) {
//           ini_set('session.cookie_secure', 1);
//      }

これにより、httpsで発行したセッション管理用クッキーがhttpでのアクセスでも送出されるようになり、regenerateを行いつつセッションを維持することが可能となります。
(もちろんhttpsで発行した別のクッキー情報もhttpで送られてしまうため、こちらは別途セキュリティを考慮する必要があります)

セッション用クッキーの生存期間

上述の問題とは関係ないのですが、Security.levelをhighに設定した場合、セッション用クッキーの生存期間は強制的に0(つまり同セッション内、通常はブラウザが閉じられるまで)に設定されます。

コメントには

‘high’   Session timeout in ‘Session.timeout’ x 10

と書かれているのですがソース上は下記のようになっています。


if ($this->security == 'high') {
    $this->cookieLifeTime = 0;
} else {
    $this->cookieLifeTime = Configure::read('Session.timeout') * (Security::inactiveMins() * 60);
}

セッションの保持期間はSession.timeout×セキュリティレベルに応じた値となってますが、highの場合は上述のコードにより、セッションクッキーの生存期間が強制的に同一セッション内のみに設定されます。

このあたりも要件に応じて変更するといいかもしれません。

まとめ

・cake1.3系(少なくとも1.3.6〜1.3.13までセッションまわりは同じ実装になっているのを確認しました)に於いては、httpsを部分的に使用したWebServiceの場合、regenerateと相性が悪いです。

・挙動を変更するためにはcake_sessionを上書きする必要があります。

・セッションクッキーを守るためには本来的にはセッションを使用する部分はすべてhttpsアクセスにしてセキュア属性をつけるべきですが、諸々の理由により一部分のみhttps実装になっている場合は上述のような対策を取る方がまだセキュアだと考えられます

cake1.3系に於いて「よくわからないけどとりあえずセキュリティレベルをmediumにしたら動いた」的なエントリを割と見かけるので一つのアプローチとして本エントリを書いてみました。
個人的にはクッキーやセッションに関する挙動はあまりフレームワークに上書きして欲しくないな、と思っているのですが、Cake2系ではこのあたりの挙動もだいぶ変わっているようなので必要があれば調べてみたいと思います。

最後に、セキュリティに関する問題はセンシティブなものだと考えておりますので、本エントリに関する間違いや違ったアプローチなど、是非突っ込みを頂ければと思います。


Tags: ,

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>