第7章 データ漏えい対策
親切すぎるエラーメッセージの回避

ユーザが攻撃者となる可能性もあるので、場面によっては攻撃者を利するような内容を含むエラーメッセージ表示を避ける。
プログラムでエラーが生じた場合、デバッグ情報といった、エラーに関する詳細情報をエンドユーザに見せないようにする。プログラムへの攻撃を意図する者にとって、都合の良いヒントになるおそれがあるからである。

ログイン失敗メッセージ

Web アプリケーションにおいては、様々なエラーメッセージを表示する場面があるが、攻撃者にヒントを与えるようなメッセージを出力しないようにする。

ユーザ認証の場面においては、ログイン失敗時のエラーメッセージが、

のようになっていると、アカウントを破るヒントを与えてしまう。さらには、パスワードクラッカー等のツールを使用してパスワードを探しあててしまうかもしれない。

対策としては、ユーザ ID が一致しなくても、パスワードが間違っていても認証できないのであれば、
    「ユーザ ID 又はパスワードが不正です」
というようにする。このようにすると、一見ユーザに対して不親切に見えるが、アカウントは破られにくくなる。

ログイン失敗メッセージ
図28: ログイン失敗メッセージ

ユーザに見せるエラーメッセージは控えめに

ユーザ認証時に限らず、ログイン後に発生するエラーのメッセージにも、必要最低限に抑えるように注意する必要がある。サーバの構成情報やバージョン、下記のようなデバッグ情報やエラー原因の詳細情報を表示しないようにする。

デバッグ情報
  ・ スタックトレース(関数コールのスタック)
  ・ Script のエラー情報(ソースファイル名、行番号等)
  ・ エラー原因のパラメータと値

デバッグ用の詳細なエラー情報は、残っていないようにする。

デバッグ用のメッセージ

C のプログラムにおいては、エラーメッセージとエラーの起きた場所を特定できるように、ソースファイル名と行番号を出力することができる。デバッグの解析用に有効であるが、下記の例のように条件付コンパイル(#ifdef)を使用しリリース時にははずすようにする。

fprintf (stderr, "(エラーメッセージ)\n", );
#ifdef DEBUG
fprintf (stderr, "%s(%d)", __FILE__, __LINE__);  ← assert.c の 10 行目
#endif

また、assert() (assert.hにてマクロ定義されている)等も、条件によりソースファイル名と行番号を出力される。

例 assert (i > 0) の出力(Visual stduio 2005)
  引数の i > 0 が偽の時、メッセージを表示しアボートする。
Assertion failed: i > 0, file c:\test\assert.c, line 20
                  ↑                ↑ソースファイル名と行番号
                  ↑assert() の引数

assert () は、バグの検出には、有効であるが、やはりリリース時には外すようにする。出力を止めるには、コンパイルオプションに、"NDEBUG" の追加定義をすればよいが、引数の条件チェックもされなくなるので注意が必要である。

エラーメッセージの防御

攻撃者は、エラー内容を分析してプログラムのロジックを推測したり、エラー画面に表示される OS やサーバソフトウェアのバージョンから「既知の脆弱性」をついた攻撃をしかける可能性がある。

また、詳細なエラー情報をログファイルに記録する場合には、特定のユーザのみにアクセス制限されたディレクトリ内に保存する必要がある。

まとめ

エラーメッセージは、攻撃者が利するような内容にすることなく、ユーザに理解し易いように出力するようにする。