Top Banner
YLUG 読読読 読読読読読読読読読読読読読読 YASUDA Yasunori [email protected] 11/Sep/2003
30

YLUG 読書会 バッファオーバフロー防止技術

Mar 19, 2016

Download

Documents

Marlie

YLUG 読書会 バッファオーバフロー防止技術. YASUDA Yasunori [email protected] 11/Sep/2003. 目次. バッファオーバフロー概要 スタックオーバフロー ヒープオーバフロー 検知・防御技術 canary 系 Stack Guard, Stack Smashing Protector, Stack Shield Address Obfuscation 系 ASLR (Address Space Layout Randomization) Address Encryption 系 PointGuard - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: YLUG 読書会 バッファオーバフロー防止技術

YLUG 読書会バッファオーバフロー防止技術

YASUDA [email protected]

11/Sep/2003

Page 2: YLUG 読書会 バッファオーバフロー防止技術

目次 バッファオーバフロー概要

スタックオーバフロー ヒープオーバフロー

検知・防御技術 canary 系

Stack Guard, Stack Smashing Protector, Stack Shield Address Obfuscation 系

ASLR (Address Space Layout Randomization) Address Encryption 系

PointGuard Non executable memory 系

non-executable stack , PAGEEXEC, SEGMEXEC, exec-shield, Library 系

Libsafe, Libverify

Page 3: YLUG 読書会 バッファオーバフロー防止技術

バッファオーバフロー概要stack overflow スタックをオーバフローさせ、スタック内にある return

address ないしは saved frame pointer を改竄 スタックの改竄内容

return address 時 : exploit code saved frame pointer 時 : exploit code & stack frame

return address の改竄の場合には、攻撃された関数の return 時、 saved frame pointer の改竄時には、攻撃された関数を呼び出した関数が return するときに任意のアドレスにジャンプ

ジャンプ先 スタック上の実行コード libc (return into libc)

スタックに引数を書き、 libc 内の関数にジャンプ

Page 4: YLUG 読書会 バッファオーバフロー防止技術

バッファオーバフロー概要stack overflow

[sample.c]char *func(char *msg) { int var1; char buf[80]; int var2;

strcpy(buf,msg); return msg;}int main(int argc, char **argv) { char *p; p = func(argv[1]); exit(0);}

func()

main()/func()

start()/main()

func()func()func()func()

main()main()main()

main()'s arguments

func()'s arguments

var2bufvar1

saved %ebpreturn address

saved %ebpreturn address

p

low

high

overflow

code/stackframe..

addressof code/stack frame

Page 5: YLUG 読書会 バッファオーバフロー防止技術

バッファオーバフロー概要heap overflow ヒープをオーバフローさせ、ヒープの管理データ

(malloc_chunk) を改竄 free() 時に行うリンクのつなぎ変え処理時に、改竄された

値で指定したアドレスの内容を書き換える 基本的に任意のアドレスの書き換えをピンポイントで可能

struct malloc_chunk { INTERNAL_SIZE_T prev_size; INTERNAL_SIZE_T size; struct malloc_chunk* fd; struct malloc_chunk* bk;}

#define unlink(P, BK, FD) \{ \ BK = P->bk; \ FD = P->fd; \ FD->bk = BK; \ BK->fd = FD; \}

Page 6: YLUG 読書会 バッファオーバフロー防止技術

バッファオーバフロー概要heap overflow

prev sizesizefdbk

prev sizesizefd = Xbk = Y

prev sizesizefdbk

free() 対象

malloc chunk: OP->fd

O->bk= P->fd->bk = (P->fd +12) ← Y

Q->fd=P->bk->fd=(P->bk+8)← X

P->bk

P->fd+12P->bk+8

malloc chunk: P malloc chunk: Q

mallocchunk:O

data mallocchunk:P

data mallocchunk:Q

data

overflow

Page 7: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術stack guard 方式

canary word による stack overflow 検知 return address の直前に canary word を入れておき、関数のリターン時に

canary word が破壊されているかどうかで、スタックオーバフローを検知 検知したら abort を呼ぶ

実装 コンパイラで実装

関数の呼び出し時に canary word を埋め込むコード、関数のリターン時にcanary word の破壊をチェックするコード( C 言語レベル)を挿入

Bypass 方法 saved frame pointer のみ書き換えることで可能 libc の GOT (Global Offset Table), .dtors などを書き換えることで

可能 e.g.) exit のアドレスを書き換え data/bss 領域の間にある

Page 8: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術stack guard

func()

func()

func()func()func()func() canary word

