5.3. C や C++ でのコンパイルによる解決

まったく違った観点から解決をはかろうとするものに、領域の境界チェックを コンパイル時に行うものがあります([Sitaker 1999] のリストを参照して ください)。 私見ですが、いろいろな防御手段の 1 つとして使用するなら、そのようなツールは 非常に有効です。しかし、この手法だけで防御するのは賢い手段とはいえません。 理由として少なくとも 2 つは挙げられます。 まず、そのようなツールはバッファオーバーフローに対して必要な防御の一部しか 行えません(そして「完璧な」防御を行おうとすると、通常の 12 から 30 倍遅く なります)。C と C++ はそもそもバッファオーバーフローを防ぐ手段を持ち合わせて いません。 次に、オープンソースであるプログラムはどんなツールを使ってコンパイルするか が決められているわけではない点です。システムについてくるデフォルトの「普通の」 コンパイラを使うと、セキュリティの弱点をさらすかもしれません。

さらに有効なツールの 1 つに「StackGuard」があります。これは、標準的な GNU C コンパイラの修正版です。 StackGuard は「ガード」するための値(「カナリア(canary)」と呼びます)を リターンアドレスが書かれている前に挿入して動作します。バッファオーバーフロー が発生してリターンアドレスを書き換えると、カナリアの値が(おそらく)変更され、 実際に使用される前にシステムが検出します。 これは非常に有効なのですが、リターンアドレス以外の値(これを利用してもシス テムを攻撃できます)を書き換えるバッファオーバーフローには対処できません。 StackGuard を強化して、カナリアを他のデータに対しても使えるようにしたものが、 「PointGuard」です。 PointGuard は自動的にある値(たとえば関数のポインタやロングジャンプ・バッファ) を保護します。 しかし他の変数を PointGuard を使って保護する場合、プログラマの介在が必要と なります(プログラマはどのデータをカナリアで保護しなければいけないのかを 判断しなければいけません)。 これは有効な半面、本来保護すべきなのに必要がない、とうっかり判断してしまい、 いとも簡単に保護を省いてしまう場合が考えられます。 StackGuard や PointGuard、またそれと同様なものについての詳細は Cowan [1999] を参照してください。 【訳註:鳥類のカナリアは、炭鉱で一酸化炭素の増加や酸欠状態を「検知」する ために飼われていました】

これと関連して、Linux のカーネルを修正し、スタック・セグメント上でのプロ グラムの実行を禁止してしまう方法もあります。それを行うにはパッチが必要です (Solar Designer 氏のパッチに含まれています。 http://www.openwall.com/linux/ を見てください)。 このドキュメントを書いている時点では、まだカーネルに取り込まれていません。 技術的な理由の 1 つに、思ったほどその効果がでない点があげられます。 攻撃者は、対象にしているプログラムに既に存在している他の「面白そうな」場所 (ライブラリやヒープ領域、スタティックなデータ・セグメント領域等)を呼び出せ てしまうからです。 また Linux はスタック領域でプログラムを実行する場合があります。例として、 シグナルや GCC の「トランポリン」の実装をする場合です。 Solar Designer 氏のパッチでこのようなケースにも対応できますが、これがパッチを 複雑なものしている原因です。 個人的には Linux 本流に組み込まれてもよいかと思います。というのもこれによって いくぶんかでも攻撃が難しくなりますし、既存の攻撃のある部分は防御できるから です。 しかし Linus Torvalds 氏たちが考えているように、このパッチが見た目ほどさま ざまな防御ができない、比較的簡単にこの防御の裏をかくことができる、という点 については私も同意見です。 Linus Torvalds 氏がこのパッチを採用しない理由については、 http://lwn.net/980806/a/linus-noexec.html を見てください。 【訳註:トランポリン(trampoline)とは、プログラムが実行している最中に プログラム自身によって生成される、互いに独立した小さなオブジェクト・ コードを指します】

要するに、まずプログラムそのものでバッファオーバーフローを防ぐように開発 するのが大切です。 そのように開発した後に、StackGuard のようなツールやテクニックを使って、 さらに安全策を講じておくべきです。 ソースコードからバッファオーバーフローを追い出せるだけ追い出したら、 StackGuard はさらに効果を発揮します。というのも StackGuard が防御のために 呼ばれるような「致命的な弱点」を減らすことができるからです。