第2章 脆弱性回避策とソフトウェア開発工程
セキュリティテスト
ソフトウェアのセキュリティ品質を確保するためには、次の3つの活動が重要である。
- 設計工程における「セキュリティレビュー」。設計ドキュメントをレビューし、考慮すべきセキュリティ対策に漏れがないか検証する
- 実装工程における「ソースコードレビュー」。記述したソースコードを直接検証する
- テスト工程における「セキュリティテスト」。作り上げたプログラムを動作させて、テストし、セキュリティ脆弱性を見つけ出す
セキュリティレビュー
(1) 目的
セキュリティレビューは、セキュリティ対策漏れを早くに見つけ出し、設計者へフィードバックすることを目的に行う。次のような観点で確認する。
- セキュリティ要件に対する対策漏れがないか
- 既知の脆弱性パターンに陥っていないか
(2) 対象
セキュリティレビューを行う際のレビュー対象は、設計工程までに作成されるおおよそ次ようなものである。
- セキュリティ要件定義書
- ソフトウェア構造設計書
- 業務仕様設計書
- モジュール分割設計書
- テスト計画書
(3) 要領・観点
必要とされるセキュリティ要件により変わり得るが、セキュリティレビューで考慮する項目は、例えば、次に示す「チェックリスト1」の項目が考えられる。
チェックリスト1
(a) 上流設計
- 本人認証ロジックは堅固か
- 親切すぎるエラーメッセージを出さないようにしているか
- アクセス承認ロジックは迂回しにくいものになっているか
- 情報を出力する箇所で重要情報の不用意な出力を避けているか
- ログ記録による証跡確保とログ自体の漏えい対策が十分か
(b) プログラムモジュールおよびファイル
- 侵害されると重大な結果を招くプログラムをchroot、jail等の環境で稼働させるようにしているか
chroot:Unixシステムコールのひとつで、ファイルシステムのルートディレクトリの位置を変更するコマンド。 コマンドを任意のディレクトリの下に閉じ込めてファイルシステムのアクセスに制約をかけることができる。 chrootから実行されたコマンドは、指定されたルートディレクトリよりも上の階層へアクセスすることが出来ない状態で起動する
jail:chrootの機能を拡張して、ネットワーク・プロセス等も隔離できるようにしたFreeBSD特有の仕組みである。 ファイルシステム空間、プロセス空間およびネットワークを隔離する技術である
- 起動された子プログラムが親プログラムを侵害することを想定し、対策を講じているか
- 秘密保持が必要なパラメータをコマンドライン引数で受け渡さないようにしているか
- 秘密保持が必要な情報を、ソフトウェアを構成するプログラムファイルや設定ファイルに簡単に読み出せる形で埋め込まないようにしているか
- ファイルへのアクセス権の付与を最小限にしているか
- テンポラリファイルへの他者からの干渉を避ける対策を講じているか
(c) 連続稼働と動作タイミング
- メモリリークが想定され対策されているか
- サービス不能状態が想定され対策されているか
- プログラムの稼働途中に短いタイミングであっても侵害に無防備な状況が生じる問題が想定され、対策が講じられているか
ソースコードレビュー
ソースコードレビューは、実装工程で開発者がコーディングしたソースコードを閲読して十分なセキュリティ対策が行われているかあるいはセキュリティ脆弱性につながってしまう部分がないかを読み取る作業である。次の記事「ソースコードレビュー」にて詳述する。
セキュリティテスト
(1) 目的
セキュリティテストの目的は、作り上げたプログラムに十分なセキュリティ対策が実装されているかどうかを確認することである。次のような観点で確認する。
- 既知の脆弱性パターンに陥っていないか
- セキュリティ設計通りの実装ができているか
- 設計工程までに検討しきれなかった脆弱性対策がないか
(2) 仕様・要領
セキュリティテストで確認するのは、おおよそ「チェックリスト2」に掲げる項目である。一部セキュリティレビューで行っていることもあるが、セキュリティ要件にあり、設計に反映されている項目は、当然、実装も行われているはずである。
実装漏れがあってはいけないので、やはりこのセキュリティテストでも確認する必要がある。また、ソフトウェアのテストの工程が、
単体テスト → 結合テスト → システムテスト
と進む中で、どのテスト工程においても十分に行うことが望ましい。

