ikepyonのだめ人間日記

セキュリティに関することを書いていく予定。

要件定義

セキュリティ機能要件

アプリケーションのセキュリティを考えるとき、必要なセキュリティ機能がいくつか存在する。そしてその要件はほとんどのアプリケーションで大きく変わることがないと思う。以下はそのような不変の機能であると思う。

  1. 認証機能
  2. データ暗号化
  3. 通信の暗号化
  4. ログ出力機能

認証機能

認証機能を実装する際、以下のような要件が必要と思われる。

1.認証方法
  • パスワードによる認証を使用するのであれば、次項のパスワードに関する要件を参照すること。
  • ユーザーが限られ、取り扱う業務が重要であれば、クライアント証明書による認証を検討する。クライアント証明書による認証には、クライアント証明書の取り扱いに関するポリシー、ルールが必要となる。
2.ログインIDポリシー
  • ログインIDに使用できる文字種は数字と大小英字を含み、記号も使用可能とする。
  • ログインIDにメールアドレスを使用しない。
  • ログインIDを認証以外に使用しない。

最近他のサイトで使用されたログインIDとパスワードの組を使用したリスト型攻撃が多発している。これを緩和するため、ログインIDをサイトごとに変更できるようにしたほうがよい。メールアドレスを複数持っているユーザーは多くないと思われるため、ログインIDにメールアドレスを使用することは望ましくない。

3.パスワードポリシー
  • パスワードに使用できる文字種は数字と大小英字、記号とする。
  • パスワードの最低桁数は8桁とする。
  • パスワードは「パスワード+ユーザー毎に異なるランダムな文字列(salt)」をハッシュ化、ストレッチングしたものと salt のみを保存する。

 パスワードの強度は桁数と文字種に依存するため、最低限の桁数だけ決めておき、それ以外は制限しないほうがよい。また、パスワード文字列を平文もしくは復号可能な暗号化された文字列として保存するのは、パスワードリストが漏えいした場合簡単にパスワードを取得できる。このため、ハッシュ化したパスワードを保存しなければならない。

4.アカウントロック
  • 10回連続してログインに失敗した場合、一定時間(30分以上)アカウントロックする。
  • アカウントロックして一定時間経過後、自動的にロックを解除する。

アカウントロックはブルートフォース攻撃を緩和する方法として有効である。このため、アカウントロック機能は実装すべきである。

5.パスワード変更
  • 現在のパスワードをパスワード変更の際には必ず要求し、確認する。また、連続して10回パスワードを間違った場合、ログアウトするとともに、アカウントをロックする。
  • パスワード変更を行った後、パスワード変更があった旨を伝えるメールを登録してあるメールアドレスに送信する。メールにはパスワードを記載してはならない。

パスワード変更を行った後、メールを送信する理由は、攻撃者によるパスワード変更を検出するためである。また、定期的なパスワード変更はパスワードの運用が難しくなるため、実施しない。

5.パスワードリセット
  •  パスワードリセットの要求に対して、32文字以上のランダムなワンタイムトークンを含むURLもしくはワンタイムのランダムなパスワードを登録してあるメールアドレスにメールにて送信する。
  • ユーザーは受け取ったメールをもとにパスワードリセットのページにアクセスし、直ちにパスワード変更を行わなければならないようにする。

 パスワードリセット機能を「秘密の質問」と「回答」による認証によって行う手法はソーシャルエンジニアリングを用いて簡単に悪用される危険性が高いため、メールによるパスワードリセットに使用することがよい。メールアドレスがパスワードリセット機能において、非常に重要な位置を占めるため、メールアドレス変更機能について以下の仕様を満たす必要がある。

6.メールアドレス変更
  • メールアドレス変更は、ログインした状態でないと実施できないようにする。
  • メールアドレス変更の際、パスワードを要求し、確認する。また、連続して10回パスワードを間違った場合、ログアウトするとともに、アカウントをロックする。
  • 変更後のメールアドレスに32文字以上のランダムなワンタイムトークンを含むURLもしくはワンタイムのランダムなパスワードをメールにて送信する。ユーザーが受け取ったメールに記載されたURLにアクセスした後、メールアドレスを変更する。
  • メールアドレス変更後、変更前のメールアドレスと、変更後のメールアドレスにメールアドレスを変更した旨のメールを送信する。

 データ暗号化