var2bufvar1

saved %ebp

return address

low

main()/func()func()'s argumentshigh

canary word の種類1: NULL canary 値 : 0x002: terminate canary 値 : 0x000aff0d 文字列系関数の terminator を含む NUL(0x0), \n(0x0a)3: random canary 値 : exec 時に乱数を作り、    それとの XOR をとる (MS の /GS もほぼ同じだが     挿入位置が変数と saved %ebp の間 )

Page 9: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術stack guard

function_prologue:pushl $0x000aff0d // push canary into the stackpushl %ebp // save stack frame pointermov %esp,%ebp // saves a copy of current %esp...

function_epologue:leave // restore stack framecmpl $0x000aff0d,(%esp) // check canaryjne canary_changedaddl $4,%esp // remove canary from stackret

canary_changed:... // abort the program with errorcall __canary_death_handlerjmp // just in case I guess

Page 10: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術Stack Smashing Protector 方式

canary word による stack overflow 検知 saved frame pointer の前に canary word (random) を入れておき、関数

のリターン時に canary word が破壊されているかどうかで、スタックオーバフローを検知

ローカル変数の再配置 非バッファ変数をバッファ変数の低位アドレスに配置。非バッファ変数を守る

関数の引数のコピー 引数をローカル変数の領域にコピー。オリジナルを守る

実装 コンパイラで実装

関数の呼び出し時に canary word を埋め込むコード、関数のリターン時にcanary word の破壊をチェックするコードを挿入

スタックフレームの構造の変更 By pass 方法

libc の GOT (Global Offset Table), .dtors などを書き換えることで可能

Page 11: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術Stack Smashing Protector

func()

func()

func()func()func()func()

canary word

buf4buf2copy of arg2

saved %ebpreturn address

low

main()/func()func()'s argumentshigh

[sample2.c]typedef struct {char str[32];} string_t;

char *func(char *arg1, string_t arg2) { int var1=1; char buf2[80]; int var3=3; char buf4[80];;

strcpy(buf2,arg1); strcpy(buf4,arg1); strcpy(arg2.str,arg1); return msg;}

func()func()func()

copy of arg1var3var1

Page 12: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術Stack Smashing Protector

standard_prologue:pushl %ebp // save frame pointermov %esp,%ebp // saves a copy of current %espsubl $272,%esp // space for local variables and canary

protection_prologue:movl __guard, %eax // read global canarymovl %eas,-24($ebp) // save copy of canary in stack...

(function body)

Page 13: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術Stack Smashing Protector

protection_epologue:movl -24(%ebp),%edxcmpl __guard, %edx // is canary in stack changed?je standard_epilogue

movl -24(%ebp), %eaxpushl %eax // push altered canary valuepushl $function_name // push function namecall __stack_smash_handleraddl $8, %esp

standard_epilogue:movl %ebp,%esp // standard epiloguepopl %ebpret

Page 14: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術Stack Shield 方式

return address を別のメモリ領域 (retarray) にコピーしておき、関数のリターン時にチェックすることにより stack overflow を検知

return address の改竄のチェック 関数のリターン先がスタックやヒープにジャンプしていないかのチェック 関数のポインタがスタックやヒープにジャンプしていないかチェック

実装 アセンブラで実装 ( 入力・出力ともアセンブラソース )

retarray: 保存用メモリ領域 retptr: 何個 return address を保持しているかのポインタ (=array tail)

Bypass 方法 saved frame pointer のみの改竄で可能 libc の GOT (Global Offset Table), .dtors などを書き換えること

で可能

Page 15: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術Address Space Location Randomize 方式

スタック、ヒープ、テキスト、ライブラリをマップする仮想アドレスを exec 時にランダマイズし、ジャンプするアドレスの指定を困難にする

stack : 4 ~ 27 bit mmap (library, heap, thread stacks, shared memory) : 12 ~ 27bit exec (text/data/bss), brk(heap) : 12 ~ 27bit

実装 カーネル内で実装

exec 時にランダマイズしてマップ 絶対アドレスの場合には fault handler がアドレスを再セット

Bypass 方法 ランダマイズされていない範囲 (0 ~ 11bit = 4kbytes = 1page) はアドレ

スの指定が簡単 同じページに飛び先のコードがある場合、 return address を下位 1byte のみ書

き換えで OK リーク関数 (printf 系 ) のあるプログラムを利用し、 1byte overflow で

main() の return address を読み出し、 libc 内の関数のアドレスを計算

Page 16: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術PointGuard 方式