(3) 手段
セキュリティテストは、次のような手段によって行う。
1) ブラックボックステスト
一般的にブラックボックステストとは、プログラムの内部の作りとは関係無く、外部からシステムの機能をテストする方法である。
セキュリティテストで行うブラックボックステストでも、同様に外部からの入力によるプログラムの動作を確認する。 また、このテストではツールを使って一定の問題を検出する方法が利用できる。 例えば、変数領域のあふれを見つけ出すツールやコンパイラのオプションを使い、バッファオーバーフロー脆弱性が生じるおそれのある箇所を指摘させる等である。 ツールによる検査では、熟練した脆弱性対策技術者でなくてもテストが行える利点がある。
○ ツールの例
- 領域あふれを検出するツール
- madflap(-fmadflap -lmudflap、GCCのオプション)
- Valgrind の memcheck ツール (Linuxで稼働するヒープデバッガ)
- /RTCs (Visual C++のコンパイルオプション)
- 32/64ビット符号付き整数の演算時のオーバーフローの検出
- -ftrapv (GCCのオプション)
- ビット幅が小さい整数変数への代入において上位ビットが失われることの検出
- /RTCc (Visual C++のコンパイルオプション)
2) ホワイトボックステスト
一般的にホワイトボックステストとは、プログラムの内部の作りを理解した上で予定された処理が、予定通り動作するかどうかを確認するテストである。
セキュリティテストで行うホワイトボックステストでも、同様に処理の条件や組み合わせなどによるテストを行う。テストケースや予定している動作がはっきり把握できるのであれば、ブラックボックステストと同様に熟練した脆弱性対策技術者でなくてもテストが行える利点がある。
(4) 注意事項
セキュリティテストを行うにあたり、注意すべき項目を次にあげる。
- どのようなテストを実施するかは、設計段階で決定しておく必要がある。
- テストパターンを想定する場合、複数の条件、モジュール、パラメータなど多くの要素を全て漏れなくテストするようにすると膨大な量になってしまう。要点を絞る必要がある。
チェックリスト2
(a) 上流設計
- 本人認証ロジックは堅固か
- 親切すぎるエラーメッセージを出さないようにしているか
- アクセス承認ロジックは迂回しにくいものになっているか
- 情報を出力する箇所で重要情報の不用意な出力を避けているか
- ログ記録による証跡確保とログ自体の漏えい対策が十分か
(b) プログラムモジュールおよびファイル
- 侵害されると重大な結果を招くプログラムをchroot、jail等の環境で稼働させるようにしているか
chroot:Unixシステムコールのひとつで、ファイルシステムのルートディレクトリの位置を変更するコマンド。 コマンドを任意のディレクトリの下に閉じ込めてファイルシステムのアクセスに制約をかけることができる。 chrootから実行されたコマンドは、指定されたルートディレクトリよりも上の階層へアクセスすることが出来ない状態で起動する
jail:chrootの機能を拡張して、ネットワーク・プロセス等も隔離できるようにしたFreeBSD特有の仕組みである。 ファイルシステム空間、プロセス空間およびネットワークを隔離する技術である
- 起動された子プログラムが親プログラムを侵害することを想定し、対策を講じているか
- 秘密保持が必要なパラメータをコマンドライン引数で受け渡さないようにしているか
- 秘密保持が必要な情報を、ソフトウェアを構成するプログラムファイルや設定ファイルに簡単に読み出せる形で埋め込まないようにしているか
- ファイルへのアクセス権の付与を最小限にしているか
- テンポラリファイルへの他者からの干渉を避ける対策を講じているか
(c) 連続稼働と動作タイミング
- メモリリークが想定され対策されているか
- サービス不能状態が想定され対策されているか
- プログラムの稼働途中に短いタイミングであっても侵害に無防備な状況が生じる問題が想定され、対策が講じられているか
(d) 入力の場面
- 環境変数を検査しているか
- コマンドライン引数を検査しているか
- ソケット入力を検査しているか
- マルチメディアコンテンツのフォーマットや長さ記述子の異常を検出するようにしているか
- それ以外の入力検査についても十分行っているか
- パス名に応じたアクセス制限を標準とは異なるパス名表記を用いて迂回する試みを防ぐようにしているか
- オープンしようとしているファイルがシンボリックリンクにすり替えられていることを検出できるようにしているか
シンボリックリンク:ファイルやディレクトリに別の名前を与え、ユーザやアプリケーションがその名前をファイル本体と同様に扱えるようにする仕組み
- オープンしようとしているファイルの適切さを確認するステップと実際にオープンするステップの間ですり替えがおこることを想定し対策を講じているか
- ファイル拡張子に応じたプログラムを起動するメカニズムの使用を避けているか
(e) データ処理の場面
- 変数の領域あふれが予防されるロジックになっているか
- 外部から与えられた文字列がprintf等のフォーマット引数に与えられないようになっているか
- 整数値の演算におけるオーバーフローや代入における上位ビット落ちを想定し、対策を講じているか
- メモリ上で重要データを消去するロジックがコンパイラの最適化機能や言語処理系の機能により妨げられることを想定し、対策を講じているか
- シェルの使用を回避しているか、あるいはコマンド注入を想定し対策を講じているか
- スクリプトエンジンを使用する際、入力データに悪意のスクリプトが挿入されることを想定し、対策を講じているか
- DBをアクセスする際、SQL注入を想定し、対策を講じているか
- 破られにくい暗号技術と擬似乱数を使用しているか
(f) エラー対応と省略時解釈値
- プログラムの異常終了時にメモリダンプが行われないようにしているか
- エラー発生を確実に検知し対応するようにしているか
- 省略時解釈値は、セキュリティが守られる側に設定されているか