30
CODE BLUE 2016.10.20 @st4g3r

[CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Embed Size (px)

Citation preview

Page 1: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

CODE BLUE 2016.10.20

@st4g3r

Page 2: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Hiroki MATSUKUMA

(@st4g3r)

新米ペンテスター サイバーディフェンス研究所所属

CTF Player TokyoWesterns

興味のあること Exploitation

GLIBC malloc (現時点では)

$whoami

Page 3: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

tl;dr

Heap Exploitation(x64 Linux/Glibc malloc)

"House of Einherjar" とは? Glibc mallocにおける新しいheap exploitation手法で, malloc()の戻り値をおおよそ任意なアドレスに強制させるものである.

通常, ユーザはmalloc()の戻り値のアドレスに対して読み書きを行える.

フラグメント防止のためにあるchunk同士の結合処理を利用する.

Well-sizedなchunk上でのOff-by-one Overflowが直後のchunkのprev_sizeとPREV_INUSEのコントロールをもたらす.

Proof of Concept http://ux.nu/6Rv6h

Page 4: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

概要

Glibc malloc Chunk

Bin

Consolidating Chunks

House of Einherjar Flaw / Flow

Demo

Evaluation

Countermeasures

Page 5: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

"struct malloc_chunk" メモリブロックはfree()される際にfree listへとつながれる.

このとき, メモリブロックは"struct malloc_chunk"として扱われる.

ChunkのサイズはSIZE_SZ*2にアライメントされる.

(prev_size)

size

fd

bk

(not used)

(prev_size)

size

data+

pads

SIZE_SZ=8byte

User'sspace

(a) in-used (b) free図1 struct malloc_chunk

Shared withprevious chunk

Glibc malloc Chunk

Page 6: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

型 名称 説明

INTERNAL_SIZE_T prev_size 自身の直前にあるchunkのサイズ (shared)

INTERNAL_SIZE_T size 自身のサイズと現在の状態

struct malloc_chunk *fd (free list上で)前方につながっているchunkへのポインタ

struct malloc_chunk *bk (free list上で)後方につながっているchunkへのポインタ

表1: struct malloc_chunk

Glibc malloc Chunk

Page 7: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

"struct malloc_chunk" メモリブロックはfreeされる際にfree listへとつながれる.

このとき, メモリブロックは"struct malloc_chunk"として扱われる.

ChunkのサイズはSIZE_SZ*2にアライメントされる.

(prev_size)

size

fd

bk

(not used)

(prev_size)

size

data+

pads

SIZE_SZ=8byte

PMA

User'sspace

(a) in-used (b) free図1 struct malloc_chunk

Low 3 bitsmean chunk

status

Shared withprevious chunk

Glibc malloc Chunk

Page 8: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

"struct malloc_chunk" メモリブロックはfreeされる際にfree listへとつながれる.

このとき, メモリブロックは"struct malloc_chunk"として扱われる.

ChunkのサイズはSIZE_SZ*2にアライメントされる.

(prev_size)

size

fd

bk

(not used)

(prev_size)

size

data+

pads

SIZE_SZ=8byte

PMA

User'sspace

(a) in-used (b) free図1 struct malloc_chunk

Low 3 bitsmean chunk

status

[P]REV_INUSE

IS_[M]MAPPED

NON_MAIN_[A]RENA

Shared withprevious chunk

Glibc malloc Chunk

Page 9: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Free chunkはfree list(bin)につながれる Small bins

MAX_FAST_SIZE < size < MIN_LARGE_SIZE

MAX_FAST_SIZE: 0xa0

MIN_LARGE_SIZE: 0x400

Unsorted bins

free()されたばかりのchunkが一時的に格納されるリスト.

サイズによる制限は無い.

Glibc malloc Bin

Page 10: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

(prev_size)

size

fd

bk

(not used)

bins[n-1]

bins[n]

bins[n+1]

FD

BK

図2. small binのfree list

bins

c

struct malloc_chunk

PMA

Glibc malloc Bin

Page 11: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Glibc malloc Consolidating Chunks

メモリ確保と解放を繰り返しているとフラグメント化を起こしてしまう そこで, free()されるchunkと隣接するfree chunkの結合を考える.

自身の直前のchunkと隣接している.

自身の直後のchunkと隣接している.

PREV_INUSE bit 自身の直前に隣接するchunkが使用中か否かを判断するためのフラグ.

これが結合の際の判断基準となる.

Page 12: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Glibc malloc Consolidating Chunks

Chunkの結合処理はどこにある? Glibcを読む.

free(p)

__libc_free(p)

_int_free(av, p, have_lock) <- これ!

Page 13: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

(a) 始点図3 _int_free()

Page 14: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

(b) 結合箇所図3 _int_free()

Page 15: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

(c) 終点図3 _int_free()

Page 16: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Glibc malloc Consolidating Chunks (prev_size)

size

prev

p

(a) prev_inuseのチェック図4 結合

size = p->size

If not prev_inuse(p):

prevsize = p->prev_size

size += prevsize

p += -(long)(prevsize)

fd

bk

(not used)

(prev_size)

size 0

data+

pads

p

Page 17: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Glibc malloc Consolidating Chunks (prev_size)

size

(b) 再配置図4 結合

size = p->size

If not prev_inuse(p):

prevsize = p->prev_size

size += prevsize

p += -(long)(prevsize)

p

fd

bk

(not used)

(prev_size)

size 0

data+

pads

prev

p

p

Page 18: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Glibc malloc Consolidating Chunks (prev_size)

size 1

p

(c) 結果図4 結合

p(prev_size)

size

fd

bk

(not used)

fd

bk

(not used)

(prev_size)

size 0

data+

pads

prev

p

p

Page 19: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Flaw / Flow

今のところ, これらのことが既知である "p->prev_size"は, 直前に隣接するchunkと共有されうる.

"p->size"のPREV_INUSE bitを基にchunkの結合の可否を決定する.

新しいpの位置は"p->prev_size"により決定する.

"p = chunk_at_offset(p, -((long)prevsize))"

Page 20: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Flaw / Flow

今のところ, これらのことが既知である "p->prev_size"は, 直前に隣接するchunkと共有されうる.

"p->size"のPREV_INUSE bitを基にchunkの結合の可否を決定する.

新しいpの位置は"p->prev_size"により決定する.

"p = chunk_at_offset(p, -((long)prevsize))"

ここで, 以下の条件について考える 3つのchunkが存在する.

p0: well-sizedなサイズをもつchunk(p1->prev_sizeを内包する).

p1: small binサイズのchunk.

(p2: malloc_consolidate()を抑制するためのchunk.)

p0についてOff-by-oneでNUL byte('¥0')なOverflowが存在する.

Page 21: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Flaw / Flow(prev_size)

size

data

(prev_size)

size

data+

pads

1

well-sized

shared

(a) Overflow前図5 House of Einherjarの原理

p0 (used)

p1 (used)

Page 22: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

(prev_size)

size

data

(prev_size)

size

data+

pads

1

(b) Overflow図5 House of Einherjarの原理

Overflown

House of Einherjar Flaw / Flow

Page 23: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

(prev_size)

size

data

0xdeadbeef

size

data+

pads

'¥0'

(c) Overflow後図5 House of Einherjarの原理

p0 (free)

p1 (used)

shared

well-sized

House of Einherjar Flaw / Flow

Page 24: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Flaw / Flow(prev_size)

size

data

0xdeadbeef

size

data+

pads

'¥0'

(c) Overflow後図5 House of Einherjarの原理

p0 (free)

p1 (used)

shared

well-sized

size = p1->size

If not prev_inuse(p1):

prevsize = p1->prev_size

size += prevsize

p1 += -(long)(prevsize)

Page 25: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Flaw / Flow(prev_size)

size

data

0xdeadbeef

size

data+

pads

'¥0'

(c) Overflow後図5 House of Einherjarの原理

p0 (free)

p1 (used)

shared

well-sized

size = p1->size

If not prev_inuse(p1):

prevsize = 0xdeadbeef

size += prevsize

p1 += -(long)(prevsize)

Page 26: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Flaw / Flow

House of Einherjarに必要なこと うまくサイズの調整されたchunkがOff-by-oneでOverflowを起こす.

ターゲットとする領域の近くにfake chunkがある.

fd, bkメンバはfake chunk自身を指すようにすると簡単である.

ターゲットとする領域と"p1"のアドレスについての差分が計算可能である.

このとき, これら2つのアドレスのleakが必要となる.

free()時に"p1->size"が大きく変更されるのでその補正が可能である.

※fake chunkは何回か編集可能であると仮定する.

Page 27: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

デモ

http://ux.nu/6Rv6h

Page 28: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Evaluation

メリット メモリレイアウトにも依るがOff-by-oneなOverflowさえあればできる.

"House of Force"のような巨大なmalloc()を必要としない.

デメリット fake chunkを置ける領域の近くしかmalloc()で取得できない.

2つのアドレスのleakが必要となる.

評価: "悪くはない"

Page 29: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

House of Einherjar Countermeasures

"struct malloc_chunk"がよくないのでは? そもそも"chunk->prev_size"が通常の書き込みにより上書きされることがよくない.

そもそもBoundary Tagアルゴリズムだから仕方がない.

対策方法は? Address checking

結合後の新しいchunkのアドレスは正しいか?

StackとHeapのアドレスは全然違う.

Return addressは守れる.

Heap内でのHouse of Einherjarには対応しきれない.

Page 30: [CB16] House of Einherjar :GLIBC上の新たなヒープ活用テクニック by 松隈大樹

Thank You For Your Attention!Any Questions?