ポインタの値を暗号化してメモリに保持、レジスタにロードするときに復号することによりジャンプするアドレスの指定を困難にする

暗号は 32bit 乱数との XOR( 乱数は exec 時に取得 ) ポインタの値を改竄されても、 illegal な領域を指すだけですむ 乱数は readonly page において、書き換えられなくする 乱数はプログラム実行時に生成

すべてのポインタを対象 Return address, Frame pointer, Function pointer (stack, heap),

Data pointer (stack, heap) 実装

コンパイラで実装 GCC の AST (Abstract Syntax Tree) ステージで実装

Page 17: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術PointGuard

CPU

pointer decryption

dataencryptedpointerMemory 0x7239

0x1234

0x7239

1. fetch pointer value2. access data referenced by pointer

0x1234

Page 18: YLUG 読書会 バッファオーバフロー防止技術

メモリレイアウト

Page 19: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術non-executable stack 方式

x86 のセグメント機能を利用した non-executable stack コードセグメントのリミット (CS limit) をスタックのアドレス境界以

下にし、スタック上のコードを実行できなくする x86 ではページプロテクションは READ, WRITE しかないため、ハー

ドウェアレベルで non-executable の制御はできない

実装 カーネル内で実装

exec 時にメモリレイアウトを調整 Code segment descriptor を設定

mprotect(2) で PROT_EXEC 設定可 Bypass 方法

return into libc など

0x0

0xbfffffff

CS

stack growth

Page 20: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術PAGEEXEC 方式

x86 のメモリ保護機能を利用した non-executable memory PTE の User/Supervisor bit を exec/non-exec bit として転用。 data 領域は non-exec (supervisor) に設定すると、 data を読み込

む際、必ず trap が発生する。 page fault handler は instruction fetch の場合、プログラムを

abort, data fetch の場合、 supervisor bit を user bit にして、 TLB にロード。

データキャッシュにキャッシュされるものはすべて User bit を立てる。 キャッシュフラッシュの際に supervisor bit を立てて書き戻す

実装 カーネル内で実装

page fault handler など Bypass 方法

return into libc など

Page 21: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術SEGMEXEC 方式

x86 のセグメント保護機能を利用した non-executable memory ユーザの仮想アドレス空間をデータセグメント (0 ~ 1.5GB) とコードセ

グメント (1 ~ 3GB) に分ける。 データセグメントにはデータとテキスト、コードセグメントにはテキス

トのみ配置 テキストにはデータ (string, function pointer table) も含まれるため、ミ

ラーを data 領域におく 実装

カーネル内で実装 exec 時にメモリレイアウトを調整

Code segment descriptor を設定 Data segment descriptor を設定

絶対アドレスの場合には fault handler が                               アドレスを再セット

Bypass 方法 return into libc など

0

1.5GB

3GB

text

text

dataDS

CS

Page 22: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術SEGMEXEC$/tmp/cat /proc/self/maps [1] 08048000-0804a000 R-Xp 00000000 00:0b 1190 /tmp/cat [2] 0804a000-0804b000 RW-p 00000000 00:0b 1109 /tmp/cat [3] 0804b000-0804d000 RW-p 00000000 00:00 0 [4] 20000000-20015000 R-Xp 00000000 03:07 110818 /lib/ld-2.2.5.so [5] 20015000-20016000 RW-p 00000000 03:07 110818 /lib/ld-2.2.5.so [6] 2001e000-20143000 R-Xp 00000000 03:07 106687 /lib/libc-2.2.5.so [7] 20014300-20149000 RW-p 00000000 03:07 106687 /lib/libc-2.2.5.so [8] 20149000-2014d000 RW-p 00000000 00:00 0 [9] 5fffe000-60000000 RW-p ffffff000 00:00 0[10] 68048000-6804a000 R-Xp 00000000 00:0b 1109 /tmp/cat[11] 80000000-80015000 R-Xp 00000000 03:07 110818 /lib/ld-2.2.5.so[12] 8001e000-80143000 R-Xp 00000000 03:07 106687 /lib/libc-2.2.5.so

data segment: 1 ~ 9 (1, 4, 6 は 10,11,12 のミラー )code segument: 10 ~ 12

DSCS

Page 23: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術exec-shield 方式

x86 のセグメント機能を利用した non-executable memory プロセスごとに CS limit を可能な限り小さく設定

コンテクストスイッチごとに CS descriptor を変更 ( 数クロック程度 ) CS limit のあたりは ascii-armor エリア (0x00 を含む ) ような値に

する strcpy などが途中で止まるように

実装 カーネル内で実装

