最近になってセッション変数を使用したアプリケーションを見かけるケースが増えてきている。セッション変数とは,セッションIDとひも付けてサーバー側に格納する変数のことである。開発環境により実装の仕方は様々だが,ログイン成功時に保存される認証情報もセッション変数の一つである。

 セッション変数をサーバーに格納すると,アプリケーションはセッションが有効な間,変数の値を再利用できる。これにより,例えばクライアントから送信された大量の入力項目をサーバー上で保持しながら複数の画面を遷移するようなアプリケーションを比較的容易に,かつ低コストで実装できるようになる。

 筆者がアプリケーションの開発現場にいたころは,サーバー・リソースを圧迫するという理由から使用を控えていることが多かったが,マシン・スペックの向上や,アプリケーションに要求される機能の複雑さの向上といった背景により事情が変わってきているようだ。

 実はクッキーと関連して,このセッション変数もセキュリティの配慮が欠かせない。Webページ間でデータを受け渡すアプリケーションを作る場合,セッション変数の代わりにブラウザのフォーム(hidden領域)入力を使う方法がある。こうした方法に比べて「セッション変数は安全」と言われることがある。ただ,セッション管理の原理からすると,一概にそうとは言い切れない。

 クライアントから送信されるデータがセッション変数に格納された際,その値が奪われることはないか,改ざんされることはないかといった点に注意しなければならない。

ログイン処理以外でも危険性があるセッション・フィクセーション

 例えば,第3回で解説したCookieMonsterの対象となるドメイン上では,セッション・フィクセーションによってセッション情報を奪われる可能性がある。以下に,新規ユーザー登録機能で発生する問題を挙げよう(図1)。セッション・フィクセーションのぜい弱性は一般的にログイン機能と関連した問題だと認識されているが,セッション変数を利用したアプリケーションでは,ログインしていない状態であっても問題が発生するケースがある。

図1●セッション変数を使うアプリケーションの例
図1●セッション変数を使うアプリケーションの例

 図1の新規ユーザー登録機能は,次のようなフローで構成される。

1. トップページへのアクセス時に,サーバーがセッションIDを発行する
2. ユーザーが新規ユーザー登録画面にアクセスする
3-1. 入力後,ユーザーが確認画面に遷移したときにユーザーが入力した情報をセッション変数に格納する
3-2. 入力エラー発生時や,「戻る」ボタンが押されたときは,入力画面に戻り,セッション変数に格納されている値を入力欄に表示する
4. セッション変数に格納された情報を使用して登録処理を実行する

 この場合,攻撃者は以下の罠をしかけることが可能である。
1. 攻撃者がトップページにアクセスし有効なセッションIDを取得する
2. 攻撃者がユーザーに,取得したセッションIDをセットして新規ユーザー登録画面へ誘導する罠をしかける
3. 罠にかかったユーザーが個人情報を入力する
4. 攻撃者が入力画面へアクセスし,ユーザーが入力した個人情報を閲覧する

 実際の被害の程度はアプリケーションの仕様に依存する。ただ,少なくとも個人情報を登録するようなアプリケーションではリスクの認識と対策が必要であると言える。

 対策は,セッション変数に変更が発生したらセッションIDを変化させ値を移し替えることである。変更されたセッションIDは,ユーザーのブラウザだけに通知され,攻撃者には未知の値となる。このため攻撃者は情報を参照できなくなる。複数画面からなる登録ページでは,すべての画面に対策が必要となる。ページを移りユーザーからの入力があるたびにセッション変数が更新されるようなアプリケーションでは,どこに罠を仕掛けられるかわからないからだ。

 もちろん,IEや,FireFoxが第3回で解説したSet-Cookie2のフォーマットをサポートすれば,別サイト上で発行されたクッキーの受け入れを拒否するように実装すれば,セッション・フィクセーションの問題は起こらない。

セッション変数へのCSRF

 セッション変数を利用したアプリケーションでは,クロスサイト・リクエスト・フォージェリ(CSRF)のぜい弱性についても考慮が必要になる。CSRFのぜい弱性は一般にコミット処理と関連した問題であると認識されている。ショッピング・サイトを例にすれば購入完了処理がこれに該当する。しかし実際には,コミット処理だけでなく,セッション変数へのデータ格納処理においても問題が発生することがある。

 一般的なショッピング・サイトのように「カートへ追加→内容確認→購入完了」というようなフローのアプリケーションを考えよう。カートへの追加処理時にデータをセッション変数に格納し,購入完了処理でもそのセッション変数を使う。このアプリケーションでは,カートへの追加リクエストを対象としたCSRF攻撃を受けると,セッション変数を上書きされてしまう危険がある。結果としてカートの中身が書き換えられ,意図しない商品を購入させられてしまう可能性がある(図2)。こうなると,購入完了処理だけを対象としたCSRF対策では攻撃を防げない。

図2●セッション変数を使うアプリケーションはログイン処理以外にもCSRFの攻撃を受けそうな処理が潜む
図2●セッション変数を使うアプリケーションはログイン処理以外にもCSRFの攻撃を受けそうな処理が潜む

 確認画面に遷移するなら,ユーザーが内容の不整合に気付くだろうと思うかもしれない。ただ,罠を踏むタイミングが確認画面への遷移後である場合は,確認画面に表示されるものとは違うデータがアプリケーションに登録されることになる。この場合,攻撃が成立するためには「ユーザーが確認画面へアクセスしている際に,罠を踏む」という厳しい前提条件が必要となるが,リスクは認識しておかなければならないだろう。

 対策は,セッション変数を変更するすべてのリクエストにCSRF対策を施すこと。第2回でクライアントにひも付けたランダムな値(トークン)を使う対策を紹介したが,その適用範囲を拡大させればよい。処理完了およびセッション変数に変更が発生するリクエストを「サーバーの状態を変化させるリクエスト」と定義すると,以下のような対策となる。

1.サーバーの状態を変化させるリクエストの前画面へのアクセス時にクライアントにひも付けたランダムな値(トークン)を発行する
2.その値をhiddenに含め,サーバーの状態を変化させるリクエストへのアクセス時に送信させる
3.サーバーの状態を変化させるリクエストでは,送信されてきたトークンが正しいものであることを,処理実行前にチェックする


安西 真人
ユービーセキュア 技術本部 テクニカルサービス部 セキュアナレッジコンサルタント 兼 Webアプリケーション検査ツールVEX開発エンジニア
プログラマを経て2年前からセキュリティ業務に従事している。