やる気の出ない情報セキュリティ8 「ホストのセキュリティ」
ホストのセキュリティ
バッファーオーバーフロー
バッファーオーバーフローとは、プログラミング言語のCやC++、アセンブリなどで作成されたプログラムに対し、入力の処理に関する バグを悪用することで、遠隔もしくはローカルから対象とするコンピュータのメモリに不正なデータや実行コードを書き込み、不正に権限を取得したりシステムへの侵入を引き起こしたりする事象もしくは脆弱性のことです。
コンピュータプログラムのほとんどは、プログラムの実行中、データを保存するための場所をメモリ空間上に確保します。
これらの連続した塊のデータの保存領域(スタック領域、ヒープ領域等)をバッファーと呼びます。
C/C++等のプログラムを実行する際、用意されたバッファーの容量を超えてデータを入れようとすると、メモリ空間上でバッファーの境界を越えて後ろに続く部分にそのデータが上書き されてしまうことがあります。これがバッファーオーバーフローです。
一般的にバッファーオーバーフローが起こると、プログラムが誤作動する等ですが、悪意を持った攻撃者がバッファーオーバーフローを悪用する場合には、プログラマの想定外の事象が起こりえます。
例えばバッファーオーバーフローを起こして、次に呼び出されるアドレスを指定することなどができれば、攻撃者が用意した悪意あるプログラムコードを実行させることができます
バッファーオーバーフローを用いた攻撃例
通常、攻撃者はバッファーオーバーフローを悪用して、そのコンピュータ上でshellコード等を実行することを目指します。攻撃例は大きく分けて以下の2つに分けられます。
- ローカルでの攻撃
- リモートからの攻撃
ローカルでの攻撃の目的は、高い管理者権限(root権限)の取得だといえます。
root権限でプログラムが実行されており、ローカル上でスタックオーバーフローを悪用する個音ができれば、root権限で悪意のあるshellコードを実行することができます
攻撃のターゲットとしては、ネットワークサーバープログラム(?)等が想定できます(管理者権限を用いてプログラムを使用する必要があるため)
リモートからの攻撃でも、目的の一つはroot権限の取得です。最終的な目的は、ターゲットのサーバープログラムを攻撃者が操作したり、マルウェアをダウンロードさせて実行させることです。
攻撃例を示します。
① バッファーオーバーフローを悪用するためのデータを送り込みます、またはターゲットとなるマシン側からダウンロードさせます。
② バッファーオーバーフローによりshellコードを実行させます。
③ 別に用意したサイトからマルウェアをダウンロードさせます
④ ダウンロードしたマルウェア本体を実行させます。
または、
③ shellコードにより攻撃者のホストに接続し返します(connect-back)
④ 攻撃者は遠隔端末ツールを用いてターゲットのホストを操作します。
connect-backとは、対象のシステム側から攻撃者側へ接続させることを言うので、ファイアウォールなどでも、内側からの接続が制限されていない場合は、有効になります。
バッファーオーバーフローの詳細と対策
C/C++などによるプログラムの実行単位をプロセスといいます
プロセスが実行されているときのアドレス空間を見てみると、プログラムが実行されると、下位アドレスの「テキストセグメント」部分に実行コードが入ります。初期値を持つ静的変数とグローバル変数は「データセグメント」部分に入り、 初期値を持たない変数は、初期値0として、「BSS(Block Started by Symbol)」に入ります。
ヒープ領域には、Cのmalloc関数などで動的に確保された領域が入り、その上位に「共有ライブラリ」のコードがメモリマッピングされます。
最高位アドレス側から割り当てられる領域がスタックになります。
スタックでは、プログラムのコードを順番に積んでいきます。(int a、等)
文字列変数をchar c[24]などでメモリを24しか確保していないところに、strcpy関数(文字列のコピー)で32バイトなどの文字列をc[24]に上書きするときなどに、 スタックオーバーフローが起こります。悪意のある利用で、リターンアドレスを書き換えたりされることもあります。
ヒープオーバーフローもありますが、簡単に悪用はできないとされています。
ヒープオーバーフローでは、あらかじめ確保していたメモリ領域をオーバーする際に発生します
バッファーオーバーフローを対策するには、まずバッファーオーバーフローを招く関数を使わないことです。
バッファーオーバーフローを招く可能性がある関数は、自動で境界領域をチェックすることをしないので、もし使う場合は、プログラマ自身が境界領域をチェックする必要があります。
他には、セキュリティパッチをOSやアプリケーションにあてること、C/C++などのアセンブリ以外のプログラミング言語を使うこと(Javaやスクリプト言語は問題ない)、バッファーオーバーフロー対策機能が付くコンパイラを用いる等があります
ほかにもデータ実行防止(DEP)や、アドレス空間配置のランダム化(ASLR)等の技術があるらしいですよ。
セキュアOSとセキュアブート
セキュアOSとは、セキュリティ機能を強化したOS、及びその機能のことです。
セキュアOSの定義は主に強制アクセス制御(MAC : Mandatory Access Control)機能及び最小特権を実現する機能を実装したOSのことを指す場合が多いようです。
強制アクセス制御とは、操作する主体と操作される対象をそれぞれレベルわけし、それぞれのレベルに応じてシステムが強制的にアクセス権限を決定する方式です。
管理者がファイルシステムなどでアクセス制御をするのは、任意アクセス制御(DAC : Discretionary Access Control)といいます。
セキュアOSでは、プロセス実行時、最小特権機能により必要最小限しか権限が割り当てられないうえに、強制アクセス制御機能によって定められた範囲の行動しかできないので、攻撃された場合も、被害が拡大する可能性が低くなります。
セキュアOSの例として、Linuxでは、OSSのSELinuxや、AppArmor、TOMOYO Linux等があるみたいです。
攻撃者の悪意の手はシステムコールなどのカーネル自体や、共有ライブラリを書き換える行為に及びます。このような技術をツール化したものをルートキットと呼び、広く普及しています。
攻撃者がルートキットのインストールを成功させてしまうと、セキュアOSでも対処ができなくなります。
そこで提案されたのがセキュアブートと呼ばれる技術です。これは、許可されていないOSやドライバーが起動時に実行されないようにする仕組みです。
セキュアブートは、ファームウェアとOS間のインターフェースの機能を定めたUEFI(Unified Extensible Firmware Interface)と呼ばれる使用の一部として規格化されており、 起動を許可するソフトウェアのハッシュ値等をUEFIモジュールに登録しておくことで実現されます。
UEFIが起動後にOSローダーを読み込み、マルウェア対策ソフトを読み込みます。この際、読み込まれるソフトウェアを、ディジタル署名などを用いて検証します。そのあとで各種ドライバを読み込み、アプリケーションを初期化します。
通常の起動ではOSローダーの後にドライバーが読み込まれますが、セキュアブートでは、検証を伴うためより安全な起動が実現できます。