JP2007052625A - ソースコード脆弱性検査装置 - Google Patents

ソースコード脆弱性検査装置 Download PDF

Info

Publication number
JP2007052625A
JP2007052625A JP2005237124A JP2005237124A JP2007052625A JP 2007052625 A JP2007052625 A JP 2007052625A JP 2005237124 A JP2005237124 A JP 2005237124A JP 2005237124 A JP2005237124 A JP 2005237124A JP 2007052625 A JP2007052625 A JP 2007052625A
Authority
JP
Japan
Prior art keywords
transition
variable
function
vulnerability
source code
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
JP2005237124A
Other languages
English (en)
Other versions
JP4693044B2 (ja
Inventor
Hiroshi Miyazaki
博 宮崎
Nobuyuki Ohama
伸之 大浜
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Hitachi Software Engineering Co Ltd
Original Assignee
Hitachi Software Engineering Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Hitachi Software Engineering Co Ltd filed Critical Hitachi Software Engineering Co Ltd
Priority to JP2005237124A priority Critical patent/JP4693044B2/ja
Publication of JP2007052625A publication Critical patent/JP2007052625A/ja
Application granted granted Critical
Publication of JP4693044B2 publication Critical patent/JP4693044B2/ja
Expired - Fee Related legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Abstract

【課題】ソースコードの脆弱性検査において、脆弱性を有する部分を精度良く検出でき、かつ、プログラマによるソースコード検査の作業負担を減らすことができるようにする。
【解決手段】検査対象のソースコード208を構文解析手段201により解析して解析木210を構築する。脆弱性検出手段202は解析木210を辿り動的仮引数間遷移DB206を作製する。これと仮引数間遷移DB204から検査対象のソースコードにおける外部入力の遷移を追跡し、外部入力をパラメータとして使用すると脆弱な関数を登録した脆弱性データベース205の登録内容に合致する箇所を、脆弱性を有する箇所として警告する。
【選択図】図2

Description

本発明は、ソフトウェアのソースコードを検査し、外部との入出力データを識別して関数間及び変数間の受け渡しを追跡し、さらに予め備えたルールに該当する脆弱性を有する箇所を検出するソースコード脆弱性検査装置に関するものである。
ソフトウェアに含まれる脆弱性を検査する方法には、動作中のソフトウェアに様々なデータを入力して結果を調べる方法と、ソフトウェアのソースコードを検査する方法の2つがある。
ソースコードを検査する方法には、パターンマッチングを用いる手法と構文解析を用いる手法がある。パターンマッチングを用いる検査では、検査対象のソースコード内から、プログラミング言語の標準ライブラリなどに含まれる「危険な関数」の使用箇所を関数名などによるパターンマッチングで検出する。「危険な関数」とは、プログラマがその使用に注意しないとソフトウェアに脆弱性を生じさせる関数のことである。例えば、データ複製の際に複製先のデータ領域の範囲を超えて複製する可能性のある関数や、コンピュータリソースを使用する際に競合状態のためプログラマの意図したとおりに使用できない可能性のある関数などがある。特に前者はバッファオーバーラン(バッファオーバーフロー)脆弱性の原因として広く知られている。
構文解析を用いる検査では、予めソースコードに検査のための付加的な注釈を加えた上でソースコードの構文解析を行い、データ構造の遷移(メモリ管理エラーや型の不一致など)や「危険な関数」の使用などを解析して論理的な矛盾点を見つけ出す。
いずれのソースコード検査手法においても、その手法を自動で行うツールが開発されている。しかし、どのツールも誤検出が多く、検査結果をもとにプログラマがソースコードを確認して脆弱性であるか否か判断しなければならない。
なお、ソースコード検査手法については下記非特許文献1に、「危険な関数」の例やバッファオーバーランについては下記非特許文献2に、それぞれ、説明がある。
情報処理振興事業協会セキュリティセンター:オープンソース・ソフトウェアのセキュリティ確保に関する調査報告書 第II部 オープンソース・ソフトウェアの効率的な検査技術の調査:平成15年2月、p.II-2〜II-4 情報処理振興事業協会セキュリティセンター:セキュア・プログラミング講座:平成14年3月、[1-2.]クロスサイトスクリプティング、他
ソフトウェアの脆弱性は、ソフトウェアが外部からの入力データを誤処理したり、誤処理した(あるいは未処理のまま)入力データを他のソフトウェアに出力したりすることで、生じる。ここで前者の代表例はバッファオーバーラン、後者の代表例はクロスサイトスクリプティング脆弱性やSQLコマンド挿入脆弱性であり、これらについては上記非特許文献2に詳しい説明がある。
ところで、パターンマッチングによるソースコード検査は「危険な関数」の使用箇所を検出するだけであり、その関数が処理するデータが外部からの入力データであるか否かを区別しない。そのため、実引数として渡されるデータの出所とは無関係に「危険な関数」の使用される全ての箇所が脆弱性として検知されてしまい、これらが本当に脆弱性であるかどうかを決定するためには、結局、プログラマがソースコードをインスペクションしなければならない。外部入力データを受け付ける関数は既知なのでその使用箇所をソースコードから検出可能であるが、パターンマッチングでは外部入力データのその後の使用箇所を追跡できず、プログラマによるインスペクション箇所を限定するには至らない。
構文解析によるソースコード検査では、構文解析を支援する注釈をプログラマが予めソースコードに詳細に記述しなければならない。そのため、ソースコード検査のための事前作業が大きく、プログラマの負担が大きい。
本発明は、上記の問題点を解決することを目的とするものであり、特に、脆弱性を有する部分を精度良く検出でき、単純なパターンマッチングで「危険な関数」の使用箇所を見つけるだけの方法と比較してプログラマがインスペクションする必要のある箇所を少なくでき、また、事前にプログラマが検査対象のソースコードに脆弱性検知の支援を目的とした注釈を記述する必要がなく、プログラマによるソースコード検査の作業負担を減らすことができるようにすることを目的とする。
上記の目的を達成するため、本発明に係るソースコード脆弱性検査装置は、検査対象のソースコードの脆弱性を検査するソースコード脆弱性検査装置であって、前記検査対象のソースコードを解析して、外部入力がどのように遷移するかを求める手段と、外部入力をパラメータとして使用すると脆弱な関数を登録した脆弱性データベースと、前記検査対象のソースコードにおける外部入力の遷移を追跡し、前記脆弱性データベースの登録内容に合致する箇所を、脆弱性を有する箇所として警告する手段とを備えることを特徴とする。
本発明では、例えば検査対象ソースコード内で使用されているライブラリに含まれる関数について、内部での処理によりどの仮引数の値がどの仮引数に移動またはコピーされるか、あるいは戻り値として返されるか、外部からの入力データを受け取るのはどの仮引数であるか、を表す仮引数間データ遷移を記述した仮引数間遷移DB(データベース)を予め備える。また、同ライブラリに含まれる、特定の仮引数に外部からの入力データを与えると脆弱性を生じる関数について、その関数名と特定の仮引数の位置を組にして登録した脆弱性DBも予め備える。
まず、検査対象ソースコードの検査にあたり、構文解析手段は、検査対象ソースコードの記述に用いたプログラミング言語の構文解析ルールに従い、検査対象ソースコードから解析木を構築する。
続いて、脆弱性解析手段は、この解析木をルートノードから所定の順序でたどり、関数定義ノードに到達したらそのノードの表すユーザ定義関数を、まだ登録されていなければ動的仮引数遷移DBに登録する。
次に、この関数定義ノードを頂点とする部分解析木を所定の順序でたどり、仮引数定義ノードに到達したら、この仮引数定義ノードの表す仮引数を変数テーブルに登録する。ここで現在処理中のユーザ定義関数について動的仮引数間遷移DBを参照し、この仮引数が外部入力データを受け取ると登録されていれば、変数テーブルにもこの仮引数の値の種類に外部入力データを登録する。
また変数定義ノードに到達したら、この変数定義ノードの表す変数を変数テーブルに登録する。
また、関数呼出しノードに到達したら、仮引数間遷移DBと動的仮引数間遷移DBを参照してこの関数呼出しノードの表す関数の仮引数間のデータ遷移を取り出す。
このデータ遷移の遷移元仮引数の値の種類としてこの関数呼出しノードの表す関数の第1の仮引数が含まれていれば、解析木を所定の順序でたどって第1の仮引数の位置に当たる第1の実引数ノードに到達する。そして変数テーブルを参照し、第1の実引数ノードの表す第1の変数について登録されている変数の保持する値の種類を読み出し、これを新たな遷移先の値の種類とする。あるいは遷移元仮引数の値の種類に外部入力データが含まれていれば、これを新たな遷移先の値の種類とする。
次に、データ遷移の遷移先仮引数の値の種類として関数呼出しノードの表す関数の第2の仮引数が含まれていれば、解析木を所定の順序でたどって第2の仮引数の位置に当たる第2の実引数ノードに到達する。そして第2の実引数ノードの表す第2の変数について、先ほど求めた新たな遷移先の値の種類を第2の変数の保持する値として変数テーブルに登録する。
さらにここで、新たな遷移先の値の種類に外部入力データが含まれ、かつ関数呼出しノードの表す関数が動的仮引数間遷移DBに登録されていれば、この関数の第1の仮引数が外部入力データを受け取ることを動的仮引数間遷移DBに追記する。
部分解析木をたどり終えたら、仮引数ごとに、変数テーブルに記録された保持する値の種類を取得して遷移元仮引数の保持する値とし、仮引数自身を遷移先仮引数の保持する値とする、新たな仮引数間データ遷移を作成し、関数呼出しノードの表す関数の新たな仮引数間データ遷移として動的仮引数間遷移DBに上書きする。
以上を検査対象ソースコードの各ユーザ定義関数について行いつつ、解析木全体をたどる。解析木全体をたどる間に一度でも動的仮引数間遷移DBに更新があれば、再びルートノードから解析木をたどり上記の処理を行う。たどり終わったときに新たな更新がなくなったら、脆弱性解析手段は、再びルートノードから解析木を所定の順序でたどり、上記の処理を行いながら、仮引数間遷移DBと動的仮引数間遷移DBを参照して変数テーブルを作成、更新する。ただし、関数呼出しノードの処理において、その新たな遷移先の値の種類に外部入力データを含み、かつその関数呼出しノードの表す関数と前記第1の仮引数の位置との組が脆弱性DBに登録されていれば、検査対象ソースコード内での前記第1の変数の記述位置を脆弱性の生じる可能性のある箇所として出力する。
本発明に係るソースコード脆弱性検査装置は、例えば検査対象のソースコードがC言語で記述されているときに、ポインタ変数自身とポインタ変数の間接参照先ごとにその値の種類を記録する。また変数のスコープに従い変数テーブルへの変数の登録・削除を行う。
本発明のソースコード脆弱性検査装置によれば、脆弱な箇所として検知する箇所を外部からの入力データを実引数として受け取る「危険な関数」の使用箇所に限定できる。そのため、検知された箇所が実際に脆弱性であるか、プログラマがインスペクションする必要のある箇所を、単純なパターンマッチングで「危険な関数」の使用箇所を見つける方法に比べて少なくできる。
すなわち本発明によれば、関数が扱うデータが、外部由来がどうか、および適切な脆弱性を回避する処理を受けているかどうかを判別するため、誤った脆弱性検出を防ぐことができる。また、あらかじめ登録した関数の呼び出し箇所だけでなく、プログラマが定義した関数の呼び出し箇所が脆弱であるかどうかも検査できる。これにより、プログラマが、脆弱性を回避する処理を行うべき場所を容易に特定できる。また、ソースコードにその内容と直接関係のない脆弱性検知を目的とした注釈を記述する必要がない。また、プログラマによるソースコード検査の作業負担が少ない。
本発明のソースコード脆弱性検査装置では、変数値の出所をポインタ変数自身やポインタ変数の間接参照先ごとに記録できるので、C言語のような間接参照をサポートするプログラミング言語で記述されたソースコードの検査も可能である。また、変数のスコープに従って変数テーブルへの変数の登録・削除を行うので、変数のスコープを考慮しない場合に比べて変数テーブルへの登録数を少なくして、ソースコード検査にかかる時間を減らすことができる。
以下、図面を用いて本発明の実施の形態を説明する。まず、第1の実施形態を説明し、その後、第2の実施形態を説明する。
図1は、本発明の第1の実施形態であるソースコード脆弱性検査装置の構成図である。
101はソースコード脆弱性検査装置の本体(コンピュータ)で、CPU102、記憶装置103、及びメモリ104を備える。CPU102は、ソースコード検査を行うプログラムの実行や各種制御を行う。記憶装置103には、ソースコード検査を行うプログラム、検査対象のソースコード、及び、後述する仮引数間遷移DB204や脆弱性DB205などが保存される。メモリ104は、CPU102で実行されるプログラムなどの扱う各種データを一時的に記憶する。
キーボード105はソースコード脆弱性検査装置に指示を送るための入力装置、CRT106はソースコード脆弱性検査装置の表示装置である。外部記憶装置107は、ソースコード脆弱性検査装置に検査対象のソースコードを入力したり、検査結果を出力するための記憶装置である。バス108はこれら各部102〜107を相互に接続するバスであり、CPU102の指示で移動されるデータの通り道である。
図2は、ソースコード脆弱性検査装置の機能の概要図である。ソースコード脆弱性検査装置は、構文解析手段201、及び脆弱性検出手段202を備える。これらの手段は、CPU102がソースコード検査を行うプログラムを実行することにより実現されるものである。
構文解析手段201は、構文解析ルール203に従って検査対象ソースコード208を構文解析して解析木210を構築する。
脆弱性検出手段202は、解析木210をたどり、検査対象ソースコード208内で定義された関数(ユーザ定義関数)を列挙し、動的仮引数間遷移DB206を作成する。更に検査対象ソースコード208内で定義された変数を変数テーブル207に登録する。そして、検査対象ソースコード208の使用するライブラリで提供される関数(ライブラリ関数)について予め作成された仮引数間遷移DB204と、解析木210をたどりながら作成・更新する、動的仮引数間遷移DB206に従い、変数間のデータ遷移を追跡し、変数の保持する値の種類を変数テーブル207に逐次記録する。ここで、ファイルI/Oや通信などで外部から入力されたデータを参照する変数が、脆弱性DB205に予め登録された危険なライブラリ関数(「危険な関数」とされるライブラリ関数)の実引数として与えられる場合、検査対象ソースコード内の該当する箇所を脆弱な箇所として脆弱性検査結果209に出力する。
図3は、ソースコード脆弱性検査装置の構文解析手段201及び脆弱性検出手段202の詳細な処理手順である。手順301は構文解析手段201により実施され、それ以降の手順は脆弱性検出手段202により実施される。以下、各手順の詳細、及び図2の203〜207について説明する。
手順301において、構文解析手段201は、検査対象ソースコード208と構文解析ルール203を読込み、解析木210を構築する。
ここでは、図4に示すC言語で記述した検査対象ソースコード208を例にしてソースコード脆弱性検査装置の処理手順を説明する。図4の左端の行番号は、説明の便宜上、記したものである。なお、本処理手順は他のプログラミング言語で記述されたソースコードにも適用可能である。
構文解析ルール203は、検査対象ソースコード208の記述に用いられたプログラミング言語の文法を解釈するために予め定義されたルールである。本実施形態はルールの記述方法や内容、構文解析の手順を特定しないが、構文解析では少なくともソースコード内で使用されているグローバル変数、ローカル変数、仮引数、ユーザ定義関数、及びライブラリ関数を識別し、またソースコードを処理の最小単位である式に分解して解析木210を構築可能であることを前提とする。
図5は、図4のソースコードから構築された解析木210の例である。説明の便宜上、左端に行番号を記している。図中の囲み文字は、ソースコードの解析単位であるノードを表す。解析木210の各末端ノード(子ノードを持たないノード)のカッコ内の文字は、その末端ノードに対応するソースコードの断片である。図5では解析されたソースコードの主要なノードのみ記しており、括弧やセミコロンなどの区切り文字、演算子などは省略されている。
本実施形態では解析木210の構造を特に指定しないが、解析木210は、解析されたソースコードの全ノード(関数定義、式、変数など)の親子関係を、ルートノードを頂点とする木構造に表したものとする。また、所定の順序(図5の例ではルートノードを始点に上から下、左から右に向かって順に)に従うと末端ノードのソースコードの断片をソースコード内での出現順にたどれるものとする。
なお本実施形態の説明では、リスト構造のデータを'['、']'、集合を'('、')'で囲み、それぞれの各要素を','で区切って表記する。
また、検査対象ソースコード208をコンパイルして実行した際に検査対象ソースコード208内の各変数や仮引数が保持する値を、本実施形態の説明では抽象化して表記する。基本的な表記方法は、変数の値については変数テーブル207に登録された変数に割り当てられる識別番号に抽象化して表記するものとし、仮引数の値についてはライブラリ関数やユーザ定義関数の各仮引数を左から順に1、2、3と割り当てた仮引数番号に抽象化して表記するものとし、さらにその変数や仮引数で可能な間接参照の深さに応じた数の'*'を前置するものとする。例えば、識別番号(仮引数番号)として3を割り当てた変数(仮引数)の可能な間接参照の深さが0(ポインタではない)ならば、その値を'3'と表記する。可能な間接参照の深さが1(ポインタや1次元配列数)ならば、ポインタ変数(仮引数)自身の値を'3'、その間接参照先の値を'*3'と表記する。可能な間接参照の深さが2(ポインタのポインタや2次元配列)ならば、ポインタのポインタである変数(仮引数)自身の値を'3'、その間接参照先の値を'*3'、さらにその間接参照先の値を'**3'と表記する。ライブラリ関数やユーザ定義関数の戻り値を表す仮引数番号として0を用いる。また、可変長仮引数を表記する場合は可変長仮引数の仮引数番号に'...'を後置する。変数や仮引数がファイルI/Oや通信など外部入力を取得するライブラリ関数の呼出しで直接取得した外部入力データを保持する場合は'IN'と表記する。変数や仮引数の保持する値が外部へ出力される場合を示す場合は'OUT'と表記する。以上で説明した、変数や仮引数の保持する値を抽象的に表記したものを、本実施形態では参照データと呼ぶ。
手順301の後、手順302において、脆弱性検出手段202は、解析木210及び仮引数間遷移DB204を読込む。
図6は、仮引数間遷移DB204の例である。仮引数間遷移DB204は、内部での処理により仮引数の間でその保持する値のコピーや移動等のデータ遷移を伴うライブラリ関数を予め列挙したDBであり、検査対象ソースコード208のプログラミング言語や使用するライブラリ、コンパイラの処理系によって内容は異なる。ここではANSI C標準ライブラリの関数の例を示している。
図6の仮引数間遷移DB204の1列目は関数名である。2列目はどの仮引数の値がどの仮引数に遷移するか示すデータ遷移のリストである。このリストを仮引数間遷移リスト、リスト内の各要素を仮引数間遷移エレメントと、呼ぶ。各仮引数間遷移エレメントは、矢印'→'の左の参照データ(遷移元参照データ)で表記される仮引数の保持する値の全部または一部が、'→'の右の参照データ(遷移先参照データ)で表記される仮引数に複製されることを意味する。なお、仮引数間遷移リスト内の各エレメントは左から順に評価されるものとする。値渡しの仮引数は関数呼出しの前後でその値が必ず不変なので、このことを表す仮引数間遷移エレメント(例えば'1→1')は仮引数間遷移リストに加えない。参照渡しの仮引数についてはその仮引数で可能な間接参照先が上書きされて残らない場合を除き、仮引数間遷移エレメント(例えば可能な間接参照の深さが2の仮引数なら'*1→*1'と'**1→**1')を必ず仮引数間遷移リストに加えるものとする。
図6の例によると、関数getsは外部入力データが第1仮引数の間接参照先に遷移し、さらに第1仮引数のポインタが戻り値として返される。関数sprintfは第2仮引数と第3仮引数以降の可変長仮引数の間接参照先が不変で、これら間接参照先の値が第1仮引数の間接参照先に遷移する。関数putsは第1仮引数の間接参照先が不変で、かつ外部に出力される。
なお、仮引数間遷移DB204や動的仮引数間遷移DB206への登録対象は、特定のデータ型の仮引数を扱う関数に限定しても、データ型に関係なく全ての関数でもよい。本実施形態では、文字列の格納に使われるchar*型、const char*型を扱うものに限定している。
手順303において、脆弱性検出手段202は、解析木210をルートノードから所定の順序で全てたどり、見つかったユーザ定義関数を動的仮引数間遷移DB206に、グローバル変数を変数テーブル207に、それぞれ登録する。ここでの登録内容は暫定的なもので、手順305〜312において更新される。
図7は、図5の解析木210をたどって作成された動的仮引数間遷移DB206の例である。動的仮引数間遷移DB206の1列目と2列目は仮引数間遷移DB204と同じである。3列目は外部入力データを受け取ることのある仮引数の集合で、集合の各要素である外部入力仮引数を参照データとして表記する。手順303の時点では仮引数間のデータ遷移は不明なので、2列目の仮引数間遷移リストの初期値には参照渡しの仮引数だけについて参照先が不変であることを示す仮引数間遷移リストを与える。各仮引数が外部入力データを受け取るかどうかもこの時点では不明なため、3列目の外部入力仮引数集合の初期値を空集合とする。ただし、関数mainだけは第2引数(char型のポインタ配列)がプログラム実行パラメータを受け取るとC言語の仕様で定められているため、そのことを表す外部入力仮引数集合'(**2)'を初期値とする。
図5の解析木210にはグローバル変数が含まれていないので、ここでは変数テーブル207への登録はない。登録する場合の初期値は、手順308で説明するローカル変数のそれと同じである。
手順304において、脆弱性検出手段202は、初めて手順304を実施する場合、あるいは手順305〜312での解析木全探索を終了して手順304に戻ったときにその全探索の前後で動的仮引数間遷移DB206の内容が更新されている場合、次に手順305を実施する。それ以外の場合、手順313に進む。手順305において、脆弱性検出手段202は解析木210の探索をルートノードから始める。手順306において、脆弱性検出手段202は、解析木210の探索が終了していれば次に手順304を実施し、終了していなければ手順307に進む。

手順307において、脆弱性検出手段202は、これまでに探索済みのノードの次から解析木210を所定の順序でたどり、最初に到達した関数定義ノードを頂点とする部分解析木を手順308〜312の処理の対象とする。この部分解析木で表されるユーザ定義関数を以下では対象関数と呼ぶ。
図5の解析木210ではまず関数format_stringが対象関数となる。以降の説明では特に断らない限り、変数とは対象関数の仮引数とローカル変数、及びグローバル変数を意味する。
手順308において、脆弱性検出手段202は、対象関数の部分解析木を所定の順序でたどり、対象関数の仮引数や関数本体で定義されたローカル変数が見つかれば、それらを変数テーブル207に登録する。
図8は、図5に示す部分解析木の関数format_stringの仮引数(図5の5〜11行目)について手順308を実施した後の変数テーブル207の内容である。変数(仮引数)毎に1行のデータが変数テーブル207に追加される。1列目は変数テーブル207に登録された変数の識別番号で、登録順に1から付けられる。2列目は変数の種別を表し、仮引数を登録する場合は'A'、ローカル変数なら'L'、グローバル変数なら'G'を格納する。3列目は変数の型、4列目は変数名、5列目は変数の保持する値を表す参照データ(変数参照データ)の集合(変数参照データ集合)から構成されるリスト(変数参照データ集合リスト)である。
図8の変数テーブル207の変数参照データ集合リストの要素(変数参照データ集合)の数は各変数で可能な間接参照の深さで決まる。変数が基本データ型(int型やchar型などポインタや配列でない単純なデータ型)なら要素数は1、ポインタまたは1次元配列なら2、ポインタのポインタまたは2次元配列なら3である。また、リスト内の各変数参照データ集合の位置はその変数の間接参照の繰り返し数に対応し、リストの先頭の変数参照データ集合はこの変数の値を表す変数参照データの集合、2つめの変数参照データ集合は変数の間接参照先の値を表す変数参照データの集合、3つめの変数参照データ集合は変数の間接参照先の間接参照先の値を表す変数参照データの集合である。変数の値やその間接参照先の値を変数参照データの集合とする理由は、例えば変数が複数の変数からコピーされた文字列を連結した文字列を保持する状態に対応するためである。なお、変数テーブル207における各変数参照データ内の数字は変数の識別番号である。
図8の変数テーブル207の変数参照データ集合リストの初期値は変数の種別により異なる。ローカル変数では、その初期化が行われていない場合、及び定数値による初期化の場合は、次のとおりである。まずローカル変数で可能な間接参照の深さごとに、そのローカル変数の変数テーブル207での識別番号に間接参照の深さに応じた'*'を前置した変数参照データを生成する。そして、各変数参照データを唯一つの要素とする変数参照データ集合を要素とするリストを初期値とする。なお、定数値で初期化される変数の場合、一番深い間接参照に対応する変数参照データ集合は、定数値を表す参照データ'C'を用いて'(C)'とする。例えば、ポインタのポインタであるローカル変数において、その可能な間接参照の深さは0、1、2なので、初期化されていない場合の変数参照データ集合リストの初期値は'[ (1), (*1), (**1) ]'、定数値で初期化されている場合の初期値は'[ (1), (*1), (C) ]'となる。ローカル変数の初期化に他の変数や関数呼び出しが含まれる場合、前記初期値に、初期化データを生成するための式に手順309の処理を加えたものとする。
グローバル変数の場合は、ローカル変数の場合と同じである。
仮引数の場合は、初期化されないローカル変数と同様の変数参照データ集合リストを初期値とする。ただし、外部入力データを渡される可能性のある仮引数については、該当する間接参照の深さの変数参照データ集合に擬似外部入力データ'PIN'を初期値に追加する。ここでの外部入力データの有無の判定は次のようにして行う。まず、変数テーブル207に登録しようとする仮引数の仮引数番号を取得する。この時点では解析木210の仮引数リストノードを頂点とする部分解析木をたどっている途中なので、登録しようとする仮引数が何番目の引数であるか、つまり仮引数番号が分かる。次に対象関数の名前をキーとして動的仮引数間遷移DB206を検索し、一致する行の外部入力仮引数集合を読み出す。この集合から前記仮引数番号を含む外部入力仮引数を全て取得する。そして、各外部入力仮引数について、間接参照の深さ(仮引数番号に前置された'*'の数)を求め、変数参照データ集合リスト内で左から前記深さに1を加えた位置の変数参照データ集合に'PIN'を追加する。例えば、対象関数の第2仮引数を変数テーブル207に登録する際、この第2引数の変数テーブル207内での変数識別番号が4、対象関数の名前をキーとして動的仮引数間遷移DB206を検索して読み出した外部入力仮引数集合が'(*1, **2)'だったとする。この集合内で、現在、処理対象の引数番号'2'を含む外部入力仮引数は'**2'であり、その間接参照の深さは2である。したがって、変数参照データ集合リストの初期値は、外部入力仮引数が無い時の初期値'[ (4), (*4), (**4) ]'の3番目の集合に'PIN'を加えた'[ (4), (*4), (**4, PIN) ]'となる。なお、関数mainの第2仮引数には必ず外部入力データが与えられるので、この第2仮引数について、変数テーブル207の変数参照データ集合リストの初期値は、仮にその変数識別番号が3とすると、'[ (3), (*3), (IN) ]'とする。
以上で説明した手順308を対象関数format_stringについて実施すると、図5の解析木からまずchar型へのポインタである仮引数stroutが見つかる(6〜8行目)。この時点での動的仮引数間遷移DB206(図7)の関数名の列内を対象関数の名前format_stringで検索すると、一致した行の外部入力仮引数集合は空である。仮引数stroutは変数テーブル207に登録する最初のデータなので識別番号は1となり、変数参照データ集合リストの初期値は'[ (1), (*1) ]'となる(図8の番号1の行)。続いて図5の解析木から仮引数strinが見つかって(9〜11行目)変数テーブル207での識別番号が2となり、この仮引数に該当する外部入力仮引数は存在しないので、変数参照データ集合リストの初期値は'[ (2), (*2) ]'となる(図8の番号2の行)。
図4のソースコードの例には含まれていないが、戻り値を返す対象関数の場合、その戻り値の参照データを記録するための行も変数テーブル207に追加する。その種別はAで仮引数扱い、変数型は戻り値の型、名前は'return'(C言語では予約語のため変数名に使えず、ユーザ定義変数と重複しない)、変数参照データ集合リストは戻り値の間接参照の深さに応じた空集合を並べたリスト(例えば深さが2なら、[ ( ), ( ), ( ) ])として登録する。
なお、手順308においては、変数テーブル207に登録した仮引数の仮引数番号と、その仮引数を変数テーブル207に登録した際に割り当てられた変数識別番号の組も、仮引数ごとに記憶しておく。
手順309において、脆弱性検出手段202は、探索済みのノードの次から解析木210を所定の順序でたどり、変数の値が別の変数に移る可能性のあるノードに到達すると、そのノードを頂点とする部分解析木について、仮引数間遷移DB204及び動的仮引数間遷移DB206を参照してデータ遷移を追跡し、変数テーブル207を更新する。
変数の値が別の変数に遷移する可能性のあるノードには関数呼出しや代入文などがある。関数呼出しのノードにたどり着いたら、そのノードを頂点とする部分解析木を処理対象とする。例として図4に示すソースコードの関数format_stringについて手順309を実施すると、図5の解析木210の探索を再開後に最初に到達する、変数間での値の遷移が起きる可能性のあるノードは、関数呼出しノードである(図5の15行目)。このノードを頂点とする部分解析木をここでの処理対象とする(同15〜26行目)。
以下、図9を用いて、関数呼出しの部分解析木を解析するときの変数テーブル更新処理(手順309)の詳細な手順を説明する。
手順901において、脆弱性検出手段202は、部分解析木内をたどって呼び出される関数の名前を取得する。図5の解析木210の例において、関数呼出しノードの次に到達する識別子ノード(同16行目)のソースコード断片から、呼び出される関数の名前sprintfを得る。
手順902において、脆弱性検出手段202は、部分解析木をたどり、この関数呼出しの全実引数を取得して各実引数が変数であるか定数であるか調べる。図5の解析木210の例では、各実引数ノードから、第1実引数strout、第2実引数"input=%s"、第3実引数strinを得る。式ノードを直接の親ノードとする識別子ノードは変数を意味するので、第1実引数と第3実引数は変数であることが分かる。第2実引数に当たるノードは、文字列ノードであるので、定数値であることが分かる。
手順903において、脆弱性検出手段202は、先に取得した関数名をキーとして仮引数間遷移DB204及び動的仮引数間遷移DB206の関数名欄を検索し、一致する行から仮引数間遷移リストを得る。なお、各DBを検索して一致行が見つからない場合(処理対象の関数呼出しに使われた関数が仮引数間遷移DB204に登録されてない場合)は図9の手順を終える。上記の例では、関数名sprintfをキーとして両DBを検索すると、図6の仮引数間遷移DB204の3行目に一致する行が見つかる。そこで、この行から仮引数間遷移リスト'[*2→*1, *2→*2, *3...→*1, *3...→*3...]'を取得する。
手順904において、脆弱性検出手段202は、先に得た仮引数間遷移リストの左から順に仮引数間遷移エレメントを取り出して手順905から手順909の処理を行い、変数間のデータ遷移を評価する。全ての仮引数間遷移エレメントについて処理を終えたら、次に手順910を行う。
手順905において、脆弱性検出手段202は、評価対象の仮引数間遷移エレメントから遷移元参照データと遷移先参照データを取り出す。両者に仮引数番号が含まれている場合、及び遷移元参照データが'IN'で遷移先参照データが仮引数番号を含む場合、遷移先参照データに含まれる仮引数番号に該当する実引数が変数であれば、次の処理に移る。これら以外の場合、手順904に戻り、次の仮引数間遷移エレメントを評価対象とする。図5の例では、まず1つめの仮引数間遷移エレメント'*2→*1'について、遷移元、遷移先ともに仮引数番号が含まれるので手順906に移る。なお、3つめ、4つめの仮引数間遷移エレメントの場合も手順906に進めるが、2つめの仮引数間遷移エレメント'*2→*2'は遷移先参照データに含まれる仮引数番号に対応する実引数が定数であるので手順904に戻る。
手順906において、脆弱性検出手段202は、評価対象の仮引数間遷移エレメントについて、仮引数番号を含む遷移元参照データ及び遷移先参照データの間接参照の深さを調べる。これは仮引数番号に付加されたアスタリスク'*'を数えて求める。上記の例では、遷移元参照データ'*2'、遷移先参照データ'*1'から間接参照の深さは共に1である。
手順907において、脆弱性検出手段202は、遷移元参照データに仮引数番号が含まれていれば、部分解析木内の該当する実引数の参照データ集合を取得する。仮引数番号に対応する実引数が変数であれば、その変数の名前をキーとして変数テーブル207の名前欄を検索し、一致する行の変数参照データ集合リストを得る。このリスト内から、先に求めた遷移元の間接参照の深さに対応する変数参照データ集合(以下、遷移元変数参照データ集合と呼ぶ)を取り出す。仮引数番号に対応する実引数が定数であれば'(C)'を遷移元変数参照データ集合とする。遷移元参照データに可変長仮引数を表す'...'が含まれているため実引数に該当する変数や定数が複数ある場合、それら全てについて上記処理を行い、その結果の和集合(ただし要素の重複を許さない)を遷移元変数参照データ集合とする。遷移元参照データが'IN'であれば、'(IN)'を遷移元変数参照データ集合とする。上記の例では、遷移元参照データ'*2'から遷移元が第2引数と分かり、これは定数値であるので'(C)'を遷移元変数参照データ集合とする。
手順908において、脆弱性検出手段202は、呼び出される関数がユーザ定義関数であり、かつ遷移元変数参照データ集合に'IN'または'PIN'が含まれている場合、呼び出される関数に外部入力データが渡されることを記録するため、この関数について動的仮引数間遷移DB206の外部入力仮引数集合を更新する。先に取得した呼び出される関数の関数名をキーとして動的仮引数間遷移DB206を検索し、一致する行の外部入力仮引数集合に遷移元参照データが含まれていなければ、この遷移元参照データそのものを外部入力仮引数集合に追加する。上記の例では該当する場合がないので具体例の説明は省略する。
手順909において、脆弱性検出手段202は、遷移先参照データに含まれる仮引数番号に対応する実引数の変数の名前をキーとして変数テーブル207の名前欄を検索して一致する行を探し、その変数識別番号を得る。そして、この変数識別番号と手順906で得た遷移先参照データの間接参照の組に、手順907で得た遷移元変数参照データ集合をさらに組にして、暫定遷移先変数参照データ集合として一時的に記憶する。暫定遷移先変数参照データ集合は遷移先(変数識別番号と間接参照の深さの組)毎に作成する。なお、同一の遷移先(変数識別番号と間接参照の深さの組)に複数のデータ遷移が存在する場合には、新たな遷移元変数参照データ集合が得られる度に暫定遷移先変数参照データ集合内の遷移元変数参照データ集合に連結する。上記の例では、遷移先実引数の変数の名前stroutをキーとして図8の変数テーブル207の名前欄を検索し、一致した行の番号欄からその変数識別番号1を得る。また先に得た遷移先の間接参照の深さは1である。これらの組に先に得た遷移元変数参照データ集合'(C)'をさらに組にして一時的に記憶する。この暫定遷移先変数参照データ集合を、便宜的に、遷移先変数の変数識別番号、その関節参照の深さ、遷移元変数参照データ集合の順に'(1, 1, (C))'と記述する。上述の手順909の後、手順904に戻る。
ここまでの処理で、上記の例では、3つめの仮引数間遷移エレメントを処理する際に1つめと同じ変数識別番号と間接参照の深さの組からなる暫定遷移先変数参照データ集合を得るので、これらをマージした暫定遷移先変数参照データ集合は'(1, 1, (C, *2))'を得る。4つめの仮引数間遷移エレメントの処理から得られる暫定遷移先変数参照データ集合は'(2, 1, (*2))'である。
手順910において、脆弱性検出手段202は、暫定遷移先変数参照データ集合のそれぞれについて以下の処理を行い、変数テーブル207を更新する。暫定遷移先変数参照データ集合から遷移先変数の変数識別番号を取得し、これをキーとして変数テーブル207の番号欄を検索して一致した行から変数参照データ集合リストを得る。このリストについて、暫定遷移先変数参照データ集合から得られる間接参照の深さに対応する位置に、同じく暫定遷移先変数参照データ集合から得られる遷移元変数参照データ集合を上書きする。この結果として得られる新たな変数参照データ集合リストを変数テーブル207の元の場所に上書きして、次の暫定遷移先変数参照データ集合の処理に移る。全ての暫定遷移先変数参照データ集合について上記処理を終えたら、手順309における変数テーブル207の更新処理を終了する。例えば、上記の例において図8の変数テーブル207を更新すると、上記1つめの暫定遷移先変数参照データ集合'(1, 1, (C, *2))'について、遷移先変数の変数識別番号1を得る。これをキーとして図8の変数テーブル207の番号欄を検索し、一致した行の変数参照データ集合リスト'[ (1), (*1) ]'を得る。また上記1つめの暫定遷移先変数参照データ集合から遷移先変数の間接参照の深さ1を得る。これに対応する上記変数参照データ集合リストの2番目の位置に、さらに上記1つめの一時記憶データから得た遷移元変数参照データ集合'(C, *2)'を上書きし、'[ (1), (C, *2) ]'を得る。この結果を図8の変数テーブル207の元の位置に上書きする。同様に、上記2つめの暫定遷移先変数参照データ集合について処理を行うと、図8の変数テーブル207の番号2の行の変数参照データ集合リストの2番目の要素を遷移元変数参照データ集合'(*2)'で上書きし、さらに図8の変数テーブル207の元の位置に上書きする。以上で変数テーブル207の更新処理を終了する。更新後の変数テーブル207を図10に示す。
以上で図9の説明を終える。
図9の処理手順は関数呼出しの場合であるが、代入文など演算子を介した変数の更新処理についても、その部分解析木が前記sprintf関数呼出しについての部分解析木(図5の15〜26行目)と同様に構築されるので、ほぼ同じ手順で処理できる。
例えばポインタの代入'p=q'の場合(変数p、qはchar*型とする)、左辺の仮引数番号を1、右辺の仮引数番号を2として、その仮引数間遷移リストは'[2→1, →*1, *2→*2]'である。代入後はポインタがコピーされ変数pの間接参照先は変数qと同じなので、前記リストではポインタ自身のコピー('2→1')と、変数pの間接参照先のクリア('→*1')を指示している。仮にchar*型のポインタ変数a、bについてポインタの代入'a=b'を処理する際、代入前の変数テーブル207が図11の状態であれば、代入後は図12のように更新され、変数aの間接参照先に当たる変数参照データ集合は空集合となる。なお、変数aがこの状態のときに変数aの間接参照先の参照データが関数呼出しや代入文の処理において必要とされた場合、空の変数参照データ集合より間接参照が一つ浅い(図12においては変数参照データ集合リスト内の左隣の)集合内の変数識別番号を取り出す。そして、この番号で識別される変数の変数参照データ集合リスト内から元々必要とされた間接参照の深さの変数参照データ集合を読み出して使用する。これも空集合であれば、空集合でないものが見つかるまで上記処理を繰り返す。
また、関数呼出しの実引数や演算子の演算対象として別の関数呼出しや演算子による演算の結果が使われる場合、その結果を一時的なローカル変数の値とみなして変数テーブル207に登録し、この結果が返される位置に該当する部分解析木内のノードを上記一時ローカル変数のノードとみなすことで、手順309の処理手順を適用して変数テーブル207を更新できる。
return文で変数の値が返される場合、変数テーブル207に変数名returnとして登録した行の変数参照データ集合リストに、前記変数の変数参照データ集合リストをマージする。この際、同一の間接参照の深さごとに両者の変数参照データ集合の和集合を取り、その結果を変数名returnの新たな変数参照データ集合リストとする。return文で定数値が返される場合は'(C)'をマージする。
再び図3に戻って、手順310において、脆弱性検出手段202は、対象関数の部分解析木の探索が終了していれば手順311に、終了していなければ手順308に戻る。
手順311において、脆弱性検出手段202は、変数テーブル207の内容に基づき、対象関数について動的仮引数間遷移DB206の内容を更新する。対象関数の仮引数それぞれについて、その仮引数の変数参照データ集合リストを変数テーブル207から取得して仮引数間遷移エレメントを生成し、最後にそれらエレメントを連結して仮引数間遷移リストとする。
手順311での処理の詳細を説明する。まず、変数テーブル207の種別欄で種別が'A'(仮引数)となっている行を選び、その変数識別番号をすべて取得する。本実施形態では対象としているC言語では入れ子の関数定義が許されていないので、変数テーブル207に仮引数として登録されているものは対象関数の仮引数のみである。
取得した変数識別番号のそれぞれについて以下の処理を行う。まず、変数テーブル207から処理対象の変数識別番号の行の変数参照データ集合リストを取り出す。そして、リスト内の変数参照データ毎に仮引数間遷移エレメントを生成する。その遷移元参照データには、手順308の処理で記憶した仮引数番号と変数識別番号の組を参照して、処理対象の変数参照データに含まれる変数識別番号を仮引数番号に変換した参照データを用いる。遷移先参照データには、同様に仮引数番号と変数識別番号の組を参照して処理対象の変数識別番号を仮引数番号に変換したものに、処理対象の変数参照データが含まれる変数参照データ集合の表す間接参照の深さを組み合わせた、参照データを用いる。なお、変数参照データ集合が空集合の場合、仮引数間遷移エレメントの遷移元参照データは無しとする。また、処理対象の変数参照データにローカル変数の変数識別番号や擬似外部入力データを表す'PIN'や定数値を表す'C'が含まれる場合は無視し、グローバル変数が含まれる場合はその変数識別番号に'G'をつけて仮引数間遷移エレメントに含める。
以上のように生成した仮引数間遷移エレメントを全て連結して対象関数の新たな仮引数間遷移リストを構成する。対象関数の名前をキーとして動的仮引数間遷移DB206を検索し、一致する行の仮引数間遷移リストを更新する。なお、遷移元参照データ及び遷移先参照データに含まれる仮引数番号が同一で、かつ両者の間接参照の深さが0の仮引数間遷移エレメントは仮引数間遷移リストに連結しない。
上述の手順311の処理を図10の変数テーブル207について行うと、種別欄が'A'である行は変数識別番号が1と2のものである。まず変数識別番号1の行について、変数参照データ集合リスト'[ (1), (C, *2) ]'を取り出す。最初の変数参照データ'1'に関して生成される仮引数間遷移エレメントは'1→1'、2つめの変数参照データ'*2'に関して生成される引数遷移エレメントは定数を表す'C'を無視して'*2→*1'となる。同様に、変数識別番号2の行について、生成される仮引数間遷移エレメントは順に'2→2'、'*2→*2'である。これらを連結して構成される新たな仮引数間遷移リストは、連結対象から除外する場合を考慮して、'[*2→*1, *2→*2]'となる。この結果、動的仮引数間遷移DB206は図13のように更新される。
手順312において、脆弱性検出手段202は、対象関数に係わる仮引数とローカル変数についての登録データを変数テーブル207から削除する。
なお、グローバル変数について変数テーブル207に登録された変数参照データ集合リストに、ポインタの代入処理などのためローカル変数や仮引数の変数識別番号を含む参照データが含まれている場合、その変数識別番号について変数テーブル207を参照し、その参照データの間接参照の深さに対応する変数参照データ集合と置き換える。
なお、本実施形態の説明では簡略化のため変数のスコープを考慮していないが、ローカル変数と仮引数の変数テーブル207への登録はそのスコープに入ったとき、削除はスコープの外に出たときに行う。解析木210を所定の順序でたどり、変数定義または変数宣言のノードがあればその変数のスコープが始まる。解析木210内でのこのノードの深さを変数テーブル207に記録して解析木210の探索を続け、探索中のノードの深さが変数テーブル207に登録したものより浅くなれば前記変数はスコープから外れたと分かるので、変数テーブル207から該当データを削除すればよい。
以上で、1つの対象関数についての処理が終わり、手順306に戻る。
図4のソースコードについて引き続き手順306〜312を実施すると、動的仮引数間遷移DB206及び変数テーブル207は次のように更新される。
図4のソースコードの関数get_inputについて手順308終了時の変数テーブル207は、図14である。
同関数について手順309終了時の変数テーブル207は図15に更新され、動的仮引数間遷移DB206は図13のままである。ここでは関数getsの呼出しについて、仮引数間遷移DB204を基に、図14の変数テーブル207に登録された変数inの変数参照データ集合リストが更新されている。
同関数について手順311終了時の動的仮引数間遷移DB206は図16に更新される。ここでは図15の変数テーブル207を基に、図13の動的仮引数間遷移DB206内の関数get_inputについての仮引数間遷移リストが更新されている。
図4のソースコードの関数put_inputについて手順308終了時の変数テーブル207は、図17である。
同関数について手順309終了時の変数テーブル207は図17のまま、動的仮引数間遷移DB206も図16のままである。
同関数について手順311終了時の動的仮引数間遷移DB206は、図16のままである。
図4のソースコードの関数mainの18行目について手順308終了時の変数テーブル207は、図18である。ここでは関数mainについて動的仮引数間遷移DB206に登録された外部入力仮引数集合を参照すると、第2仮引数に外部入力データが与えられている。したがって、第2仮引数argvについて変数テーブル207に登録される変数参照データ集合リストには、その参照の深さ2に対応する変数参照データ集合の初期値に'(IN)'が設定されている。
同関数の19行目について手順309終了時の変数テーブル207は図19に更新され、動的仮引数間遷移DB206は図16のままである。ここでは図18の変数テーブル207に登録されている変数inbufの変数参照データ集合リストが、ユーザ定義関数get_inputの呼出しについて図16の動的仮引数間遷移DB206に従い更新されている。
同関数の20行目について手順309終了時の変数テーブル207は図20に更新され、動的仮引数間遷移DB206は図21に更新される。ここでは、図19の変数テーブル207に登録されている変数outbufの変数参照データ集合リストが、ユーザ定義関数format_stringの呼出しについて図16の動的仮引数間遷移DB206に従い更新されている。また、同変数テーブル207に登録されている変数inbufの変数参照データ集合リストに'IN'が含まれているので、ユーザ定義関数format_stringについて図16の動的仮引数間遷移DB206に登録された外部入力仮引数集合が図21に更新されている。
同関数の21行目について手順309終了時の変数テーブル207は図20のままで、動的仮引数間遷移DB206は図22に更新される。図20の変数テーブル207に登録されている変数outbufの変数参照データ集合リストに'IN'が含まれているので、同関数について図21の動的仮引数間遷移DB206に登録された外部入力仮引数集合が図22に更新されている。
手順311は、同関数が仮引数間遷移DB204に登録されているため、実施しない。
以上で図5の解析木210の探索が終わるので手順304に戻る。現在の動的仮引数間遷移DB206(図22)は前回の手順304の実施時のそれ(図7)と異なるので、手順305〜312を再び実施する。
図4のソースコードの関数format_stringについて2回目の手順308終了時の変数テーブル207は、図23である。ここでは同関数について図22の動的仮引数間遷移DB206に登録された外部入力仮引数集合に基づき、変数テーブル207に登録される仮引数strinの変数参照データ集合リストの初期値に擬似外部入力データ'PIN'が含まれている。
同関数について2回目の手順309終了時の変数テーブル207は図24に更新され、動的仮引数間遷移DB206は図22のままである。ここでは関数sprintfの呼出しについて仮引数間遷移DB204に基づき、図23の変数テーブル207の変数stroutの変数参照データ集合リストが図24に更新されている。
同関数について2回目の手順311終了時の動的仮引数間遷移DB206は、図22のままである。1回目の同手順実施時とは異なり変数参照データ集合リストに'PIN'が含まれているが、仮引数間遷移リストの生成には利用されないので、図22の動的仮引数間遷移DB206は更新されない。
図4のソースコードの関数get_inputについて2回目の手順306〜312を実施時の変数テーブル207の変化の様子は1回目のそれと同じである(図14)。そのため、同関数について動的仮引数間遷移DB206に登録される仮引数間遷移リストも1回目のそれと変わらず、図22の動的仮引数間遷移DB206がそのまま維持される。
図4のソースコードの関数put_inputについて2回目の手順308終了時の変数テーブル207は、図25である。ここでは、同関数について図22の動的仮引数間遷移DB206に登録された外部入力仮引数集合に基づき、変数テーブル207に登録される仮引数outの変数参照データ集合リストの初期値に擬似外部入力データ'PIN'が含まれている。
同関数について2回目の手順309終了時の変数テーブル207は図25のまま、動的仮引数間遷移DB206も図22のままである。
同関数について2回目の手順311終了時の動的仮引数間遷移DB206は、図22のままである。
図4のソースコードの関数mainについて2回目の手順306〜312を実施時の変数テーブル207の変化の様子は1回目のそれと同じである(図18〜21)。そのため、同関数について動的仮引数間遷移DB206に登録される仮引数間遷移リストも1回目のそれと変わらず、図22の動的仮引数間遷移DB206がそのまま維持される。
以上で図5の解析木210の2回目の探索が終わるので手順304に戻る。現在の動的仮引数間遷移DB206(図22)は前回の手順304の実施以降で更新されていないので、手順313に移る。
手順313において、脆弱性検出手段202は、脆弱性DB205を読込む。
脆弱性DB205の例を、図26に示す。1列目は脆弱性を生じる可能性のある関数の名前である。2列目は外部入力データが与えられると脆弱性を生じる可能性のある仮引数を参照データ形式でリスト化した脆弱仮引数リストで、数字は仮引数番号である。
手順314において、脆弱性検出手段202は、解析木210をルートノードから所定の順序でたどり、脆弱性DB205の脆弱性仮引数リストに登録された仮引数に'IN'または'PIN'を含む変数が与えられる箇所を脆弱性検査結果209として出力する。
手順314では、これまでに構築された動的仮引数間遷移DB206と変数テーブル207に基づき、手順305〜312を実施する。ただし、動的仮引数間遷移DB206の更新に関する手順(手順311、及び手順309の処理を詳細化した図9の手順908)は省略する。また、手順910の処理の直前において、脆弱性DB205を参照して脆弱性検出ルールに合致する場合は脆弱性の恐れを指摘する、脆弱性検知手順を実施する。
前記脆弱性検知手順の処理は次のようなものである。まず、手順901で取得した、呼び出される関数の名前をキーとして図26の脆弱性DB205の関数名欄を検索する。一致する関数が見つからなければ脆弱性検知手順を終了する。見つかれば、その行の脆弱性仮引数リストを読込む。次に手順905〜907と同様の処理を行い、脆弱性仮引数リスト内の各仮引数参照データに対応する実引数について、その参照データを変数テーブル207から読込む。この参照データに外部入力データを表す'IN'、または擬似外部入力データを表す'PIN'が含まれていれば、脆弱性を生じる恐れがあるとして脆弱性検査結果209として出力する。
図4のソースコードについて前記脆弱性検知手順を実施する場合を説明する。
図4のソースコードの3行目の関数sprintfの関数呼出しについて前記脆弱性検知手順を実施する直前の変数テーブル207の状態は図23、動的仮引数間遷移リスト206の状態は図22である。まず、関数名sprintfで図26の脆弱性DB205の関数名欄を検索し、その一致する行の脆弱仮引数リスト'[*2, *3...]'を読込む。同リスト内の仮引数参照データ'*2'に対応する実引数は"input=%s"なので、この参照データは存在しない。同リスト内の次の仮引数参照データ'*3...'に対応する実引数は変数strinで、前記仮引数参照データの間接参照の深さが1であることから、前記変数strinの変数参照データ集合を図23の変数テーブル207から取得すると'(*2, PIN)'である。この変数参照データ集合には'PIN'が含まれているので、前記関数sprintfの関数呼出しは脆弱性を生じる可能性があり、この旨を脆弱性検査結果209として出力する。
図4のソースコードの8行目の関数getsの関数呼び出しについて同様に前記脆弱性検知手順を実施する直前の変数テーブル207の状態は図14、動的仮引数間遷移リスト206の状態は図22である。関数getsについて脆弱性DB205に登録されている脆弱仮引数リストを読込むと'[ ]'を得る。同リストが空の場合、前記関数呼出しがいつでも脆弱であることを意味する。したがって、前記関数getの関数呼出しは脆弱性を生じる可能性があり、この旨を脆弱性検査結果209として出力する。
図4のソースコードの13行目の関数putsの関数呼び出しについて同様に前記脆弱性検知手順を実施する直前の変数テーブル207の状態は図25、動的仮引数間遷移リスト206の状態は図22である。関数putsについて脆弱性DB205に登録されている脆弱性仮引数リストを読込むと'[*1]'を得る。この参照データに対応する実引数は変数outで、前記参照データの間接参照の深さが1である。これらに該当する変数参照データ集合を図25の変数テーブル207から読込むと'(*1, PIN)'を得る。この変数参照データ集合には'PIN'が含まれているので、前記関数putsの関数呼出しは脆弱性を生じる可能性があり、この旨を脆弱性検査結果209として出力する。
以上で、本実施形態における基本的な手順の説明を全て終える。
次に、検査対象ソースコード208に条件分岐やループが存在した場合の処理を以下で説明する。
if文やswitch文による条件分岐では、条件式の評価結果により、分岐処理A、分岐処理B、分岐処理C、…のいずれか1つが実行される。if文により条件分岐する検査対象ソースコード208の例を図27に、このソースコードから構文解析手段201により生成された解析木210の例を図28に示す。これらの図を用いてif文の場合の処理を説明する。
脆弱性検出手段202は、手順309において図27の検査対象ソースコード208から構築された図28の解析木210を所定の順序でたどり条件分岐のノードに到達したら、この条件分岐ノードを頂点とする部分解析木について以下の処理を行う。まず前記部分解析木を所定の順序でたどり、1つめの式ノード(図28の4行目)について手順309を適用する。続いて、この時点での動的仮引数間遷移DB206、変数テーブル207の複製を作成する。そして、図28の解析木210を所定の順序でたどり、次に現れる2つめの式ノード(図28の5行目)を頂点とする解析木210について、手順308〜310を適用して前記複製元の動的仮引数間遷移DB206、変数テーブル207を更新する。図28の解析木210を所定の順序でたどりELSEノードに到達したら、さらにその次に現れる3つめの式ノード(図28の7行目)を頂点とする解析木210について、手順308〜310を適用して前記複製された動的仮引数間遷移DB206及び変数テーブル207を更新する。図28の解析木210を所定の順序でたどり、前期3つめの式ノードを頂点とする解析木210をたどり終えたら、前記複製元の動的仮引数間遷移DB206及び変数テーブル207と、前記複製された動的仮引数間遷移DB206及び変数テーブル207とを、それぞれマージする。動的仮引数間遷移DB206のマージでは、同一の関数名を持つ行ごとに、仮引数間遷移リスト同士、外部入力仮引数集合同士を重複する要素を除いて連結する。変数テーブル207のマージでは、同一の変数識別番号を持つ行ごとに、変数参照データ集合リスト内の同一の間接参照の深さである変数参照データ集合同士を重複する要素を除いて連結する。
switch文の場合、脆弱性検出手段202は、その条件式に対して手順309を適用した後、それぞれの分岐処理毎に動的仮引数間遷移DB206、変数テーブル207の複製を用意して手順309を適用して更新処理を行い、それらの結果をマージして新たな動的仮引数間遷移DB206、変数テーブル207とする。
for文、while文、do-while文によるループの場合、脆弱性検出手段202はその条件式(for文の場合は初期化と更新の式も含む)及びループ本体に対し一度だけ手順309を適用し、動的仮引数間遷移DB206、変数テーブル207を更新する。
上記第1の実施形態では脆弱性DB205に登録された関数を直接呼び出す箇所のみ脆弱性として検出しているが、そのような箇所を含むユーザ定義関数を呼び出す箇所も脆弱性として指摘することも上記第1の実施形態の手順を一部修正することで可能である。
その一つの方法は、上記のようなユーザ定義関数と外部入力データを受け取ることのある仮引数を組にして記憶し、その使用箇所を手順314と同様の処理で検出するというものである。
また別の方法は、ユーザ定義関数のそれぞれの仮引数について、そのユーザ定義関数の呼出し箇所における実引数の参照データの種類を、外部入力データ'IN'、擬似外部入力データ'PIN'、その他に分類して動的仮引数間遷移DB206に記憶しておく。手順304において同DBの更新がなくなったときに、その他に分類された参照データを受け取ることのない仮引数を持ち、かつその仮引数で受け取った外部入力データの使用により脆弱性として検出される箇所を内部に持つユーザ定義関数について、その関数名と仮引数を組にして記憶し、その使用箇所を手順314と同様の処理で検出するというものである。
以上で、第1の実施形態の説明を終える。
次に第2の実施形態について説明する。第2の実施形態のソースコード脆弱性検査装置の構成は、第1の実施の形態で説明した図1と同じであるので、構成の説明は省略する。ただし、各変数や仮引数の保持する値の表記方法などは第1の実施形態とは異なる。
図29は、第2の実施形態のソースコード脆弱性検査装置の備える機能構成図である。本実施形態のソースコード脆弱性検査装置は、ソースコード検査手段201、固定関数遷移DB2902、脆弱遷移先DB2903、不定関数遷移DB2904、及び変数DB2905を備える。ソースコード検査手段201は、ソースコードの構文を解析する構文解析手段2911、及び脆弱な箇所を検出する脆弱性検出手段2912を備える。
図30は、あらかじめ登録された脆弱遷移先DB2903の例である。1列目は脆弱遷移先、2列目は脆弱回避値である。
図31は、固定関数遷移DB2902の例である。固定関数遷移DB2902は、標準ライブラリ関数などのデータ遷移をあらかじめ登録したデータベースである。1列目は関数名、2列目はどの値がどこに遷移するかを示すデータ遷移のリストである。データ遷移は、矢印'→'を用いて表記し、'→'の左を遷移元、'→'の右を遷移先とする。遷移元には、後述する変数DB2905に正の整数で登録される第何引数かを表す引数番号、外部から入力されたデータに由来するデータを表すIN、脆弱性を回避する処理を経たことを示す脆弱性回避値のいずれか、もしくはこれらの組み合わせが設定される。遷移先には、引数番号、グローバル変数の変数番号、戻り値を表すR、脆弱性を生じる可能性のある遷移先である脆弱遷移先のいずれかが設定される。
図32は、不定関数遷移DB2904の例である。不定関数遷移DB2904には、プログラマが定義した関数についてのデータ遷移情報を、ソースコード解析中に登録する。これは、固定関数遷移DB2902と同様の構造であるが、新たに解析を終了したかどうかを表すための解析済みフラグの項目を追加している。解析済みフラグは0か1の値をとり、解析済みフラグが0である関数は、後述の手順3406から3412までの解析が終了していないことを表し、一方1である関数は前記解析が終了していることを表す。初期値は0とする。以下、前記解析が終了していない関数の状態を未解析であると呼ぶ。不定関数遷移DB2904で遷移先に設定され得る値には、固定関数遷移DB2902の場合に設定され得る値に加え、後述する変数DB2905に負の整数で登録されるグローバル変数の変数番号がある。遷移値には、手順3401終了時、初期値DEFが与えられている。この値は、後述の手順3406または手順3408にて更新される。
図33は、変数DB2905の例である。1列目は変数DB2905に登録された変数の識別番号である。この変数番号は、グローバル変数の場合、負の整数値で−1、−2と降順に付ける。仮引数の場合、引数番号と一致する正の整数値を付ける。ローカル変数の場合、既に登録されている仮引数の変数番号に続くように昇順に付ける。正の整数値が一つも登録されていない場合、1から順に昇順に付ける。2列目は変数の種別を表し、仮引数を登録する場合は'A'、ローカル変数なら'L'、グローバル変数なら'G'を格納する。3列目は変数名である。4列目は変数の保持する値であり、初期値は変数番号と同一の値とする。値が定数の場合は、Cとする。
図34は、本実施形態のソースコード脆弱性検査装置の処理手順である。以下の処理で、関数定義、代入、及び関数呼び出しなどのソースコード中の構文の解析は、構文解析手段2911が行う。
ソースコード検査プログラムが起動されると、与えられたソースコードを全てたどり、見つかったプログラマ定義関数を不定関数遷移DB2904に、グローバル変数を変数DB2905に、それぞれ登録する。グローバル変数の変数番号は、負の整数値で−1から降順に付ける(手順3401)。
次に、ソースコードの先頭を探索開始位置にする(手順3402)。複数のファイルで構成されるソースコードを検査する場合、検査するファイルの順序を決めておき、その先頭を探索開始位置にする。次に、ソースコード中から、未解析である関数定義を探索する(手順3403)。未解析の関数が無い場合は後述する手順3413に移る(手順3403)。該当関数が見つかれば、次に、該当関数の定義の中で、未解析の関数呼び出しが行われていないかを探索する(手順3404)。未解析の関数呼び出しが行われている場合、探索開始位置をソースコード中の次の関数定義位置に移し(手順3405)、手順3403に戻る。未解析の関数呼び出しが行われていない場合、本関数を処理対象関数とし、解析を開始する(手順3406)。
まず、対象関数の仮引数があればそれを変数DB2905に登録する(手順3407)。このとき、仮引数の変数番号は、その引数番号と一致するように登録する。対象関数内で定義されたローカル変数が見つかれば、それらを変数DB2905に登録する(手順3408)。変数番号は、正の整数で昇順に付ける。
さらに、関数呼び出し箇所があれば、関数名で固定関数遷移DB2902および不定関数遷移DB2904を探索し、該当関数の遷移値を取得する。遷移値がDEFである場合、手順3410へ進む。そうでない場合、次に記す処理を行う。呼び出された関数が引数を持つ関数である場合、実引数の値を取得する。関数呼び出しに伴う遷移の遷移元が正の整数(引数番号)である場合、その遷移元を引数番号に相当する実引数値に修正後、以下の処理を行う。遷移元が負の整数(グローバル変数の変数番号)である場合、変数DB2905から該当する変数値を参照し、その値に修正した後、以下の処理を行う。それ以外の場合、何もせず以下の処理を行う。
データ遷移の遷移先の値に応じて次の処理を行う(手順3409)。まず、遷移先が変数番号のデータ遷移の箇所があれば、変数DB2905の該当する変数値を更新する。遷移先が脆弱遷移先DB2903の脆弱遷移先のいずれかに合致し、遷移元が変数種別'A'または'G'の変数番号のデータ遷移があれば、不定関数遷移DB2904に追加する。遷移先が脆弱遷移先DB2903の脆弱遷移先のいずれかに合致し、遷移元にINを含み、脆弱遷移先に対応する脆弱性回避値を含まないデータ遷移があれば、不定関数遷移DB2904に追加すると共に、ソース中の該当箇所への警告を検査結果として出力する。
なお、代入文についても、右辺→左辺のデータ遷移として、関数呼び出しと同様に処理する。
対象関数の処理を終えるまで、手順3408、3409を繰り返す。対象関数の処理を終えたら、解析済みフラグを1に設定し、手順3411に移る(手順3410)。
変数DB2905の種別欄で種別が'A'(仮引数)または'G'(グローバル変数)となっている行を選び、その値を取得する。値がINまたは、それ自身以外の変数番号でかつ種別が'A'または'G'である場合、それぞれINまたは変数番号を遷移元とし、該当行の変数番号を遷移先とする遷移を不定関数遷移DB2904に登録する(手順3411)。
変数DB2905から仮引数とローカル変数についての登録データを削除する。グローバル変数の値を初期化する(手順3412)。対象関数についての処理を終え、手順3403に戻る。
手順3413では不定関数遷移DB2904に、前回解析時と比較して、グローバル変数を遷移先とする新たな遷移値の登録があるかどうかを調べる。該当する遷移値の登録がある場合、不定関数遷移DB2904の解析済みフラグの値をすべて0に初期化し、手順3403へ戻る。一方、無い場合は処理を終了する。
後述する検査対象ソースコードにポインタ変数の遷移がないため、記述していないが、変数DB2905に参照の深さと参照値を加えることと、固定関数遷移DB2902および不定関数遷移DB2904の遷移値に設定できるものの一つにこの参照値を加えることと、手順3409で遷移元がポインタ変数の変数番号である場合、変数リストから、その値を取得し、遷移元を修正すること、を行うことでポインタ変数の遷移に対応できる。
以上で図34の説明を終える。
図46は、本実施形態のソースコード脆弱性検査装置を説明するための検査対象ソースコードである。C言語で記述されており、説明の便宜上一番左に行番号を記述している。sanitizeOs関数の定義を省いているが、含めても以下の結果は変わらない。
まず、従来のパターンマッチング法を、図46のソースコードに適用した場合について説明する。パターンマッチング法による検査では、関数に渡されるデータが外部由来かどうかを判断することなく、あらかじめ登録された脆弱性を生じる可能性のあるライブラリ関数使用箇所のすべてを検出するため、22行目のOSコマンドインジェクションを生じる可能性のあるライブラリ関数であるsystem関数に対し、警告が出力される。しかし、system関数は直接main関数から呼ばれることはなく、call_do_system関数を通して呼ばれており、system関数が実行される5行目、8行目、12行目の3箇所のうち、8行目の一箇所だけが実際に脆弱である。5行目は、扱うデータが外部由来ではない。また、12行目は、扱うデータが事前に適切な脆弱性回避処理がなされたデータである。プログラマは、パターンマッチング法を用いた脆弱性検査を行った後、このように警告箇所が実際に脆弱であるかを、自ら目視で判断する必要がある。
また、プログラマが脆弱性の警告への対処として行う脆弱性回避処理は、目視で実際に脆弱であると判断された箇所で行う必要がある。もし、警告された22行目の直前でその扱うデータに対し脆弱性回避処理を施すと、8行目で脆弱性回避処理を行う必要のないデータに対し脆弱性回避処理が行われ、12行目で二重に脆弱性回避処理が行われることになり、この2箇所で想定外の動作が生じる可能性がある。
次に図46のソースコードに対して、34の処理を適用した場合の処理を説明する。図32は、手順3401終了時の不定関数遷移DB2904の例を示し、検査対象ソースコードに定義されている関数が登録されている。この検査対象ソースコードにはグローバル変数は定義されていない。
手順3401,3402の後、ソースコードの先頭から未解析の関数を探索し、main関数が検出される(手順3403)。main関数の定義内で、未解析の関数呼び出しの有無の検査を行う(手順3404)。5行目でcall_do_system関数が呼ばれており、不定関数遷移DB2904より解析済みフラグが0であることが分かる(手順3404)。すなわち未解決の関数呼び出しが行われているので、探索開始位置を次の関数定義に移す(手順3405)。
次に、do_gets関数が、未解析で、定義内で未解析の関数呼び出しが行われていないことが分かる(手順3403および3404)。よってdo_getsを解析対象の関数(対象関数)とする(手順3406)。以降、手順3406にて対象関数とされる関数の順番は、do_gets、do_system、call_do_system、mainである。
まず対象関数do_getsに対し、仮引数とローカル変数を変数DB2905に登録する(手順3407、3408)。do_getsについて手順3408終了時の変数DB2905が、図33である。17行目の関数getsの呼び出しによるデータ遷移の処理を行う(手順3409)。getsの遷移値を、固定関数遷移DB2902および不定関数遷移DB2904より検索し取り出す。すると、IN→1の遷移が取得される。この遷移先は、変数番号であるので、変数DB2905の該当変数の変数値を更新する。以上で対象関数do_getsの処理を終える(手順3410)。手順3410終了時の変数DB2905が、図35である。
変数DB2905のうち、種別が'A'の変数値がINであるので、これに相当する遷移IN→1を、不定関数遷移DB2904に登録する(手順3411)。手順3411終了時の不定関数遷移DB2904が、図36である。
次にdo_systemを対象関数とした処理を説明する。上記と同様にして、仮引数とローカル変数を変数DB2905に登録する(手順3407、3408)。手順3408終了時の変数DB2905が、図37である。22行目の関数systemの呼び出しによるデータ遷移の処理を行う(手順3409)。systemの遷移値を、固定関数遷移DB2902および不定関数遷移DB2904より検索し取り出す。すると、1→OSCOMMの遷移が取得される。第一引数の実引数値は1であり、遷移元をこの値に修正する。遷移先OSCOMMは、脆弱遷移先DB2903の脆弱遷移先に登録されている。遷移元は変数種別'A'の変数番号であるので、不定関数遷移DB2904に遷移を登録する(手順3409)。以上で対象関数do_systemの処理を終える(手順3410)。手順3410終了時の不定関数遷移DB2904が、図38である。
次にcall_do_systemを対象関数とした処理を説明する。上記と同様にして、仮引数とローカル変数を変数DB2905に登録する(手順3407、3408)。手順3408終了時の変数DB2905が、図39である。27行目の関数do_systemの呼び出しによるデータ遷移の処理を行う(手順3409)。do_systemの遷移値を、固定関数遷移DB2902および不定関数遷移DB2904より検索し取り出す。すると、1→OSCOMMの遷移が取得される。第一引数の実引数値は1であり、遷移元をこの値に修正する。この遷移先OSCOMMは、脆弱遷移先DB2903の脆弱遷移先に登録されている。遷移元は変数種別'A'の変数番号であるので、不定関数遷移DB2904に遷移を登録する(手順3409)。以上で対象関数call_do_systemの処理を終える(手順3410)。手順3410終了時の不定関数遷移DB2904が、図40である。
次にmainを対象関数とした処理を説明する。上記と同様にして、仮引数とローカル変数を変数DB2905に登録する(手順3407、3408)。手順3408終了時の変数DB2905が、図41である。5行目の関数call_do_systemの呼び出しによるデータ遷移の処理を行う(手順3409)。すなわち、まずdo_systemの遷移値を、固定関数遷移DB2902および不定関数遷移DB2904より検索し取り出す。すると、1→OSCOMMの遷移が取得される。第一引数の実引数値は定数を表すCであり、遷移元をこの値に修正する。この遷移先OSCOMMは、脆弱遷移先DB2903の脆弱遷移先に登録されている。しかし、遷移元が定数値Cであるので、何も行わない(手順3409)。
次に7行目の関数get_inputの呼び出しによるデータ遷移の処理を行う(手順3409)。17行目と同様に処理する。手順3409終了時の変数DB2905が、図42である。
次に8行目の関数call_do_systemの呼び出しによるデータ遷移の処理を行う(手順3409)。同様に1→OSCOMMの遷移が取得される。第一引数の実引数値はINであり、遷移元をこの値に修正する。この遷移先OSCOMMは、脆弱遷移先DB2903の脆弱遷移先に登録されている。遷移元がINであるので、不定関数遷移DB2904に登録するとともに、この箇所が脆弱であるという警告を検査結果として出力する。
次に10行目の関数strlcpyの呼び出しによるデータ遷移の処理を行う(手順3409)。同様に2→1の遷移が取得される。第二引数の実引数値はINであり、遷移元をこの値に修正する。この遷移先は、変数番号であるので、変数DB2905の該当変数の変数値を更新する。手順3409終了時の変数DB2905が、図43である。
次に11行目の関数sanitizeOsの呼び出しによるデータ遷移の処理を行う(手順3409)。同様に1,SAFE_OS→1の遷移が取得される。第一引数の実引数値はINであり、遷移元の1をこの値に修正する。この遷移先は、変数番号であるので、変数DB2905の該当変数の変数値を更新する。手順3409終了時の変数DB2905が、図44である。
次に12行目の関数call_do_systemの呼び出しによるデータ遷移の処理を行う(手順3409)。同様に1→OSCOMMの遷移が取得される。第一引数の実引数値はIN, SAFE_OSであり、遷移元をこの値に修正する。この遷移先OSCOMMは、脆弱遷移先DB2903の脆弱遷移先に登録されている。遷移元にINを含むが、脆弱遷移先DB2903の脆弱回避値SAFE_OSも同時に含むので、何も行わない。
以上で対象関数mainの処理を終える(手順3410)。手順3410終了時の不定関数遷移DB2904が、図45である。
未解析の関数探索(手順3403)にて該当関数が見つからないので手順3413に移る。不定関数遷移DB2904に登録されている遷移値で、グローバル変数の変数番号を遷移先とする遷移の登録はないため、検査を終了する。
以上のように、本ソースコード脆弱性検査装置を、図46のソースコードに適用した場合、正確に8行目が脆弱であるという警告を出す。よってプログラマは、8行目の直前でその扱うデータに対し脆弱性回避処理を施せばいいことが分かる。このように従来のパターンマッチング法に比べ、誤った検出がなされず、プログラマが脆弱性回避処理を行うべき箇所を容易に特定できる。また、ソースコードに検査のための注釈を書き込む必要がない。
また本実施形態では記述していないが、変数に対し二重に脆弱性回避処理を行ってしまう場合に、警告を出すこともできる。手順3409にて変数DB2905の変数値を更新する際に、新しく更新された値に、脆弱遷移先DB2903の脆弱回避値の同一の値が二つ以上含まれる場合、その箇所に警告を出すようにすればよい。
また、遷移先が変数DB2905の種別'A'もしくは'G'の変数の変数番号である場合、図34の手順3409で一度変数DB2905にその遷移を反映した後、手順3411にて遷移を読み取り不定関数遷移DBに登録するのではなく、手順3411を無くし、直接不定関数遷移DBに遷移を登録してもよい。
以上で第2の実施形態の説明を終える。
第1実施形態のソースコード脆弱性検査装置の構成の概要図 第1実施形態のソースコード脆弱性検査装置の機能の概要図 構文解析手段と脆弱性検出手段での処理手順を示す図 検査対象ソースコードの例を示す図 解析木の例を示す図 仮引数間遷移DBの例を示す図 動的仮引数間遷移DBの例(手順303終了時)を示す図 変数テーブルの例(関数format_stringについて手順308終了時)を示す図 関数呼出し箇所を解析時の変数テーブル更新処理手順を示す図 変数テーブルの例(関数format_stringについて手順309終了時)を示す図 変数テーブルの例(ポインタの代入'a=b'の処理前)を示す図 変数テーブルの例(ポインタの代入'a=b'の処理後)を示す図 動的仮引数間遷移DBの例(関数format_stringについて手順311終了時)を示す図 変数テーブルの例(関数get_inputについて手順308終了時)を示す図 変数テーブルの例(関数get_inputについて手順309終了時)を示す図 動的仮引数間遷移DBの例(関数get_inputについて手順311終了時)を示す図 変数テーブルの例(関数put_inputについて手順308終了時)を示す図 変数テーブルの例(関数mainの18行目について手順308終了時)を示す図 変数テーブルの例(関数mainの19行目について手順309終了時)を示す図 変数テーブルの例(関数mainの20行目について手順309終了時)を示す図 動的仮引数間遷移DBの例(関数mainの20行目について手順309終了時)を示す図 動的仮引数間遷移DBの例(関数mainの21行目について手順309終了時)を示す図 変数テーブルの例(関数format_stringについて2回目の手順308終了時)を示す図 変数テーブルの例(関数format_stringについて2回目の手順309終了時)を示す図 変数テーブルの例(関数put_inputについて2回目の手順308終了時)を示す図 脆弱性DBの例を示す図 if文を含む検査対象ソースコードの例を示す図 解析木の例を示す図 第2実施形態のソースコード脆弱性検査装置の機能の概要図 脆弱遷移先DBの例を示す図 固定関数遷移DBの例を示す図 不定関数遷移DBの例(手順3401終了時)を示す図 変数DBの例(関数do_getsについて手順3408終了時)を示す図 本実施形態のソースコード脆弱性検査の動作を示すフローチャート図 変数DBの例(関数do_getsについて手順3410終了時)を示す図 不定関数遷移DBの例(関数do_getsについて手順3411終了時)を示す図 変数DBの例(関数do_systemについて手順3408終了時)を示す図 不定関数遷移DBの例(関数do_systemについて手順3410終了時)を示す図 変数DBの例(関数call_do_systemについて手順3408終了時)を示す図 不定関数遷移DBの例(関数call_do_systemについて手順3411終了時)を示す図 変数DBの例(関数mainについて手順3408終了時)を示す図 変数DBの例(関数mainの7行目について手順3409終了時)を示す図 変数DBの例(関数mainの10行目について手順3409終了時)を示す図 変数DBの例(関数mainの11行目について手順3409終了時)を示す図 不定関数遷移DBの例(関数mainについて手順3411終了時)を示す図 検査対象ソースコードの具体例を表す図
符号の説明
101…ソースコード脆弱性検査装置の本体(コンピュータ)、102…CPU、103…記憶装置、104…メモリ、105…キーボード、106…CRT、107…外部記憶装置、108…バス。

Claims (7)

  1. 検査対象のソースコードの脆弱性を検査するソースコード脆弱性検査装置であって、
    前記検査対象のソースコードを解析して、外部入力がどのように遷移するかを求める手段と、
    外部入力をパラメータとして使用すると脆弱な関数を登録した脆弱性データベースと、
    前記検査対象のソースコードにおける外部入力の遷移を追跡し、前記脆弱性データベースの登録内容に合致する箇所を、脆弱性を有する箇所として警告する手段と
    を備えることを特徴とするソースコード脆弱性検査装置。
  2. 検査対象のソースコードの脆弱性を検査するソースコード脆弱性検査装置であって、
    検査対象ソースコードの構文の解析を行い、該検査対象のソースコードの解析木を構築する構文解析手段と、
    前記検査対象ソースコード内で使用されているライブラリに含まれる関数について、内部での処理による仮引数間のデータ遷移を記述した仮引数間遷移データベースと、
    前記検査対象ソースコード内で定義されているユーザ定義関数について、内部での処理による仮引数間のデータ遷移と、該検査対象ソースコードをコンパイルして作成されたプログラムの実行時に該プログラムの外部から与えられた入力データを受け取ることのある仮引数の位置とを、組にして登録するための動的仮引数間遷移データベースと、
    前記検査対象ソースコード内で使用されている変数の保持する値の種類を、外部から与えられた入力データであるか否かを区別して、記録するための変数テーブルと、
    前記解析木を辿りながら、ユーザ定義関数があれば、そのユーザ定義関数を分析対象である対象関数とし、その部分解析木を探索して仮引数とローカル変数の定義を前記変数テーブルに登録し、変数間のデータ遷移や変数の外部出力の箇所があれば、前記仮引数間遷移データベースと前記動的仮引数間遷移データベースと前記変数テーブルとを参照して更新し、前記対象関数の部分解析木の探索が終了したら、その対象関数について変数テーブルの内容に基づき前記動的仮引数間遷移データベースの内容を更新し、このような処理を繰り返すことにより、解析木を辿って変数間のデータ遷移を追跡できるようにする手段と、
    外部入力をパラメータとして使用すると脆弱な関数を登録した脆弱性データベースと、
    前記脆弱性データベースを読み込み、前記変数間のデータ遷移が該脆弱性データベースの登録内容に合致する箇所を、脆弱性を有する箇所として警告する手段と
    を備えることを特徴とするソースコード脆弱性検査装置。
  3. 検査対象のソースコードの脆弱性を検査するソースコード脆弱性検査装置であって、
    検査対象ソースコードの記述に用いたプログラミング言語の構文解析ルールに従って該検査対象ソースコードを構文解析して解析木を構築する構文解析手段と、
    該検査対象ソースコード内で使用されているライブラリに含まれる関数について、内部での処理による仮引数間のデータ遷移を記述した仮引数間遷移データベースと、
    該検査対象ソースコード内で定義されているユーザ定義関数について、内部での処理による仮引数間のデータ遷移と、該検査対象ソースコードをコンパイルして作成されたプログラムの実行時に該プログラムの外部から与えられた入力データを受け取ることのある仮引数の位置とを、組にして登録する動的仮引数間遷移データベースと、
    該検査対象ソースコード内で使用されている変数の保持する値の種類を、該プログラムの外部から与えられた入力データであるか否かを区別して、記録する変数テーブルと、
    プログラムの実行時に該プログラムの外部から与えられた入力データをある特定の仮引数で受け取って処理すると脆弱性を生じる可能性のある該ライブラリ内の関数と、該特定の仮引数の位置とを、組にして登録した脆弱性データベースと、
    前記解析木のルートノードから該解析木の全体を所定の順序で繰り返し辿りながら、前記動的仮引数間遷移データベースと変数テーブルとを更新し、前記動的仮引数間遷移データベースに新たな更新がなくなった後に、再び該解析木のルートノードから該解析木の全体を所定の順序でたどりながら、前記仮引数間遷移データベースと前記動的仮引数間遷移データベースを参照して前記変数テーブルを更新し、さらに、前記脆弱性データベースを参照して、該脆弱性データベースに登録された関数が前記検査対象ソースコード内で呼び出される箇所において、該登録された関数と組の該特定の引数の位置で実引数として指定された変数について該変数テーブルに登録された該変数の保持する値の種類が該プログラムの外部からの入力データであれば、該箇所を脆弱性として脆弱性検査結果に出力する脆弱性検出手段と
    を備え、
    前記脆弱性検出手段は、前記解析木を所定の順序でたどって関数定義ノードに到達した時、該関数定義ノードの表すユーザ定義関数が前記動的仮引数間遷移データベースに登録されていなければ該ユーザ定義関数を登録し、
    続いて該解析木の該関数定義ノードを頂点とする部分解析木を所定の順序でたどり、仮引数定義ノードに到達すれば、該仮引数ノードの表す該仮引数を前記変数テーブルに登録し、
    また該ユーザ定義関数について該動的仮引数間遷移データベースに該仮引数が前記プログラムの外部からの入力データを受け取ることのある仮引数として登録されていれば、該変数テーブルに該仮引数の保持する値の種類として外部入力データを登録し、
    また変数定義ノードに到達すれば、該変数定義ノードの表す変数を該変数テーブルに登録し、
    また関数呼出しノードに到達すれば、該関数呼出しノードの表す関数について該仮引数間遷移DBまたは該動的仮引数間遷移データベースに登録された仮引数間のデータ遷移を参照し、該仮引数間のデータ遷移を構成する、遷移元仮引数の値の種類、および遷移先仮引数の値の種類を取得し、
    該遷移元仮引数の値の種類が該関数呼出しノードの表す関数の第1の仮引数であれば、該部分解析木を所定の順序でたどって該第1の仮引数の位置に当たる第1の実引数ノードに到達し、該第1の実引数ノードの表す第1の変数について前記変数テーブルに記録された変数の保持する値の種類を新たな遷移先の値の種類として取得し、
    該遷移元仮引数の値の種類が外部入力データであれば新たな遷移先の値の種類を外部入力データとし、
    該遷移先仮引数の値の種類が該関数呼出しノードの表す関数の第2の仮引数であれば、該部分解析木を所定の順序でたどって該第2の仮引数の位置に当たる第2の実引数ノードに到達し、該第2の実引数ノードの表す第2の変数について前記変数テーブルに記録された変数の保持する値の種類として、該新たな遷移先の値の種類を登録し、
    さらに該新たな遷移先の値の種類に外部入力データを含み、かつ該関数呼出しノードの表す関数が前記動的仮引数遷移データベースに登録されていれば、該関数呼出しノードの表す関数について該第1の仮引数が該プログラムの外部から入力データを受け取ることを該動的仮引数間遷移データベースに登録し、
    さらに該新たな遷移先の値の種類に外部入力データを含み、かつ該関数呼出しノードの表す関数と該第1の仮引数の位置との組が前記脆弱性データベースに登録されていれば、前記検査対象ソースコード内での該第1の変数の記述位置を脆弱性が生じる可能性のある箇所として出力し、
    そして該部分解析木を所定の順序でたどり終えたら、該仮引数ごとに、該変数テーブルに記録された該仮引数の保持する値の種類を遷移元仮引数の保持する値の種類、該仮引数自身を遷移先仮引数の保持する値の種類とする新たな仮引数間のデータ遷移を作成し、該動的仮引数間遷移データベースの該ユーザ定義関数についての仮引数間のデータ遷移を該新たな引数間のデータ遷移で上書きする
    ことを特徴とするソースコード脆弱性検査装置。
  4. 請求項3に記載のソースコード脆弱性検査装置において、
    前記脆弱性検出手段は、前記変数テーブルに記録される変数の保持する値の種類を、該変数について可能な間接参照の深さ毎に記録することを特徴とするソースコード脆弱性検査装置。
  5. 請求項3または4に記載のソースコード脆弱性検査装置において、
    前記脆弱性検出手段は、前記解析木を所定の順序でたどり、変数の定義ノードに到達したときに該変数の定義ノードの表す変数および該解析木内での深さを該変数テーブルに登録し、
    さらに該解析木を所定の順序でたどって到達したノードの該解析木内での深さが該変数の定義ノードの深さより浅くなったときに該変数についての登録データを該変数テーブルから削除する
    ことを特徴とするソースコード脆弱性検査装置。
  6. 検査対象のソースコードの脆弱性を検査するソースコード脆弱性検査装置であって、
    検査対象ソースコードの構文の解析を行う構文解析手段と、
    ライブラリ関数に伴うデータ遷移をあらかじめ登録しておく固定関数遷移データベースと、
    脆弱性の生じる可能性のある遷移先と、それを回避するための処理を経たことを表す値とを、あらかじめ登録しておく脆弱遷移先データベースと、
    ソースコード内で定義される変数の種類と値とを記録する変数データベースと、
    前記検査対象ソースコード内で定義した関数に伴うデータ遷移を記録する不定関数遷移データベースと、
    前記検査対象ソースコードを辿りながら、前記固定関数遷移データベースと脆弱遷移先データベースとを参照し、前記変数データベースに前記検査対象ソースコード内で定義される変数の種類と値を記録し、前記不定関数遷移データベースを更新し、これによりデータ遷移を追跡できるようにし、脆弱性を回避する処理を受けていない外部入力値が、脆弱性の生じる可能性のある遷移先に遷移する、脆弱なデータ遷移が行われる関数呼び出し箇所を脆弱性として検出する脆弱性検出手段と
    を備えることを特徴とするソースコード脆弱性検査装置。
  7. 請求項6に記載のソースコード脆弱性検査装置において、
    前記検査対象ソースコード中で定義された関数のうち、その内部で呼ばれる関数が、ライブラリ関数または既に処理を終えデータ遷移を登録したプログラマ定義関数のみである関数定義から処理するように、処理対象関数を決める手段を備えることを特徴とするソースコード脆弱性検査装置。
JP2005237124A 2005-08-18 2005-08-18 ソースコード脆弱性検査装置 Expired - Fee Related JP4693044B2 (ja)

Priority Applications (1)

Application Number Priority Date Filing Date Title
JP2005237124A JP4693044B2 (ja) 2005-08-18 2005-08-18 ソースコード脆弱性検査装置

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
JP2005237124A JP4693044B2 (ja) 2005-08-18 2005-08-18 ソースコード脆弱性検査装置

Publications (2)

Publication Number Publication Date
JP2007052625A true JP2007052625A (ja) 2007-03-01
JP4693044B2 JP4693044B2 (ja) 2011-06-01

Family

ID=37917035

Family Applications (1)

Application Number Title Priority Date Filing Date
JP2005237124A Expired - Fee Related JP4693044B2 (ja) 2005-08-18 2005-08-18 ソースコード脆弱性検査装置

Country Status (1)

Country Link
JP (1) JP4693044B2 (ja)

Cited By (16)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP2008299723A (ja) * 2007-06-01 2008-12-11 Hitachi Systems & Services Ltd プログラム検証方法、プログラム検証装置
WO2011122724A1 (ko) * 2010-03-29 2011-10-06 주식회사 소프트 포 소프트 아밥 소스코드의 코드 검사를 수행하는 코드검사 수행시스템
EP2398256A2 (en) 2010-06-18 2011-12-21 Funai Electric Co., Ltd. Television set and speaker system
JP2012059221A (ja) * 2010-09-13 2012-03-22 Toshiba Corp 情報処理装置、情報処理プログラム
US8365280B2 (en) 2009-06-30 2013-01-29 International Business Machines Corporation System, method, and program for determining validity of string
US8468605B2 (en) 2009-11-30 2013-06-18 International Business Machines Corporation Identifying security vulnerability in computer software
US8528095B2 (en) 2010-06-28 2013-09-03 International Business Machines Corporation Injection context based static analysis of computer software applications
US8584246B2 (en) 2009-10-13 2013-11-12 International Business Machines Corporation Eliminating false reports of security vulnerabilities when testing computer software
WO2014021190A1 (ja) 2012-08-01 2014-02-06 三菱電機株式会社 プログラム実行装置及びプログラム解析装置
US9959191B2 (en) 2012-11-23 2018-05-01 Samsung Electronics Co., Ltd. Dynamic library profiling method and dynamic library profiling system
CN110162972A (zh) * 2019-05-06 2019-08-23 武汉大学 一种基于语句联合编码深度神经网络的uaf漏洞检测方法
KR102026959B1 (ko) * 2019-04-19 2019-09-30 한화시스템(주) 보안 시스템 및 그 동작 방법
JP2019168753A (ja) * 2018-03-22 2019-10-03 三菱電機株式会社 ソースコード解析装置およびソースコード解析プログラム
KR102067733B1 (ko) * 2019-05-15 2020-01-17 세종대학교산학협력단 포맷 스트링 취약점 검출 방법 및 이를 수행하기 위한 장치
WO2020261430A1 (ja) * 2019-06-26 2020-12-30 三菱電機株式会社 情報処理装置、情報処理方法及び情報処理プログラム
WO2023238239A1 (ja) * 2022-06-07 2023-12-14 日本電信電話株式会社 修正装置、修正方法及び修正プログラム

Citations (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP2004171064A (ja) * 2002-11-15 2004-06-17 Mitsubishi Research Institute Inc バッファオーバーフロー静的解析方法およびプログラム
WO2004095176A2 (en) * 2003-04-18 2004-11-04 Ounce Labs, Inc. Detecting vulnerabilities in source code
WO2006087780A1 (ja) * 2005-02-17 2006-08-24 Fujitsu Limited 脆弱性監査プログラム、脆弱性監査装置、脆弱性監査方法

Patent Citations (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP2004171064A (ja) * 2002-11-15 2004-06-17 Mitsubishi Research Institute Inc バッファオーバーフロー静的解析方法およびプログラム
WO2004095176A2 (en) * 2003-04-18 2004-11-04 Ounce Labs, Inc. Detecting vulnerabilities in source code
JP2006523898A (ja) * 2003-04-18 2006-10-19 オンス ラブス,インク ソースコードの脆弱点の検出法および検出システム
WO2006087780A1 (ja) * 2005-02-17 2006-08-24 Fujitsu Limited 脆弱性監査プログラム、脆弱性監査装置、脆弱性監査方法

Cited By (21)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP2008299723A (ja) * 2007-06-01 2008-12-11 Hitachi Systems & Services Ltd プログラム検証方法、プログラム検証装置
US8365280B2 (en) 2009-06-30 2013-01-29 International Business Machines Corporation System, method, and program for determining validity of string
US8584246B2 (en) 2009-10-13 2013-11-12 International Business Machines Corporation Eliminating false reports of security vulnerabilities when testing computer software
US8468605B2 (en) 2009-11-30 2013-06-18 International Business Machines Corporation Identifying security vulnerability in computer software
US8875110B2 (en) 2010-03-29 2014-10-28 Soft4Soft Co., Ltd. Code inspection executing system for performing a code inspection of ABAP source codes
WO2011122724A1 (ko) * 2010-03-29 2011-10-06 주식회사 소프트 포 소프트 아밥 소스코드의 코드 검사를 수행하는 코드검사 수행시스템
EP2398256A2 (en) 2010-06-18 2011-12-21 Funai Electric Co., Ltd. Television set and speaker system
US8528095B2 (en) 2010-06-28 2013-09-03 International Business Machines Corporation Injection context based static analysis of computer software applications
US8650655B2 (en) 2010-09-13 2014-02-11 Kabushiki Kaisha Toshiba Information processing apparatus and information processing program
JP2012059221A (ja) * 2010-09-13 2012-03-22 Toshiba Corp 情報処理装置、情報処理プログラム
WO2014021190A1 (ja) 2012-08-01 2014-02-06 三菱電機株式会社 プログラム実行装置及びプログラム解析装置
US9507933B2 (en) 2012-08-01 2016-11-29 Mitsubishi Electric Corporation Program execution apparatus and program analysis apparatus
US9959191B2 (en) 2012-11-23 2018-05-01 Samsung Electronics Co., Ltd. Dynamic library profiling method and dynamic library profiling system
JP7068752B2 (ja) 2018-03-22 2022-05-17 三菱電機株式会社 ソースコード解析装置およびソースコード解析プログラム
JP2019168753A (ja) * 2018-03-22 2019-10-03 三菱電機株式会社 ソースコード解析装置およびソースコード解析プログラム
KR102026959B1 (ko) * 2019-04-19 2019-09-30 한화시스템(주) 보안 시스템 및 그 동작 방법
CN110162972A (zh) * 2019-05-06 2019-08-23 武汉大学 一种基于语句联合编码深度神经网络的uaf漏洞检测方法
CN110162972B (zh) * 2019-05-06 2022-11-18 武汉大学 一种基于语句联合编码深度神经网络的uaf漏洞检测方法
KR102067733B1 (ko) * 2019-05-15 2020-01-17 세종대학교산학협력단 포맷 스트링 취약점 검출 방법 및 이를 수행하기 위한 장치
WO2020261430A1 (ja) * 2019-06-26 2020-12-30 三菱電機株式会社 情報処理装置、情報処理方法及び情報処理プログラム
WO2023238239A1 (ja) * 2022-06-07 2023-12-14 日本電信電話株式会社 修正装置、修正方法及び修正プログラム

Also Published As

Publication number Publication date
JP4693044B2 (ja) 2011-06-01

Similar Documents

Publication Publication Date Title
JP4693044B2 (ja) ソースコード脆弱性検査装置
CN108614707B (zh) 静态代码检查方法、装置、存储介质和计算机设备
US7958493B2 (en) Type inference system and method
CN109857641B (zh) 对程序源文件进行缺陷检测的方法及装置
Bernardi et al. Design pattern detection using a DSL‐driven graph matching approach
CN106371997B (zh) 一种代码检查方法及装置
CN112256271B (zh) 一种基于静态分析的区块链智能合约安全检测系统
US11262988B2 (en) Method and system for using subroutine graphs for formal language processing
Dong et al. Orplocator: Identifying read points of configuration options via static analysis
JP4951416B2 (ja) プログラム検証方法、プログラム検証装置
Kuramitsu Nez: practical open grammar language
Lerner et al. Combining form and function: Static types for JQuery programs
US20040010780A1 (en) Method and apparatus for approximate generation of source code cross-reference information
Anderson et al. Supporting analysis of SQL queries in PHP AiR
CN114489653A (zh) 基于编译器的数据处理方法、装置以及可读存储介质
CN114647439A (zh) 一种代码扫描的方法、代码迁移的方法及相关装置
Arusoaie et al. Automating abstract syntax tree construction for context free grammars
Grigorev et al. String-embedded language support in integrated development environment
JP2005056183A (ja) ルール検査システム、ルール検査装置、ルール検査方法、及びルール検査プログラム
Li et al. Mapping Modern JVM Language Code to Analysis-Friendly Graphs: A Study with Kotlin
US20240184549A1 (en) System and method for indexing source code
Zhang et al. Propositional projection temporal logic specification mining
Khabibullin et al. On development of static analysis tools for string-embedded languages
Negrini A hybrid approach for automatic recognition of C++ objects in optimized binaries
CN116595533A (zh) 一种针对Java Web应用的注入型漏洞检测方法及系统

Legal Events

Date Code Title Description
A621 Written request for application examination

Free format text: JAPANESE INTERMEDIATE CODE: A621

Effective date: 20080108

A977 Report on retrieval

Free format text: JAPANESE INTERMEDIATE CODE: A971007

Effective date: 20101124

A131 Notification of reasons for refusal

Free format text: JAPANESE INTERMEDIATE CODE: A131

Effective date: 20101201

A521 Request for written amendment filed

Free format text: JAPANESE INTERMEDIATE CODE: A523

Effective date: 20110128

TRDD Decision of grant or rejection written
A01 Written decision to grant a patent or to grant a registration (utility model)

Free format text: JAPANESE INTERMEDIATE CODE: A01

Effective date: 20110217

A01 Written decision to grant a patent or to grant a registration (utility model)

Free format text: JAPANESE INTERMEDIATE CODE: A01

A61 First payment of annual fees (during grant procedure)

Free format text: JAPANESE INTERMEDIATE CODE: A61

Effective date: 20110217

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20140304

Year of fee payment: 3

R150 Certificate of patent or registration of utility model

Free format text: JAPANESE INTERMEDIATE CODE: R150

LAPS Cancellation because of no payment of annual fees