Webアプリケーションの認証ロジック

くぅ。またくだらないミスを犯してしまった。。。
↓対処法
細かいことだけど,手軽な実装で大きなリスクを減らせる実装を紹介する.


システムの背景

  • Webアプリケーション
  • HTTPセッション管理をファイルに保存している
  • データベースが開発環境と運用環境に分離されている
  • 運用環境のデータを開発環境に取り込み,動作テストやリハーサルを行う場合がある
  • ユーザのHTTPリクエストによって実行されるプログラムからメールを送信する
  • ログイン認証をユーザIDなどの1つの値を保持するのみで実装してある

背景となるアプリケーションアーキテクチャの例.

開発環境データベースプログラムユーザ
運用環境データベース

上記の背景では,オペレーションミスにより,運用環境に登録されているユーザへメールが送信されてしまう場合がある.

  1. 開発環境のデータベースを利用する状態でログインする.
  2. データベースを運用環境のデータベースに変更する.
  3. ブラウザで再度アクセスすると運用環境のユーザIDでログインされた状態になる
  4. メール送信を行うプログラムへアクセスすると,運用環境に登録されたユーザへメール送信される.

上記の問題を回避するために,ログインの定義を変更する.
ログインの定義が,「ユーザIDの保持」だと問題が発生するので,「ユーザIDとアカウント名の一致」とすることでセッションジャックの危険性を減らせる.セッションハイジャックの危険性をより減らすためには,より多くの情報とログイン状態を関連づける.

背景の認証ロジックの式は以下.左辺と右辺が一致した場合はログイン認証を認める.

仮定:

  • getFromSession()はセッションからログイン情報として保存してある文字列を取得する関数
    idはセッションから取得した顧客ID
  • isValid(id)は顧客IDを引数とし,ログイン可能な状態ならばidを返却する.

式:
getFromSession() == isValid(id)

問題を回避するための認証ロジックの式は以下.

仮定:

  • other1, other2はidに関連した情報.ユーザ登録時から一切変更されない情報.idを元にデータベースから取得した情報。
  • hash()は引数の値をseedに取るハッシュ関数.

式:
getFromSession() == hash(isValid(id) , other1, [other2...])

コメント