サーバセキュリティ(5)
バッファオーバフロー(BOF)攻撃
C++言語などのプログラミング言語で書かれたプログラムでは、プログラムが確保したメモリサイズを越えて文字列が入力されると領域があふれて(オーバフロー)しまい、予期しない動作が起きる。 バッファオーバフローを引き起こしたプログラムが持っているアクセス権の範囲で任意の動作を行うことが可能となる。また、一般にWebサーバなど、インターネット経由でサービスを提供するプログラムは管理者権限で稼動しているため、こういったプログラムのバッファオーバフローを使われてしまうと、不正侵入者に管理者権限を奪われることもある。
仕組み
バッファとは
通常コンピュータプログラムは何らかの情報(数値・文字列)を格納するための領域をメモリ上に確保する。特に、文字列をメモリ上に格納する際には、文字数に応じて連続したメモリ領域を確保する必要がある。この、同じ形式のデータ(ここでは文字)を複数個格納するためにメモリ上に確保する領域のことをバッファ領域と呼ぶ
また、バッファ領域が確保されるメモリには、バッファの利用方法によって主にスタックとヒープの2種類が存在する。スタックは、主に関数内で一時的に利用するデータを格納するために利用され、関数を呼び出す際は、関数呼び出し命令の次の命令が格納されているアドレス、つまり子関数からの戻り先アドレスもスタックに格納される。ヒープはプログラムによってメモリが必要になった際に、動的に確保または、プログラムの開始から終了まで参照される情報を格納しておく領域を指す
オーバフローとは
メモリは無限に存在するわけではなく、メモリ上に確保されるバッファ領域の大きさにも上限がある。バッファ領域の上限はプログラムが規定しているが、一方、プログラムを実行するCPUはバッファ領域の上限を知らない。情報がバッファ領域の上限を超えてしまう場合、CPUはバッファ領域を超えて情報を格納してしまい、バッファがオーバフローしてしまう。その場合、メモリ上の不正な場所に情報を格納することになってしまい、プログラムが誤動作することになってしまう
sfp(スタックフレームポインタ)
内部変数にアクセスするためのスタック領域上の基準点として使用される値を格納する。関数の実行中に内部変数にアクセスする場合にはsfpからの相対アドレス(sfpから何バイト目かという形式で表されるアドレス)を用いる
BOF攻撃の仕組み
スタックには、CPUがそれまで実行していた関数の内部で使用しているバッファやリターンアドレスなどが保存される。スタック上に存在するバッファでオーバフローが発生すると、リターンアドレスが格納されている領域も書き換えられてしまうことがあり、親関数に戻る際に正常なアドレスに戻れなくなる。ここで、このバッファオーバフローを利用して、リターンアドレスに「悪意のあるコードを格納しているメモリアドレス」をセットし、親関数に戻る際に本来の制御を横取りして、悪意のあるコードを実行することが可能となる
ターゲットとなったサービスをシェル(/bin/sh)に置き換えてしまう、ターゲットホスト上の既存のプログラム(バックドアのように機能するもの)を実行さえるものがある
シェル
UNIX環境などでコマンドインタフェースを提供するプログラム
バックドア
侵入者が、一度侵入に成功したホストに再び容易に侵入するために密かに作っておく裏口
setuid/setgid属性悪用
setuid/setgid
基本的に、実行可能ファイルと公共ディレクトリには、3 種類の特殊なアクセス権を設定でき、これらのアクセス権を設定すると、その実行可能ファイルを実行するユーザは、そのファイルの所有者のユーザIDを持つことができる。しかし、ユーザIDがrootに設定されているプログラムを実行することで、スーパーユーザのアクセス権を取得可能となる。
setuid(set userID)
読込み、書込み、実行属性を持つファイルに設定する属性の一つ、実行されたプログラムのユーザ権限を一時的に設定する。一般ユーザなどが使用するコマンドの中で管理者の権限などを必要とする処理の実行を可能にする
setgid(set groupID)
setuidに似ているが、プロセスの実効グループID(GID)はファイルのグループ所有者に変更され、ユーザにはそのグループに与えられたアクセス権に基づくアクセス権が与えられる
仕組み
侵入者が、所有者がrootで、setuid/setgid属性をもつプログラムを実行し、非常にサイズの大きい入力データを与えBOF状態を引き起こし、root権限を手に入れる
クラッカー
悪意をもって他人のコンピュータのデータやプログラムを盗み見、改ざん・破壊などを行う者のこと
クラッカーがコンピュータに不正に侵入した後に利用するソフトウェアをまとめたパッケージ
セキュリティホールなどを利用して他人のコンピュータに不正侵入を行った攻撃者は、侵入を隠蔽するためのログの改ざんツール、侵入口が塞がれても再び侵入できるようにするバックドアツール、侵入に気付かれないための改ざんされたシステムコマンド群などをインストールする。これらを素早く導入するため、一連のソフトを使いやすいパッケージにまとめたものがrootkitで、いくつかの種類がある
これらのソフトのほかにも、ネットワークを盗聴するスニッファツールや、侵入したコンピュータを踏み台にして他のコンピュータを攻撃するための攻撃ツールなどがパッケージされたものもある
影響
不正なプログラムが実行された場合、そのプログラムはBOF攻撃の対象となったサービスと同じ権限で実行されることになる。つまり、バッファオーバフローを引き起こしたプログラムが持っているアクセス権の範囲で任意の動作を行うことが可能となり、不正侵入者に管理者権限を奪われる。
対策
利用者として
予防・防止
- OS・ソフトウェアのバージョンを最新化し、パッチを適用する
- 脆弱性検査を実施し、BOF攻撃に関するセキュリティホールが塞がれていることを確認・対処する
- ファイアウォールによって不要なポートへのアクセスを遮断する
- サービスを提供しているポールに対するBOF攻撃をIPSによって遮断する※1
- スタック領域でのプログラムの実行権限(パーミッション)を外すことが可能なOS使用し、当該機能を有効に設定する※2
- setuid/setgid属性をもつプログラムには以下のように対処する
- findコマンドを使用して所有者がrootでsetuid/setgid属性をもつプログラムを探す
- 上記プログラムの中で不要な物を削除する
- 上記Aで削除できないものは、setuid/setgid属性が不要なものについてはパーミッションを変更してsetuid/setgid属性を解除する
※1通常のファイアウォールではパケットのデータ部分(ペイロード)を詳細にチェックしないので、BOF攻撃を検知・遮断できない
※2この対策を行ったとしてもスタック外の領域にあるプログラムを起動させるタイプのBOF攻撃や、BOF攻撃の対象となったプログラムが異常終了することを防ぐことはできない
検知・追跡
- ネットワーク監視型IDS、ホスト監視型IDS、IPSを用いて検知する
- ホストのログが改ざん・消去などされずに保存されていれば、それを用いて追跡調査を行う
回復
- サーバログ、IDSログなどから原因・脆弱性を特定し、ベンダが公開している対策手順に従って対処する
- 不正アクセスを受けたホスト・当該ホストからアクセス可能なすべてのホストを対象に、データ改ざん、不正プログラムの埋め込み設定変更などの有無を徹底的に検証・修復する
(状況によってはOSをクリーンインストールし、サーバ環境を再構築する) - 予防対策と同時に脆弱性検査を実施し、対処する
開発者として
BOF攻撃について十分に理解し、その原因となるバグを作らないようにする
※C/C++言語を使う場合
- gets、strcpy、strcatなどBOFを引き起こす危険性の高い関数を使用しないようにする
- 入力データのレングスチェックを確実に行う
- スタック上に埋め込んだカナリアコードによってBOF攻撃を検知する
- BOF防止機能を追加したライブラリを使用する
 

