第2章 アクセス制御
アクセス認可

アクセス制御は、ユーザ認証とアクセス認可の2段階からなる。アクセス制御されるWebページは、オブジェクトIDによって「一本釣り」できてしまわないようにPEP(Policy Enforcement Point)を設置する必要がある。

アクセス認可

アクセス認可は、ユーザ認証を通過したユーザに対してデータやプログラム等のコンピュータのリソースの利用を許す/許さないを制御する機能である。アクセス認可の機能を実装する際には、ふたつの留意点がある。

アクセス認可の三段階のチェック
図2-5: アクセス認可の留意点

(1) ユーザ認証の結果に基づく

アクセス認可は、あらかじめユーザ認証(本人認証)を行っておき、その結果に基づいて行う必要がある。

クライアントの接続IPアドレスや、パスワードの提示を受けずに受け入れたユーザ識別番号等を用いてアクセス認可を行う方法は、他人によるなりすましを見過ごすおそれがある。ユーザを特定することが重要でないシステムを除き、これらの方法は避けた方がよい。

(2) ユーザの全アクセスをインターセプトする

ユーザから対象のリソースへのアクセスが起こる際、アクセス認可のためのロジックを迂回できては具合が悪い。例えば、選択できる項目の表示をメニュー画面上で隠したのみでは、URLを用いて直接リソースが呼び出せるといった問題があり得る。

ユーザがリソースにアクセスする経路に立ちふさがる形で仕組みを設け、ユーザがアクセスを試みたときには必ずアクセス認可の判定ロジックが働くようにする。

Webアプリケーションにおけるアクセス認可の実装

(1) 3段階の構成

Webアプリケーションにおいて、アクセス認可の判定内容は概ね次の 3段階の構成になる(図2-6)。これらの最終的な判定結果が「Yes」の場合のみ、Webページ等のリソースへのアクセスを執行するようなPEP(Policy Enforcement Point)を設置する。

a) ログイン有無による制限
b) ページ単位のアクセス許可・禁止
c) パラメータ単位のアクセス許可・禁止

アクセス認可の三段階のチェック
図2-6: アクセス認可の3段階のチェック

(2) https:の使用

アクセス認可の対象となるWebページは原則としてhttps:を使用する。さもないと、正規のユーザがコンテンツを取得する際の通信を許可されていない第三者が傍受し、不正にコンテンツを閲覧するおそれがある。

ただし、Webサイトのセキュリティの方針として、盗聴されるリスクを容認する旨の意思決定をした場合はその限りではない。

ログイン有無による制限

会員制のサイトや有償コンテンツを提供するサイトにおいては、特定のページはログイン済みのユーザでなければ閲覧を制限するような仕組みが必要である。

そのためには、制限の対象となるWebページを表示する各プログラムにおいて、現在アクセスしているユーザがログイン済みであるか否かをプログラム冒頭で判定するようにする。ユーザがログイン済みでなければコンテンツを開示しない。

この仕組みはおおむね次のように実現する。

(1) ユーザ認証にHTTP認証を使う場合

HTTP認証を使う場合は、毎回のHTTPリクエストにユーザ認証データが含まれているので、それが適切なユーザ認証データであるか否かを判断することによって、ユーザがログイン済みであることの判定を行う。

(2) ユーザ認証にログインフォームを用い、ログインの状態をCookie等に搭載したセッションIDによって維持する場合

  • ユーザがログインに成功した時点で次を行う。
    • この時点ではじめてセッションIDを発行する。または、それまでと異なる新しい値のセッションIDを発行する。
    • セッションメカニズムがサポートしているセッション変数の仕組みを利用し、現在のユーザがログイン済みであることを示すセッション変数をひとつ記録する。
  • ログイン有無による制限対象のWebページを表示するプログラムにおいて次を行う。
    • ユーザがログイン済みであることを示すセッション変数が記録されているか否かを判断することによって、ユーザがログイン済みであることの判定を行う。

(3) ユーザ認証にログインフォームを用い、ページの連続を維持するセッションIDとは別に設けたCookie等でユーザのログイン状態を維持する場合

  • ユーザがログインに成功した時点で次を行う。
    • ログイン状態を維持するためのCookie等を発行する。
  • ログイン有無による制限対象のWebページを表示するプログラムにおいて次を行う。
    • ユーザがログイン済みであることを示すCookie等が適切な値を持っているか否かを判断することによって、ユーザがログイン済みであることの判定を行う。

ページ単位のアクセス許可・禁止

ログイン済みのユーザに無条件ですべてのWebページの閲覧を許すのではなく、各ユーザごとにWebページの閲覧の許可・禁止を制御したい場合がある。例えば、オプションの申し込みに応じて利用できる内容が変化するサイト、一般会員と特別会員のように会員に複数の種別があるサイト等である。

そうした制御の対象となるWebページを表示する各プログラムにおいては、現在ログインしているユーザの識別子と表示しようとしているページの組み合わせが「許可されている」ものであるか否かを判定するロジックをもつ。組み合わせが「許可されない」ものであればコンテンツを開示しない。

この仕組みについては、概ね次のような要素から成る。

  1. どのユーザにどのページの閲覧を許すかを示すデータ
  2. 現在ログインしているユーザと閲覧しようとしているページの組み合わせが「許可されている」か否かを判定するモジュール
  3. 各Webプログラムでは、ユーザがログイン済みであることを判定した後、この共通モジュールを呼ぶ

パラメータ単位のアクセス許可・禁止

Webページによっては、そのWebページそのものの閲覧はどのログイン済みユーザにも許すが、そのユーザに関わりのあるデータのみ開示するように制限を加えたいというケースがある。

例えば、会員のショッピング履歴項目のひとつひとつを一意に識別できるキーの値が存在し、それをWebプログラムのパラメータに与えるようになっている場合である。このパラメータにうまく値を与えると他人のショッピング履歴が不正に参照できるとしたら具合が悪い。

Webプログラムがデータを表示あるいは保存する際のキーは、それが現在のユーザに「許可された」ものであることを確かめた上で用いる必要がある。

(1) データベース検索条件にユーザIDを含める

データベーステーブルにユーザID(あるいはユーザを一意に識別できる別値)のカラムを設けておき、そのテーブルにアクセスする際のSQL文のWHERE句には必ずユーザIDによる制約条件をつけるようにする。

(2) キー値の正当性の検査

ユーザIDとキー値の妥当な組み合わせを表やリスト等何らかのデータ構造で保持しておき、キー値を用いたデータへのアクセスに先だってキー値を検査する。

うまくいかない実装の例

アクセス認可のうまくいかない実装方式を下例に示す。

(1) 入力パラメータでユーザを識別する

攻撃者は、そのパラメータを偽造しうる。

(2) メニュー画面からリンクを隠すのみ

攻撃者は、URLを直接指定してページを呼び出しうる。

(3) Referer: ヘッダを見て制御する

攻撃者は、ツールを使って Referer: ヘッダを偽造しうる。

(4) GETメソッドに反応せずPOSTのみに応答を返す

攻撃者は、ツールを使って POSTリクエストを投入しうる。