2012年8月10日金曜日

[ハッキング手法との対応]②バッファオーバーフロー(Buffer overflow)




セキュリティに関心のある人なら、 "バッファオーバーフロー"という用語は馴染みやすいものであり、その中で積極的な管理者は、インターネットに散らばっているさまざまなバッファオーバーフローexploit(攻撃コード)をダウンロードしてテストもして見たのだ。その結果はどうだった? Exploitコードが指示するコンパイルオプションと、ターゲットサーバーが適切たら簡単にroot権限を獲得したのだ。もちろん、攻撃に成功した "バッファオーバーフロー"についてすべてを知っていると自信を持って言える人はそんなに多くないだろう。

この資料では、 "バッファオーバーフロー"のA〜Zまでを説明する必要はないだろうし(既に優れたドキュメントが発表されているため)、 "バッファオーバーフロー"の概念の理解を目的に説明する。

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

文字通り、バッファをあふれ(overflow)ことを意味し、解いて説明すると、メモリに割り当てられたバッファの量を超えるデータを入力して、プログラムの復帰アドレス(return address)を操作し、最終的にハッカーが任意のコードを実行するである。ここでは "バッファ(buffer)"とは、プログラム処理に必要なデータが一時的に保存されている空間にメモリのスタック(stack)の領域とヒープ(heap)領域がここに属し、 "バッファオーバーフロー"が、この2つの領域のどちらを使用するかによって2つに分類することができる。この資料では、その概念がよく知られており、スタックベースのバッファオーバーフローに焦点を合わせて説明します。このように、バッファオーバーフローの概念を理解するためには、プログラミングの基礎知識が必要であり、これにより、高度なハッキング技術に分類されている。

"バッファオーバーフロー"の歴史

バッファオーバーフローは、ハッキング技術ではなく、単純なプログラム上の問題で最初に紹介された1973年頃C言語のデータの整合性の問題で、その概念が初めて分かった。
その後1988年モリスウォム(Morris Worm)がfingerdのバッファオーバーフローを利用したことが知られ、この問題の深刻性が認識され始めており、1997年にはオンラインセキュリティ雑誌で有名なPhrack(7巻49号)にAleph Oneが " Smashing The Stack For Fun And Profit "という文書を掲載しながら、より広く知られるようになった。この記事は、さまざまな "バッファオーバーフロー"攻撃を流行させるきっかけになったし、現在までにハッカー志望者の必読記事として位置付けている。その後、 "バッファオーバーフロー"は、SANS(www.sans.org)
で毎年発表されるTOP20攻撃手法の中で相当数を占めており、ハッカーたちのたゆまぬ愛を受けてきている。

"バッファオーバーフロー"は、どのように決まるのか?

バッファオーバーフローの正確な動作原理を理解するためには、プログラムによってデータがどのように保存されるかをまず理解しなければならない。一つのプログラムは、多くのサブルーチンで構成され、このサブルーチンがプログラムによって呼び出されたとき、関数、変数とサブルーチンの復帰アドレス(return address)へのポインタをスタック(stack)と呼ばれる論理的なデータ構造に格納することになる。スタックは、実行中のプログラムが必要とする情報を格納するメモリ領域です。サブルーチンが終了すると、オペレーティングシステムはそれを呼び出したプログラムに制御を返す必要があるため、復帰へのポインタを介してプログラムがサブルーチンの実行を終えてから戻りアドレスを指すようになる。

バッファは割り当てられたメモリ領域の高アドレスから下位アドレスに設定され、スタック領域の最後の入ってデータが一番最初に抜けて出てくるLIFO(Last in、First out)の特定を持っている。このようなLIFOの特徴で一番最初に入っての(復帰ポイント)がスタックに最後に削除されることを覚えなければならない。サブルーチンの実行が終了すると、最後に行われるのは復帰へのポインタをスタックから削除してサブルーチンを呼び出した関数に返すのだが、もしこのポインタが使用されない場合は、サブルーチンの実行が終了すると、プログラムがどこで行わなければどうかを知ることができないだろう。

ポインタ(pointer)は、メモリの位置を格納する変数である。プログラムの実行を目的として、他のコードに移動するときにどこから去ったかどうかを記憶するためにポインタを使用する必要があり、もしポインタを使用しない場合サブルーチンの実行が終わってどこに戻らなければならどうかを知ることができないだろう。

これで、スタックを操作することになればどんなことが起こるか見てみよう。プログラムは、変数の割り当てられた領域に格納するデータのサイズを確認せずにサイズの制限を設けない場合は、変数領域は、あふれるようになるだろう。つまり、バッファのオーバーフローが発生すると、保存されたデータは、隣接する変数領域も侵すものであり、最終的にはポインタの領域まで侵犯することになるだろう。ハッカーは、これらのデータの長さと内容を適切に調整することで、バッファオーバーフローを起こして、オペレーティングシステムのスタックを崩壊させ、特定のコードが実行されるようにする。ハッカーが送信されるデータは、通常の場合、特定のシステムで実行できるマシン語コードと復帰へのポインタに格納される新しいアドレスで構成されており、復帰へのポインタに格納され、新しいアドレスは、再びメモリのスタック領域を指して、プログラムがサブルーチンで戻ったときに、ハッカーが作成したコマンドを実行することになるだろう。

この時に考慮すべきことは、攻撃対象となるプログラムが何であろうと、ハッカーが攻撃コードは、プログラムが実行されている権限で実行されるということです。このため、ハッカーは、攻撃を成功させた場合のシステムの最上位の権限を得るために、rootまたはadministrator権限で実行中のプログラムを攻撃対象にするのだ。

理論的には非常に直感的なようだが、実際にこの攻撃を実行することは簡単な作業ではない。しかし、このような過程がどのように勉強して理解していないスクリプトキディ(script kiddie)
も簡単に公開された攻撃コードを利用して、バッファオーバーフロー攻撃を試みることができますので、セキュリティ管理者に、より多くの仕事をする状況であるといえる。

"バッファオーバーフロー"の脆弱性が多くの理由は?

多くのプログラムが脆弱性を持つ重要な理由は、エラーチェックを正しく実行しないからだ。エラーチェックを実行していない大きな理由の一つは、開発者が根拠のない特殊な仮定をするためであり、通常の環境では、変数に割り当てられたメモリのサイズが十分であると過信するのも問題になる。脆弱なプログラムであっても、ユーザーが適切に使用して発表されて何年もたっても何の問題もなく動作してきたこともある。そんな中、誰かが突然 "もしプログラムの元と他の種類の情報を入れるとどうなるか?"、 "プログラムに期待されるサイズよりも多くのデータを入れるとどうなるでしょう?"というような疑問を持つようになったエラーチェックを実行していないプログラムは、そのような疑問の実験対象になってハッキングの目的となっている。

この文を終えて

"バッファオーバーフロー"攻撃は、脆弱なプログラムを対象に、攻撃者が任意のコードを実行させることができるという点で非常に危険であり、その結果として得る被害の範囲は、システムを停止させることから、管理者権限を得るものまで様々である。
セキュリティ管理者は、 "バッファオーバーフロー"がどのように動作するのかを理解し、普段のベンダーから提供されるソフトウェア関連のパッチの適用、最小限の権限でのプログラムの実行、不要なサービスを削除する、侵入防止システムを介した有害トラフィック遮断を介して攻撃被害の可能性を最小限に抑える必要がある。
今日何の問題もなかったことにより、自動的明日も安全であること盲信を捨てるべきである。今この時間にも、地球の向こうでは、熱心に攻撃コードをテストする誰かがいますから....

0 件のコメント:

コメントを投稿