Chapter 5. バッファオーバーフローの回避

 

敵がこの地を囲み、 お前の砦を倒し、城郭を略奪する。

 旧約聖書 アモス書 3 章 11 節
Table of Contents
5.1. C や C++ の危険なところ
5.2. C と C++ でのライブラリによる解決策
5.2.1. 標準 C ライブラリによる解決策
5.2.2. 静的もしくは動的に確保したバッファ
5.2.3. strlcpy と strlcat
5.2.4. libmib
5.2.5. C++ std::string クラス
5.2.6. Libsafe
5.2.7. その他のライブラリ
5.3. C や C++ でのコンパイルによる解決
5.4. その他の言語

頻繁に発生しているセキュリティ上の弱点は、「バッファオーバーフロー」 に対する脆弱性です。 バッファオーバーフローは「バッファオーバーラン」とも言われ、さまざまな バッファオーバーフロー攻撃が存在しています(「スタック領域破壊」や 「ヒープ領域破壊」もそうです)。 厳密に言えば、バッファオーバーフローはプログラムの実装上の問題ですが、 あまりに頻繁に発生し、かつ重大な問題を抱えているので、あえて独立して項目を 立てました。 この問題がいかに重要なのかは、CERT の勧告の内 1998 年の 13 の内の 9、1999 年の少なくとも半分以上がバッファオーバーフロー関連であることで明らかです。 Bugtraq による 1999 年の非公式な調査でも、おおよそ 2/3 の回答がバッファ オーバーフローがセキュリティの脆弱さの原因としています(残りの回答は「設定ミス」 が原因としています) [Cowan 1999]。 これは以前からある既知の問題ですが、未だに幾度となく現れる問題です [McGraw 2000]。 【訳註:Bugtraq は、セキュリティ関連の情報をやり取りする ML です。 ML のアーカイブ が公開されています。 日本語での ML も存在しています。詳しくは、 BUGTRAQ-JP FAQ を見てください】

バッファオーバーフローは、ある値(文字列等)を固定長のバッファ領域にその領域 を越えて書き続けてしまう場合に発生します。 バッファオーバーフローは、ユーザからの入力をバッファに読み込む時にも 起こりますし、プログラムのまったく違った処理の最中にも起こる可能性があります。

安全性が求められるプログラムでバッファオーバーフローが起きると、攻撃者がそれを 悪用するケースがよくあります。 バッファが C のローカル変数で実装されていた場合、攻撃者はこのオーバーフローを その関数中で望みのコードを強制的に実行させる手段として利用します。 この攻撃のバリエーションは「スタック破壊(stack smashing)」攻撃と呼ぶ場合も ままあります。 バッファがヒープ領域にあっても、状況が良くなるわけではありません。攻撃者 は、オーバーフローを使って、プログラム中の変数をコントロールできます。 さらに詳細な情報は、Aleph1 [1996]や Mudge [1995]、LSD [2001]を参考にするか、 Nathan P. Smith 氏のサイト http://destroy.net/machines/security/ にある「Stack Smashing Security Vulnerabilities」を見てください。 【訳註:ヒープ領域は、プログラムで利用するデータを格納する領域で、 利用時に動的に割り当てられ、利用が済むと解放された後、再利用に回されます。 C では malloc(3) で確保された領域がこれに当たります】

高水準言語の大部分は、そもそもこういった問題に影響されません。 理由は、自動的に配列の大きさを変更したり(たとえば Perl)、バッファオーバー フローを検知して防御するようになっていたり(たとえば、Ada95)するからです。 しかし、C はこのような問題に対して、何も防ぐ手段を持ち合わせていませんし、 C++ でもこの問題を発生させるのは他愛もありません。 アセンブリ言語でも何も防御する方法がありません。言語にはそのような防御を 持っているもの(たとえば、Ada や Pascal)もありますが、通常は無効になって います(性能上の理由です)。 たとえプログラムの大部分を他の言語で書いていても、ライブラリルーチンの 多くとそのライブラリルーチンを呼び出すインタフェースコードは C や C++ で書いてあります。したがって、他の言語が期待通りにバッファオーバーフローを完全 に防ぐとは言えません。