第2章 脆弱性回避策とソフトウェア開発工程
ソースコードレビュー
ソースコードレビュー
ソースコードレビューは、開発者担当者が書いたソースコードを閲読してセキュリティ脆弱性あるいはそのきざしを読み取る作業である。
ソースコードレビューで見いだされた脆弱性の情報を開発作業にフィードバックし、ソースコード修正を行う。
(1) ソースコードレビューを行う理由
プログラマが書き下ろしたソースコードは、そのままでは多くのバグといくつかのセキュリティ脆弱性を内に秘めているおそれがある。
ソースコードの正しさを検証するためにテストを行うのであるが、その前にソースコードをレビューしてブラシュアップすることにより、問題の何割かを事前に除去しておくことができる。
(2) 誰が行うか
ソースコードレビューを行う人物には次が考えられる。
- 開発者本人
- 開発チームの別の担当者
- 開発チームとは独立したセキュリティ脆弱性対策チームのメンバ
開発者本人がソースコードを見直すことと、別の人物の眼によるチェックを行うことの両方が行われるのが望ましい。
前者の利点は、開発者がより脆弱性の少ないコードを書く能力の向上がはかれること、後者の利点は、思い込みによって開発者が見落としがちな問題についても見つけ出す機会が得られることである。
(3) いつ行うか
ソースコードが新たに書きおこされるか、既存のプログラムが改修されて、ソフトウェアの中のひとまとまりの機能のソースコードが揃った時点でレビューを行う。
(4) 何を記録するか
ソースコ−ドレビューの成果物としては、次の記録が残されていることが望ましい。
- いつ誰がレビューしたか
- どの範囲のどの時点のソースコードが対象か
- 開発においてコーディング標準を用いていればそこから逸脱している箇所の指摘
- 所期の機能から逸脱した動作の指摘
- コードのどの部分にどのような脆弱性の疑いがあるかの指摘
レビューにおいては、「このように直す」といった脆弱性の対策方法までは述べず、問題をなるべく多く指摘することに注力するのがよい。
レビューの4つの段階
ソースコードレビューは次の4つの段階に分けて行う。
下読み どこに何があるかの把握
成熟度点検 ある程度の品質水準に達しているか否かの評価
機能点検 バグ、すなわち機能面の不具合の検出
脆弱性点検 セキュリティ脆弱性の検出
(1) 下読み
ソースコードを書いた本人以外がレビューする場合、詳しく内容を吟味する前に下読みを行う。ここでは、次のような情報の把握につとめる。可能なら設計ドキュメントを入手して参照する。
- 構成──対象ソフトウェアはどのような構成単位(モジュール)に分割され、配置されているか
- 記述対象──各ソースファイルが記述している対象は何か
- モジュール間参照関係──各モジュールはそれぞれどのモジュールを参照しているか
- 手続きとデータの関係──どの手続きがどのデータをアクセスしているか、あるいはどのオブジェクトにどのようなメソッドが集められているか
- データ構造──データはどのような構造をもっているか
- 制御フロー──手続きのコードはどのような制御フローをもっているか
(2) 成熟度点検
ソースコードを下読みし、そのコードが雑に書かれたものであるか十分な考慮と注意の下に書かれたものであるかを判断する。
著しく水準を下回る場合はソースコードを差し戻し、プログラマに改善を求める。
また、所定のコーディング規約、命名規約に従っているかどうかを点検し、違反箇所を指摘する。
点検項目の例として、例えば、次のような項目が考えられる。
- 命名規約が整然としていること
- 記号名の命名が適切であること
- モジュール分割が十分細かく行われていること
- ひとつの関数の行数が多過ぎないこと
- アクセス制御、同期、暗号等の専門技術を要するコードが局所化されていること
- アサートが記述されていること
- 関数の入力パラメータは適切か
- 長期的データのインテグリティが確保されているか
- 処理を行った結果長期的データのインテグリティが損なわれなかったか
- 返す結果が適切か
- 動的メモり割当・解放が組織立って行われていること
- malloc()呼び出し、free()呼び出しが局所化されていること
- 一定期間コンテキストを維持する機構で動的メモリの把握が行われること
- このコンテキストの消滅時にその機構で使われていた動的メモリもすべて解放されること
- ループが有限回数で停止すること
- 再起呼び出しが有限の深さで停止すること
- 外部から取り込むデータすべてに入力検査を施していること
(3) 機能点検
書かれたコードが所期の機能を果たすものであるか否かを点検する。バグが著しく多く見いだされた場合はソースコードを差し戻し、プログラマに改善を求める。
(4) 脆弱性点検
脆弱性検出のためには、例えば、「セキュリティテスト」の記事にある「チェックリスト2」に示すような観点でソースコードを点検することが望ましい。ただし、これらの項目の中には実際にプログラムを動かしてみないと確認しづらいものも含まれる。慣れないうちは次のような観点から始めるのもひとつの手段である。
- 取り扱いに注意を要するライブラリ関数を呼び出している箇所はないか?
- printf系関数およびsyslog()関数呼び出しの書式引数に外部入力を渡していないか?
- 設計ではもともと予定されていないデバッグ機能や保守機能等がプログラマの判断で組み入れられていて、情報漏えいや所期のアクセス制御の迂回がおこらないか?
- 領域からデータがあふれ得る箇所はないか?
ツールの利用
上記の脆弱性観点からのレビューをすべて行うことが出来れば脆弱性対策に大いに寄与するが、いきなりすべてを行うことは必ずしも容易ではない。
より手軽に始める方法としては、まず最初はソースコードの静的検査ツールを使い、ツールが自動で検出してくれる問題から手を付けるという方法がある。

ソースコードを静的に検査し、セキュリティ脆弱性を指摘してくれる有償のツール製品が存在する。例えば、下記のものがある。
- Coverity Prevent
- Fortify Source Code Analysis Suite
- Visual Studio Team System の /analyze オプション
また、機能は限定されるが、領域あふれ、フォーマット文字列問題、外部からの問題のある入力の受け入れ箇所等、注意を要するランタイム関数の使用箇所を指摘してくれる無償ツールも存在する。
例えば、次のものである。
- Flawfinder
- ITS4
- RATS