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年間保存する。

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

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

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

 

要件定義

要件定義においてセキュリティというと、セキュリティ機能と実装する機能にセキュリティの問題が無いかを確認する必要があると思う。そこで、おのおの考えてみる。

機能要件のセキュリティ

機能の安全性を考慮する際、リスク分析するというのがあるが、これを行うのは非常に難しいし、手間がかかる。

そこで、アプリケーションで取り扱うデータのアクセス権をまず最初に定義し、各機能が取り扱うデータに対するアクセス権と先に定義したアクセス権で矛盾が無いかを確認する。これにより、比較的簡易に機能の安全性を確認することが出来ると思われる。また、誰が、どのデータにどう言ったことを行うかを明確にすることで、要求仕様の曖昧さを減らすことが出来るだろう。

 それでは、どのような資料が必要か考えてみる。

データのアクセス権定義

まずはデータのアクセス権を定義するため、以下のような作業が必要と思われる。

  1. データの洗い出し
    対象のアプリケーションで使用するデータが何かを洗い出す必要がある。この段階では、詳細な項目(アカウントの名前、住所、メールアドレスといったもの)は出せなくてもよいと思う。たとえば、個人情報、決済情報、注文情報、商品情報といった具合でも問題ないだろう。ただし、明確にアクセス権が異なるものについては同じ項目であっても分割しておいたほう(例えば、決済情報のうち、Cセキュリティコードは取り扱いが異なるので分けて考えるほうがよい)が後の作業が楽になる。
  2. ロールの洗い出し
    対象のアプリケーションを使用するユーザーのロール(役割)を洗い出す必要がある。このロールをもとに各データのアクセス権を決定していけばよい。注意しないといけないのは、このユーザーのロールを洗い出す際、対象のアプリケーションのユーザーではない人や各ロールの補集合も洗い出すことである。また、アプリケーション管理者だけでなく、サーバー管理者もロールとして洗い出しておく。サーバー管理者であれば、仮に複合可能な暗号でデータが保存されていたとしても、閲覧することは可能だからである。
  3. データ管理者の定義
    各データの管理者(大抵はそのデータを作成、登録したもの)を決める。
  4. アクセス権の定義
    各データごとに洗い出したロールに対するアクセス権(読み込み、書き込みができるか)を決定する。なお、データ管理者には読み書きのアクセス権を通常与えるため、特に定義する必要はないと思われる。
    この際、対象のデータを検索条件とする場合も読み込み権限が必要であることに注意が必要である。これはデータの内容を直接見ることはできなくても、検索条件としてデータの有無を調べることでそのデータが存在するかどうかを調べることにより、結果としてデータの内容を直接見ることと同じ効果を得られるからである。
    アクセス権の定義はISMSで定義されている物を参考にすればよいだろう。

以上の作業を行うと、例えば、以下のような表ができる。

データ項目名 データ管理者 一般ユーザーのアクセス権 一般ユーザー以外のアクセス権 対象店舗管理者のアクセス権 対象店舗以外の店舗管理者のアクセス権 アプリケーション管理者のアクセス権 サーバー管理者(システム)のアクセス権
個人情報 ユーザー なし なし 読み込み/書き込み なし 読み込み/書き込み 読み込み/書き込み
決済情報 ユーザー なし なし なし なし なし なし
注文情報 ユーザー なし なし 読み込み/書き込み なし 読み込み/書き込み 読み込み/書き込み
商品情報 店舗管理者 読み込み 読み込み 読み込み/書き込み 読み込み 読み込み/書き込み 読み込み/書き込み
店舗情報 店舗管理者 読み込み 読み込み 読み込み/書き込み 読み込み 読み込み/書き込み 読み込み/書き込み
 機能要件の定義

機能要件はRFPに通常記述する。この際、以下のことを明確に記述する必要がある。

  1. 誰が(どのロールが)
  2. 何を(どのデータ項目を)
  3. どうする(読み込むのか、書き込むのか)

これらをRFP提出の際に表にしておくとわかりやすいのではないだろうか?

例えば、以下のようになるだろう。

