23
スススススススススス : (propolice StackGuard XP SP2) スス スス スススス ススス スススススス ススススススス ・・

スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

  • View
    217

  • Download
    1

Embed Size (px)

Citation preview

Page 1: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

スタック保護システム : (propolice 、 StackGuard 、XP SP2)

江藤 博明日本アイ・ビー・エム株式会社、東京基礎研究所

Page 2: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

目次

スタックのバッファ オーバーフロー スタックスマッシング攻撃とは? スタック プロテクタ ランドスケープ Stack Guard propolice Windows XP SP2 (/Gs option) 比較 まとめ

Page 3: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

スタックのバッファ オーバーフローとは? バッファ オーバーフローは割り当てられたメモ

リ領域(バッファ)を超える量のビットを入力しようとすると発生する

以上が起こった場合、次の連続したメモリの塊が上書きされてしまう

戻りアドレス 関数ポインタ 前回のフレームポインタなど

また攻撃コードも挿入される これらは深刻なセキュリティ問題に繋がる

Page 4: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

スタックレイアウトおよび攻撃により影響を受けたメモリ --- 関数 foo が bar によって呼び出される場合

int foo (void (*funcp)()) { char* ptr = point_to_an_array; char buf[128]; gets (buf); strncpy(ptr, buf, 8); (*funcp)();}

文字列増加

スタック増加

int bar (int val1) { int val2; foo (a_function_pointer);}

影響を受けたメモリ

最も攻撃を受けやすいターゲッ

val1

val2

arguments (funcp)

return address

Previous Frame Pointer

pointer var (ptr)

buffer (buf)

Page 5: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

攻撃シナリオ #1--- 戻りアドレスの変更

args (funcp)

return address

PFP

pointer var (ptr)

buffer (buf)

攻撃コード

① 戻りアドレスを、攻撃コードをポイントするように変更する。関数が戻った後、攻撃コードに導く。

② コードセグメント内に存在する命令はsystem() や exec() などのような攻撃コードとして使用できる。

② これらのポインタをスタックにセットする

“/bin/sh”

system()

Page 6: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

攻撃シナリオ #2--- ポインタ変数の変更

args (funcp)

return address

PFP

pointer var (ptr)

Buffer (buf)

攻撃コード

① 関数ポインタを攻撃コードをポイントするよう変える。続く関数ポインタ呼び出しは攻撃コードへ導く。

② あらゆるメモリが、たとえスタック内になくても、影響を受けたポインタに値を保存する命令文によって変更されうる。

E.g. strncpy(ptr, buf, 8); *ptr = 0;

関数ポインタ

グローバル オフセット テーブル

①  

②  

Page 7: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

攻撃シナリオ #3--- 前回のフレームポインタの変更

args (funcp)

return address

PFP

pointer var (ptr)

Buffer        (buf)

攻撃コード

① 呼び出し側フレームを近くの場所に変更する。フレームには影響を受けた戻りアドレスが含まれている。

return address

PFP

Page 8: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

スタック プロテクタ ランドスケープ コンパイラベースのプロテクタ

StackGuard 、 stack shield 、 propolice 、 XP SP2 /Gs

ランタイムスタック信頼性チェッカー Libsafe

アドレス空間の非実行可能な部分 Solar Designer の 「 non-exec stack patch 」、 Exec

Shield 、 OpenBSD の W^X 、 XP SP2 NX

単独のソリューションでは解決不可能 !!!

Page 9: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

Stack Guard

StackGuard ではスタックの戻りアドレスの直前に「カナリア」と呼ばれる値 を挿入する。

関数を実行後、プロテクションツールは、「カナリア」が戻りアドレスにジャンプする前に修正されていないかをチェックする。

「カナリア」の値が不正に修正されている場合、プログラムは終了する。

脆弱性報告 “BYPASSING STACKGUARD AND STACKSHIELD ( STACKGU

ARD および STACKSHIELD の回避法)” , Phrack 56 “Four different tricks to bypass StackShield and StackGuard protec

tion ( StackShield および StackGuard 防御を回避する4つの方法)”

Page 10: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

Stack Guard 2.1 様々な「カナリア」の値

ターミネーター カナリア 0x000aff0d ランダム カナリア random XOR カナリア random ^ return address

コンパイラを構築する際に、「カナリア」メソッドを選ぶ

args

return address

canary

PFP

Local variables including arrays

文字列増加

スタック増加

データのランダムな値

mprotect はこのデータへの書き込みアクセスを禁止する

Page 11: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

開発中の Stack Guard

フレームポインタ問題を解決するために、「カナリア」を移動

戻りアドレス、 フレームポインタ、ローカル変数の広範的な完全性チェック

args

return address

PFP

canary

Local variables including arrays

XOR

データのランダムな値

文字列増加

スタック増加

Page 12: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

propolice: 設計目標

“Safe Stack Usage Model” の導入 これは、理想的なスタックレイアウトとスタッ

クの完全性をチェックする手段を組み合わせたものである。

プログラムをできるだけ理想的なスタックレイアウトに近づけるよう変換する GNU gcc コンパイラのパッチはプログラムを変

換するコンパイル過程を追加する

Page 13: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

Safe Stack Usage Model スタックの完全性チェック :