exec/context switch 時に code segment descriptor を設定 ld で指定

-melf-i386-small option の追加 スタック上のコードを実行させる場合には、バイナリの ELF フラ

グを設定することで non-exec の対象からはずせる By pass 方法

return into libc など

Page 24: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術exec-shield$/home/mingo/cat-lowaddr /proc/self/maps00101000-00116000 r-xp 00000000 03:01 319365 /lib/ld-2.3.2.so00116000-00117000 rw-p 00014000 03:01 319365 /lib/ld-2.3.2.so00117000-0024a000 r-xp 00000000 03:01 319439 /lib/libc-2.3.2.so0024a000-0024e000 r-xp 00132000 03:01 319439 /lib/libc-2.3.2.so0024e000-00250000 rw-p 00000000 00:00 001000000-01004000 r-xp 00000000 16:01 2036120 /home/mingo/cat-lowaddr01004000-01005000 rw-p 00000000 16:01 2036120 /home/mingo/cat-lowaddr01005000-01006000 rw-p 00000000 00:00 040000000-40001000 rw-p 00000000 00:00 040001000-40201000 r—p 00000000 03:01 464809 locale-archive40201000-40207000 r—p 00915000 03:01 464809 locale-archive40207000-40234000 r—p 0091f000 03:01 464809 locale-archive40234000-40235000 r—p 00955000 03:01 464809 locale-archivebfffe000-c0000000 rw-p fffff000 00:00 0

CS limit 01004000

Page 25: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術libsafe 方法

危険な libc 内の標準関数の置き換え str 系 , printf 系 , gets, getwd, realpath, wcpcpy, wscat, wcscpy,

memcpy 引数チェックを行う

スタックフレームを壊すかどうか? gcc の __builtin_frame_pointer(0) を使って境界を取得 StackGuard などのスタックフレームの構成が変更されたものと組み合わせ不可

実装 共有ライブラリによる実装

/etc/ld.so.preload, LD_PRELOAD によって libc より先にリンク オーバフロー時にメールを送れる /etc/libsafe.exclude で libsafe 対象外のコマンドの設定ができる

Bypass 方法 上記以外の関数のオーバフロー libc の GOT (Global Offset Table), .dtors などを書き換えることで

可能

Page 26: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術libsafe

Page 27: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術libverify 方法

プロセスのメモリ内のコードを書き換え、 return address の改竄チェック

ヒープにオリジナルの関数のコードをコピー オリジナル関数のテキストは wrapper_entry にジャンプするコードに置換 wrapper_entry は return アドレスを保存し、ヒープ内のコピーにジャンプ 関数の最後に wrapper_exit にジャンプし、 return address をチェック

実装 共有ライブラリの実装

/etc/ld.so.preload, LD_PRELOAD によって libc より先にリンク exec 時のリンク処理の中で rewrite する (_init で実行 )

Bypass 方法 libc の GOT (Global Offset Table), .dtors などを書き換えることで可能

Page 28: YLUG 読書会 バッファオーバフロー防止技術

検知・防御技術libverify

Page 29: YLUG 読書会 バッファオーバフロー防止技術

比較方式 H/Wサポー

ト要

ソースコード要

Stack frame 改竄チェック

データ領域実行禁止

アドレスのランダム化

StackGuard No Yes Yes (※1) No NoStackShield No Yes Yes (※1) No NoSSP(Propolice)

No Yes Yes No No

PointGuard No Yes Yes (※2) No NoASLR No No No No Yesnon-exec stack

Yes No No Yes (※4) No

PAGEEXEC Yes No No Yes NoSEGMEXEC Yes No No Yes Noexec-shield Yes No No Yes Nolibsafe No No Yes (※3) No Nolibexec No No Yes No No※1 RA のみ ※ 2 アドレスのみ ※ 3 一部の標準関数のみ  ※ 4 stack のみ

Page 30: YLUG 読書会 バッファオーバフロー防止技術

まとめ 組み合わせて使おう

適用領域によって最適な組み合わせは変わる コンパイラ変えて OK or NG ハードウェアサポートがある or ない 性能の妥協点など

性能比較するためのデータが少ないのでオーバヘッドの比較ができないが、だいたいの目安は以下のとおり

コンパイラがコード追加 数 %~ 20%くらい、 (最悪だと 80%?!)

ハードウェアサポート利用 ~ 10% くらい , (PAGEEXEC はもっと多いはず )

lib 系 ~ 20% くらい

libsafe < libverify ≒ stack guard address obfuscation 系

多分そんなに大きくないはず ( 絶対アドレスがなければ )