機能名 誰が 何を どうする
ユーザー登録 ユーザー 個人情報 編集する(書き込み)
商品検索 誰もが 商品情報 検索する(読み込み)
決済情報登録 ユーザー 決済情報 編集する(書き込み)
商品購入 ユーザー 注文情報 書き込む
    決済情報 参照する
商品情報登録 店舗管理者 商品情報 編集する(書き込み)

このように機能を書き出し、対象となるデータのアクセス権と必要な権限が矛盾していないか確認する。矛盾していた場合、機能変更、機能を実装しない、アクセス権を見直すなどの対策を行う必要がある。どうしても実装したい場合、RFPに記述しておき対策を受注者に検討してもらうという方法もある。この矛盾をどうするかに対する回答を出してくるかどうかで発注先を選定する基準にもすることができるだろう。

先の例の場合、特に矛盾がないように見えるが、「商品購入」機能において、ユーザーが保存した「決済情報」を参照するためには「システム」=「サーバー管理者」も「決済情報」を参照する必要がある。しかし、先のデータのアクセス権の定義では「サーバー管理者」にも「決済情報」はアクセスを許可していないため、矛盾する。これでは機能が提供できない。

この例では、「クレジットカードのセキュリティコード」も「決済情報」として想定していたとする。「クレジットカードのセキュリティコード」はカードの保持者以外には知られてはいけない情報であるため、ユーザー以外のロールにはアクセス権を付与していなかった。そこで、「決済情報」から「クレジットカードのセキュリティコード」を除外し、それ以外についてのアクセス権をもう一度定義しなおすことで、矛盾を解消することにする。

データ項目名 データ管理者 一般ユーザーのアクセス権 一般ユーザー以外のアクセス権 対象店舗管理者のアクセス権 対象店舗以外の店舗管理者のアクセス権 アプリケーション管理者のアクセス権 サーバー管理者(システム)のアクセス権
決済情報 ユーザー なし なし なし なし なし 読み込み
セキュリティコード ユーザー なし なし なし なし なし なし

これにより、システムでの読み込みが可能になり、矛盾がなくなり、機能実装を行うことができるようになる。

最初に定義したデータのアクセス権を変更することは、セキュリティホールを作ることになるので、あまり好ましくない。これはどうしても実装したい機能が実装できない場合に限るべきである。

機能要件のセキュリティまとめ

機能要件がセキュリティホールになることを減らすには以下のことを検討し、RFPに資料としておくと発注側も注意すべき点が明確になるため、齟齬が起こりにくくなると思われる。

  1. 使用するデータのアクセス権を定義する
  2. 各機能要件において「誰が」「何を」「どうする」かを明確に記述する
  3. 1.と2.で矛盾が存在しないか確認し、必要に応じて、機能の変更、データ分類の再検討、機能の削除を行う

はじめに

RFPを作成する際、セキュリティを考慮する必要があるが、何をすれば、何を書けばいいのかわからないということが多いように思われる。OWASPでも公開(https://www.owasp.org/images/8/88/Web_application_security_requirements.pdf)されているのだけど、何となく今一なので、ちょっと考えてみる。

開発工程において、それぞれセキュリティを考慮しなければ行けないと思う。そこで、開発工程毎に考慮すべきこと、そのために必要な資料、成果物を考えて、それらを行ってもらえるようにRFPを書けばいいかと思うのだけどどうだろうか?

と言うわけで、開発工程を以下のように分けて、次回以降、開発工程毎に要求することを考えてみる。

  1. 要件定義
  2. 設計
  3. コーディング
  4. テスト
  5. 運用

 

 

 

また久しぶりw

バレンタインチョコ欲しい!
欲しいプレゼントは…これしかない!

ECサイト向けセキュリティ対策ガイドライン

http://www.jipdec.or.jp/archives/ecom/results/h13seika/h13results-11.pdf
http://www.jipdec.or.jp/archives/ecom/results/h13seika/h13results-12.pdf
http://www.jipdec.or.jp/archives/ecom/results/h13seika/h13results-13.pdf
後で読む