バッファオーバーフロー

バッファオーバーフローとは


バッファオーバーフロー(バッファオーバーラン)とは、プログラムでのデータ入力によってバッファ(実行時に確保されているメモリ上の領域)を超える領域を破壊・改ざんできる脆弱性と、それを利用してシステムの異常動作を引き起こしたり、悪意のあるプログラムを実行させたりする攻撃をいいます。

例えば C言語の場合、「char str[10];」のように10バイト分の文字列用バッファを確保して、入力された文字列をこの変数に代入できます。この代入や処理にgets(標準入力からメモリへの文字列の入力)やstrcpy(メモリ間の文字列のコピー)等でバッファ長より長い文字列を扱うと、バッファを超えた部分(char str[10]; の場合は11バイト目以降)が他のメモリ領域を上書き・破壊してしまいます。このように、メモリを直接扱う言語上で入力データ長の制御を怠るとバッファオーバーフローが発生します。

バッファオーバーフローは入力データが無作為であればプログラムの異常動作(データの破損や異常終了)を引き起こします。さらに、メモリ上のバッファや関数スタックの配置などを分析された場合、悪意あるプログラムを実行される恐れも生じます。例えば、ローカル変数が配置されるスタック領域には、関数の呼び出し元を格納するリターンアドレスも配置されていますが、バッファオーバーフローの脆弱性を悪用して、機械語のプログラムをメモリ上に配置するとともにリターンアドレスをそのアドレスに書き換えると、関数の終了時に攻撃者が入力したプログラムに実行制御が移されます。悪意のあるプログラムが実行された場合、ウイルス・マルウェアの侵入や機密情報の取得、サーバの乗っ取りなどの大きな被害につながる恐れがあります。

バッファオーバーフローの対策法とは


バッファオーバーフローの脆弱性を防ぐためには、入力データのサイズがバッファを超える場合も正しく処理できるよう、コーディングもしくは言語のレベルで対策することになります。

コーディングレベルの対策としては、データ長を制御できないメモリアクセス関数の使用を避けることが挙げられます。例えばC言語のgets関数ではなく、バッファ長を指定できるfgets関数で実装する事が考えられます。また、最近のC++標準ライブラリでは、gets関数の使用を制限するなどの安全策がとられているため、古いライブラリを使わないこともある程度の対策となります。さらに静的解析やユニットテストも考えられます。これによりバッファオーバーフローの原因となるコードを発見できる場合があり、リスクが軽減されます。

より根本的な対策としては、メモリ保護の仕組みが組み込まれた言語(Java等)を実装に用いる事です。これにより、言語レベルでバッファオーバーフローからメモリが保護され、メモリ上のデータの破壊・改ざんや任意コードの実行を防止できます。