公開日:2007年9月26日
独立行政法人情報処理推進機構
セキュリティセンター
本ページの情報は2007年9月時点のものです。
記載の資料は資料公開当時のもので、現在は公開されていないものも含みます。
C言語/C++言語で書かれたプログラムを最も悩ませる問題のひとつが、いわゆる「バッファオーバーフロー」問題である。いわゆるバッファオーバーフロー攻撃は、実行中のプログラムのメモリ内に攻撃者の手による機械語プログラムが送り込まれて実行され、最悪の場合、コンピュータ全体の制御が奪われることになる。
バッファオーバーフロー攻撃には次の種類がある。
複数の種類の攻撃のうち、これまで最も実行が容易とされてきたのがスタックを標的としたバッファオーバーフロー攻撃である。これは「スタック破壊攻撃」(Stack Smashing Attack)とも呼ばれる。
スタックには、C言語/C++言語の関数のローカル変数(自動変数)と、その関数からのリターンアドレスの両方が置かれる。ローカル変数の領域あふれがおこることによって、容易にリターンアドレスの書き変えがおきる。
この病理メカニズムを悪用し、コンピュータを操るための機械語バイト列を入力データとして送り込むと同時に領域をあふれさせて関数リターンアドレスを辻褄が合うよう書き換え、送り込んだ機械語プログラムに制御を移させるのがこのタイプの攻撃である。
ヒープ領域を標的としたバッファオーバーフロー攻撃も存在する。これは「ヒープ破壊攻撃」と呼ばれることがある。
ヒープ領域におけるバッファオーバーフロー攻撃は多くの場合、ヒープの未使用ブロックの管理に双方向リストと呼ばれるデータ構造が用いられていることを悪用するものである。この双方向リスト構造は、順序付けられたデータの集まりであって、そこに項目を追加したり削除する操作をポインタのつなぎ替えのみで素早く行う仕組みである。
双方向リストを操作してヒープを管理するライブラリの実装によっては、このポインタのつなぎかえのアルゴリズムが無防備であり、メモリ上の任意の箇所への任意の値の書き込みに悪用できるものがある。
攻撃者は、この方法でプログラム内のジャンプアドレスを書き換えて、送り込んだ侵入コードに制御を移す。書き換えの標的となるジャンプアドレスには、関数のリターンアドレス、例外ハンドラアドレス、関数ポインタ変数等がある。
静的領域を標的としたバッファオーバーフロー攻撃は、あふれさせることのできる変数の後方(アドレスが大きくなる方向)の比較的近くに、書き換えてプログラムの制御を奪うことのできるジャンプアドレスが置かれている場合に仕掛けられる。
攻撃を成功させるには、上記3種類の手口とも、プログラムのおおよその動きとメモリ配置がどのようになっているかを攻撃者が把握する必要がある。
広く配布されている製品ソフトウェアのバイナリコードの入手は困難でなく、リバースエンジニアリングに使うことのできるデバッガソフトウェアも多くのものが出回っている。
バッファオーバーフロー攻撃への対策は次のようなものである。
バッファオーバーフロー攻撃は、次のすべてが成立した場合に成功する。
対策は、これらの要因の成立をひとつ以上阻害することによって、攻撃を失敗に終わらせることである。これらに対する阻害手段として次のものが考えられる。(なお、どの手段も100%完璧ではあり得ないことにご注意いただきたい)
バッファオーバーフロー脆弱性対策には多くのものが考案されている。開発工程の中のタイミング別に見ると、次のようになる。
これらの具体的な内容については、後続の次の記事を見られたい。