第4章 セッション対策
想定外ナビゲーション対策
想定外ナビゲーション
複数のWebページを、Webアプリケーションが望んでいない順序でユーザが辿った場合、Webサーバ内のデータの辻褄が合わなくなったり、本来開示すべきでない情報を漏えいするおそれがある。Webアプリケーションは、望ましくないページナビゲーション操作にも一定の対策を講じておく必要がある。
もたらされる被害
どのような現象が生じるかはそれぞれのWebアプリケーションによって異なるが、想定外のナビゲーション操作が行われたとき、プログラムが誤作動して次の被害を生じるおそれがある。
- データのインテグリティが損なわれる
適切な順序でデータが組み立てられない状態でデータベース等への書き込みが行われた場合、データが不完全な形で書き換えられ、インテグリティ(一貫性、完全性)が損なわれるおそれがある。 - 情報漏えいが生じる
検索条件が適切に揃わない状態でデータの検索が行われた場合、本来開示すべきでない情報をWebページに表示してしまうおそれがある。
問題となる操作
Webアプリケーションは通常、複数のWebページをユーザに一定の順序で辿ってもらうことによって適切に機能するよう計画される。ところがユーザは、意図して、あるいは誤って次のような操作を行うことがあり得る。
- ブックマークやURL直接入力によるページ呼び出し
一連の流れの途中のWebページに、ブックマークから直接アクセスする。もしくは、ブラウザのアドレスバーにURLを直接入力する。 - 「送信」ボタン複数回クリックによるフォームデータの再送信
フォームの「送信」ボタンを連続して複数回クリックする。 - 「戻る」ボタン操作によるフォームデータの再送信
ブラウザの「戻る」ボタンで戻り、再びフォームの「送信」を行う。 - ページの「再読み込み」操作によるフォームデータの再送信
一度呼び出したWebページを、ブラウザの「再読み込み」機能を用いて再び呼び出す。 - タブブラウザのセッション復元機能によるページ呼び出し
ブラウザFireFoxでは2.0からタブ復元機能が装備されている。この機能は、FireFoxが何らかの障害でクラッシュしたり、自動アップデートの際の再起動後元のセッションを復元するものである。この復元機能により、POSTリクエストで得られたページも復元される。

対策その1: URL直接呼び出しに対するもの
ブックマークやURL直接入力によるページ呼び出しに対しては、次のような対策が考えられる。
(1) POSTメソッドによるページ遷移
一連のページの流れの途中では、すべてPOSTメソッドで次のページへ遷移するようにし、それらのページはGETメソッドで呼び出せないようにする。
この方法には次のような限界がある。
- 悪意あるユーザによるページ呼び出しを防ぐことはできない。ユーザは、HTTPリクエストを編集するツールを用いてPOSTメソッドのリクエストを投入することができる
- タブブラウザの「最近閉じたタブを再び開く」機能でページが呼び出されるのを防げない
(2) Referer:ヘッダのチェック
HTTPリクエスト内のReferer:ヘッダを見て所定のページから遷移してきたことを確認する。
この方法には次のような限界がある。
- パーソナルファイアウォール製品がクライアントコンピュータからのReferer:ヘッダの送出を抑制している場合、この方法は使えない
- ユーザがページを呼び出そうとする試みをすべて防ぐものではない。ユーザはHTTPリクエストを編集するツールを用い、Referer:ヘッダを偽装してリクエストを送りつけることができる
対策その2: 送信ボタン複数回クリックに対するもの
「送信」ボタン複数回クリックによるフォームデータの再送信に対しては、次のような対策が考えられる。
(1) クリックカウンタによる複数回クリック対策
JavaScriptを用い、送信ボタンのクリック回数カウンタをもつとともに、2回目以降のクリックではデータを送信しないようにする。
この方法には次のような限界がある。
- ブラウザでJavaScript機能が停止させられている場合、対策は機能しない
(2) ポップアップウィンドウによるマウスイベントの受け止め
ユーザが「送信」ボタンをクリックした際、JavaScriptでポップアップウィンドウを出してマウスクリックイベントをそのウィンドウで受け止める。
この方法には次のような限界がある。
- ブラウザでJavaScript機能が停止させられている場合、この方法は使えない
- ブラウザでポップアップウィンドウ防止機能がはたらいている場合、この方法は使えない
- フォームデータの送信とその処理が完了したのちに、ユーザがもう一回同じフォームからデータを送信するのを防ぐものではない
対策その3: いくつかの再送信操作に対するもの
「戻る」ボタン操作による順路変更や「再読み込み」操作等によるフォームデータの再送信に対しては、次のような対策が考えられる。
(1) 更新処理と更新後表示のプログラムを分ける
データベース更新処理と更新結果照会処理をふたつのWebプログラムに分け、HTTPのリダイレクトレスポンスでふたつを結びつけて連続実行させる。
この方法には次のような限界がある。
- ユーザが意図的に、ひとつのフォームを用いて複数回データを送信するのを防ぐものではない
(2) ワンタイムトークンの埋め込み
各ページごとに異なる識別情報を埋め込むことによって、同一のフォームからのデータ送信の重複を検出するようにする。例えば次のようなロジックをもつ。
- 入力フォームには、表示するごとに異なる値の識別情報(トークン)を埋め込む
- 識別情報はサーバ側でも控えを保持し、サーバ側で発行した識別情報であり有効なものであることを確認できるようにしておく
- フォームデータを受け取ったWebプログラムはこの識別情報を調べ、それが有効であり、かつ初めて受信するものであるときに限り、データを受理し所定の処理を行う
- 有効でない識別情報を含んでいたり、すでに1度処理した識別情報を含むフォームデータは受理しないようにする
- サーバ側にデータが送られてこなかったフォームの識別情報は、ユーザがログアウトした時点で無効にする
- 識別情報には、ランダム性の高い桁数の多い値を用いるのがよい。単純な連番等では、ユーザがHTTPリクエストをねつ造できるおそれがある
まとめ
Webアプリケーションにおいて、ユーザのページ遷移の自由度は高い。Webアプリケーションの設計・実装の際、プログラムに都合の良いページ閲覧順路をユーザが辿ってくれるだろうと期待するだけで何も手を打たないのは時として具合が悪い。
上記のような方法を用い、ユーザのページ遷移操作に一定の制限を課すか、あるいは、ユーザが自由な順序でページを訪れたとしても、サーバにおけるデータ更新が適切に行われ、データのインテグリティが常に保たれるようにする必要がある。