関数のプロローグで、 guard に予想不可能な値をいれる 関数のエピローグで、 guard 値の完全性を確かめる、もしくはプログラ

ムの実行を中止する 理想的スタックレイアウト :

A 配列もポインタ変数もなし B 配列のみ C 配列なし、ポインタ変数あり

args

return address

PFP

guard

arrays

Local variables

A

BC

オーバーフローによって影響を受け

ない

文字列増加

スタック増加

Page 14: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

呼び出し側の関数がスタックスマッシング攻撃に対し安全である理由

args

return address

PFP

guard

arrays

Local variables

A

BC

関数がアクセスできる範囲

関数がアクセスできる範囲である args から guard まではポインタ変数がない。よってメモリはポインタ攻撃の影響を受けない。

関数が呼び出し側の関数に戻った場合、呼び出し側の関数の連続するメモリの塊はバッファ オーバーフローによる影響をうけない。

スタック増加

文字列増加

Page 15: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

わかりやすい説明 : PFP と配列の間に「 guard 」 を構築する方法

foo () {

char *p;

char buf[128];

gets (buf);

}

Int32 random_number;

foo () {

volatile int32 guard;

char buf[128];

char *p;

guard = random_number;

gets (buf);

if (guard != random_number)

/* program halts */

}

1. 「 guard 」と呼ばれる値の挿入

2. ローカル変数の位置を入れ替える+ オプティマイザは random_number への二

度目のアクセスを削除する。- 配置されたバッファ alloca は guard の隣

に位置を変更できない。

Page 16: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

わかりやすい説明 : ポインタタイプがある場合の関数引数の扱い方

foo (int a, void (*fn)()) {

char buf[128];

gets (buf);

(*fn)();

}

Int32 random_number;

foo (int a, void (*fn)()) {

volatile int32 guard;

char buf[128];

(void *safefn)() = fn;

guard = random_number;

gets (buf);

(*safefn)();

if (guard != random_number)

/* program halts */

}

1. ポインタを C領域から指定された変数にコピーする。実際、それはその変数にレジスタを指定しようとする。

2. 指定された変数で関数呼び出しの名前を変更する

Page 17: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

propolice: スタック プロテクタ オプション -fstack-protector

スタック保護は関数がバイト配列の時のみ生成される。

-fstack-protector-all 常に「 guard 」を作成する。 バイト配列が使用されていれば、「 guard 」の隣

に指定される。 そうでなければ、配列が「 guard 」の隣に指定さ

れる。

Page 18: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

propolice の現状http://www.research.ibm.com/trl/projects/security/ssp/ 実際の使用

Laser5, trusted debian, openbsd, gentoo など 対応アーキテクチャ

Ix86, powerpc, alpha, sparc, mips, vax, m68k, amd64

Gcc バージョン gcc2.95.3 – gcc3.4.1 gcc HEAD cvs 開発中

Page 19: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

Microsoft XP SP2 --- Windows 2003 スタック保護 非実行スタック コンパイラ /Gs オプション

xor カナリアと propolice のコンビネーションメソッド

理想的なスタックレイアウトとはほど遠い 脆弱性報告

David Litchfield 氏、 “ Defeating the stack based buffer overflow prevention mechanism of Microsoft Windows 2003 server ( Microsoft Windows 2003 サーバにおけるスタックベースのバッファ オーバーフロー防御メカニズムを破る)”

Page 20: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

Gs オプションがどのように機能するか カナリアは最初に配置されたバイト配列の前に挿入

される。 配列以外のローカル変数はスタック内でアルファベ

ット順に指定されるようである。

args

return address

PFP

Local variables

including arraysXOR

データのランダムな値

Stack point register

canary

First byte array

文字列増加

スタック増加

Page 21: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

防御法の比較表  --- 防御レベル

StackGuard

2.1/3

MS /Gs propolice propolicestack-protector-all

バッファ オーバーフロー 適用可 不可 不可 適用可戻りアドレス 検知 検知 検知 検知

PFP 不可 / 検知 検知 検知 検知ローカル変数のポインタ 不可 / 検知 検知 検知 検知

Args のポインタ 不可 / 検知 検知 防御 防御関数ポインタ 不可 不可 防御 防御

ポインタによる修正 不可 不可 防御 防御

検知 : 関数の終わりに修正がみられる。防御 : 修正されない。

Page 22: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

パフォーマンスに関して考慮すべき点SG/tc SG/rc SG/xc SG/3 MS/Gs propolice propolice/

all

全関数保護 yes yes yes yes no no yes

オーバーフローが検知されない時実行される追加命令の数Mem load 1 3 5 5 - 3 2 – 3 2 – 3

Mem save 1 1 1 1 1 1 1

その他 2 2 4 4 - 4 2 2

実験基準 (実行オーバーヘッド :%)

Ctag - 3 - - - 1 -

Perl - 8 - - - 4 -

ここで示すオーバーヘッド率は、すべての OS のデフォルトでこれを有効にすることを十分なものにする

Page 23: スタック保護システム : (propolice 、 StackGuard 、 XP SP2) 江藤 博明 日本アイ・ビー・エム株式会社、東京基礎研 究所

まとめ

スタックオーバーフロー問題の説明 様々なスタックスマッシング攻撃の説明 StackGuard, propolice, および MS/Gs の特性

を説明 さまざまな観点によるそれぞれの防御法の比