保存するデータのうち何を暗号化するか、暗号化方式に何を使うか、暗号化に使用する鍵の管理方法を決定する必要がある。

1. 暗号化対象のデータ

全てのデータを暗号化して保存することはパフォーマンスの面からもよい方法とは言えない。機密にする必要があるものに限って暗号化は実施すべきである。セキュリティポリシーでセキュリティレベルの高いデータとしているものについてのみ、暗号化して保存することが、効率が良い。

  • 要求仕様を作成する際にどのデータを暗号化して保存するか明確にしなければならない。暗号化して保存すべきデータとしては、パスワード、クレジットカード番号等があげられる。
2. 暗号化方式

 独自の暗号化方式は脆弱である可能性が非常に高く、機密にしたい情報を適切に守ることができないため、独自の暗号化方式は使用してはならない。また、上記リストにある暗号化方式であっても、独自に実装している場合、バグが混入し脆弱である可能性が高くなるため、可能な限り独自実装を行わないほうがよい。

3. 暗号鍵の管理
  • 暗号化鍵をコード中に記述せず設定ファイル等で指定する。
  • 暗号鍵はアプリケーション管理者、サーバー管理者、アプリケーション以外からアクセスできないようにOSレベルのアクセス制御を行う。

暗号鍵をハードコードすると万が一鍵が漏えいした場合、コードの修正が必要となるため、容易に鍵の変更ができなくなる。これを防ぐために、設定ファイル等で指定するほうが、運用がしやすくなる。

公開鍵方式を使用する場合、公開サーバーがハッキングされた際、秘密鍵が漏えいしてしまうため、公開サーバーでデータを復号化する必要がなければ、秘密鍵は公開サーバーに保存しないほうがよい。

 通信の暗号化

機密情報を送受信する場合、通信経路についても暗号化が必要である。

  • 機密情報を送受信するページはSSLを使用して通信を行う。
  • サーバー証明書に自己証明書、有効期限の切れた証明書は使用しない。
  • 暗号化方式にSSL2.0は使用しない。

機能要件の際に洗い出したデータのうち、特定のユーザー以外はアクセスできないと定義したデータを機密情報として扱う。これらを送受信するページについてはSSLを使用した通信を行うことで通信の盗聴の被害を防ぐことができる。

自己証明書を使用している場合、正規のサーバーとの通信が確立できているかユーザーは判断できないため、使用してはならない。また、有効期限の切れた証明書についても同様である。もしこれらを使用している場合、盗聴、改ざん、成りすましを防げない。

SSL2.0は脆弱性があるため、SSL3.0などを使用すべきである。

ログ出力機能

ログ自体攻撃を防ぐことはできないが、インシデントが発生した場合、被害を調査したり、異常を検知し対策を行うことができる。このため、可能な限りログは取得しておいた方がよい。

  •  ログには以下の内容を記録する。
    ー 日時(yyyy/mm/dd HH:MM:SS)
    ー 送信元IPアドレス
    ー アクセスしたユーザーアカウント
    ー 処理対象となる項目名
    ー 行った処理(使用した機能)
    ー 処理結果(成功/失敗)
  • 出力したログはアプリケーション管理者、サーバー管理者以外がアクセスできない場所に保存する。
  • ログは3年間保存する。

インシデントが発生した場合、ログを確認することで誰が、いつ、何を、どこから行ったかが分かるようになる。これにより、被害の範囲が確認できる。ログから情報が漏えいする可能性があるため、パスワードや個人情報などの機密情報はログに出力してはならない。

ログには攻撃者にとって有用な情報が含まれることがあるため、必要なもの以外にアクセスできないようにしておく必要がある。アプリケーション管理者、サーバー管理者以外がログを見ることはないので、管理者以外に読み取りアクセス権は必要がない。

インシデントが発覚するのはインシデントが発生してから時間がかかるため、ある程度長期間ログを保存しておく必要がある。また、ログの保存にもディスク容量が必要となるため、最低限保存しておく期間を定義しておかなければならない。