Share
Embed
様々なCPUアーキテクチャにおけるROP攻撃 / CSEC100
多木 優馬, 福光 正幸, 湯村 翼. 様々なCPUアーキテクチャにおけるROP攻撃可能性の検証, 情報処理学会第100回コンピュータセキュリティ(CSEC)研究会の発表資料
yumulab
March 06, 2023
Transcript
50 slides
-
様々なCPUアーキテクチャにおける ROP攻撃可能性の検証 北海道情報大学 多木 優馬※ 長崎県立大学 福光 正幸 北海道情報大学 湯村
翼 1 ※4月より、GMOサイバーセキュリティ byイエラエ株式会社に就職 -
概要 背景 ・ROP攻撃の活⽤法が増える ・組込み機器への影響は未知数 →検証が要必要 貢献 ・組込み機器を想定したやられ環境を3種類⽤意しROP攻撃を検証した ・x86, ARM32環境への攻撃は成⽴、ARM64環境への攻撃は不成⽴であった 結論
・ 関数呼び出しの⽅法⼀つでリターンアドレス書き換えの緩和が可能 2 ROP攻撃, 各環境の詳細は後述 検証対象 アーキ テクチャ 実行 ステート OS ROP攻撃 成立可否 x86環境 x86 - CentOS6 〇 ARM32環境 Armv8-A AArch32 RaspiOS 〇 ARM64環境 Armv8-A AArch64 Nuttx × -
ROP攻撃の危険性 悪用例 ・ROP攻撃を利用したマルウェアの作成 ・Blind ROP攻撃によるサーバの乗っ取り 4 高い攻撃力 セキュリティ機構の回避 コンピュータの乗っ取り 広い攻撃範囲
パソコン スマートフォン 組込み機器 高い汎用性 Blind ROP, kROPなど、 派⽣技術が多様 -
ROP攻撃の原理 正常なプログラムの コード領域 命令片1 命令片2 命令片3 ROPチェーン 攻撃に必要な 命令片を集める 実⾏ファイル
ROPチェーン 埋め込み コード領域 データ領域 6 … … 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} 0x103ac: pop {r3, pc} 0x10684: mov r0, r7 0x10688: blx r3 0x1067c: mov r2, r9 0x10680: mov r1, r8 0x103ac: pop {r3, pc} 0x10684: mov r0, r7 0x10688: blx r3 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} レジスタに入れる値 レジスタに入れる値 0x103ac: pop {r3, pc} 0x10684: mov r0, r7 0x10688: blx r3 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} レジスタに入れる値 レジスタに入れる値 -
ARM32へのROP例 ・system(“/bin/sh”)を呼び出して制御を奪う例 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ 0x103ac:
pop {r3, pc} : 0x10684: mov r0, r7 0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : コード領域 buf (0x10) fp sp fp + 4 ! ! ! スタック領域 7 saved fp リターンアドレス レジスタ r0 関数の第一引数を格納 r3 汎用レジスタ r7 汎用レジスタ pc 次に実行する 命令ポインタを格納 fp スタックフレームポインタ を格納 sp スタックトップポインタ を格納 -
・bofによるROPチェーン埋め込み時 0x103ac: pop {r3, pc} : 0x10684: mov r0, r7
0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : AAAAAAAAAAAAAAAA fp sp fp + 4 スタック領域 8 AAAA 0x103ac systemの実アドレス 0x10694 ‘A’ * 12 “/bin/sh”のアドレス ‘A’ * 12 0x10684 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ ARM32へのROP例 コード領域 レジスタ r0 関数の第一引数を格納 r3 汎用レジスタ r7 汎用レジスタ pc 次に実行する 命令ポインタを格納 fp スタックフレームポインタ を格納 sp スタックトップポインタ を格納 -
・関数エピローグ時 pop {fp, pc} 0x103ac: pop {r3, pc} : 0x10684:
mov r0, r7 0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : AAAAAAAAAAAAAAAA sp スタック領域 9 AAAA 0x103ac systemの実アドレス 0x10694 ‘A’ * 12 “/bin/sh”のアドレス ‘A’ * 12 0x10684 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ ARM32へのROP例 コード領域 レジスタ r0 関数の第一引数を格納 r3 汎用レジスタ r7 汎用レジスタ pc 0x103ac fp 0x41414141 sp スタックトップポインタ を格納 -
・pop {r3, pc} 0x103ac: pop {r3, pc} : 0x10684: mov
r0, r7 0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : AAAAAAAAAAAAAAAA sp スタック領域 10 AAAA 0x103ac systemの実アドレス 0x10694 ‘A’ * 12 “/bin/sh”のアドレス ‘A’ * 12 0x10684 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ ARM32へのROP例 コード領域 レジスタ r0 関数の第一引数を格納 r3 systemの実アドレス r7 汎用レジスタ pc 0x10694 fp 0x41414141 sp スタックトップポインタ を格納 -
・pop {r4, r5, r6, r7, r8, sb, sl, pc} 0x103ac:
pop {r3, pc} : 0x10684: mov r0, r7 0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : AAAAAAAAAAAAAAAA sp スタック領域 11 AAAA 0x103ac systemの実アドレス 0x10694 ‘A’ * 12 “/bin/sh”のアドレス ‘A’ * 12 0x10684 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ ARM32へのROP例 コード領域 レジスタ r0 関数の第一引数を格納 r3 systemの実アドレス r7 “/bin/sh”のアドレス pc 0x10684 fp 0x41414141 sp スタックトップポインタ を格納 -
・mov r0, r7 0x103ac: pop {r3, pc} : 0x10684: mov
r0, r7 0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : AAAAAAAAAAAAAAAA sp スタック領域 12 AAAA 0x103ac systemの実アドレス 0x10694 ‘A’ * 12 “/bin/sh”のアドレス ‘A’ * 12 0x10684 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ ARM32へのROP例 コード領域 レジスタ r0 “/bin/sh”のアドレス r3 systemの実アドレス r7 “/bin/sh”のアドレス pc 0x10688 fp 0x41414141 sp スタックトップポインタ を格納 -
・blx r3 0x103ac: pop {r3, pc} : 0x10684: mov r0,
r7 0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : AAAAAAAAAAAAAAAA sp スタック領域 13 AAAA 0x103ac systemの実アドレス 0x10694 ‘A’ * 12 “/bin/sh”のアドレス ‘A’ * 12 0x10684 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ ARM32へのROP例 コード領域 レジスタ r0 “/bin/sh”のアドレス r3 systemの実アドレス r7 “/bin/sh”のアドレス pc systemの実アドレス fp 0x41414141 sp スタックトップポインタ を格納 -
・system(“/bin/sh”)の実行 0x103ac: pop {r3, pc} : 0x10684: mov r0, r7
0x10688: blx r3 : 0x10694: pop {r4, r5, r6, r7, r8, sb, sl, pc} : AAAAAAAAAAAAAAAA sp スタック領域 14 AAAA 0x103ac systemの実アドレス 0x10694 ‘A’ * 12 “/bin/sh”のアドレス ‘A’ * 12 0x10684 アセンブリ命令 pop xx: spが指す値をxxレジスタに格納 blx xx: xxレジスタが格納するポインタにジャンプ ARM32へのROP例 コード領域 レジスタ r0 “/bin/sh”のアドレス r3 systemの実アドレス r7 “/bin/sh”のアドレス pc systemの実アドレス+4 fp 0x41414141 sp スタックトップポインタ を格納 -
関数2 ROP攻撃対策の先行研究 ・Control-Flow Integrity (CFI) - ROP対策としてCFIというセキュリティ機構が存在する - 制御フローを監視し、ROP攻撃を防ぐ -
組込み機器で使われるArmv8-Mアーキテクチャでは CFI実装が進む[4] - 組込み機器は種類が多く、CFIが実装できていないものもある 15 CFI Arm AVR RISC-V Mips [4]河⽥ 智明ら,Arm TrustZone for Armv8-Mを利⽤したマルチタスク対応CFIの検討(2018) 関数1 関数3 関数1 -
やられ環境について 19 検証対象 プロセッサ アーキ テクチャ OS 実行 ステート (A)
x86環境 i686 x86 CentOS6 - (B) ARM32環境 Arm Cortex-A53 Armv8-A RaspiOS AArch32 (C) ARM64環境 Arm Cortex-A53 Armv8-A Nuttx AArch64 -
攻撃側環境 ・攻撃者の想定 - 攻撃対象プログラムの実行ファイルを持っており様々な解析が可能 ・命令片の探索 - 解析ツール(rp++,ropper)を使用し、攻撃に使える命令片を探索 ・エクスプロイトコードの作成 - 対象のアーキテクチャに合わせてROPチェーンを作成
- Pwntoolsを用いてROPチェーンを埋め込む攻撃コードを作成 21 -
x86環境 22 検証対象 OS アーキテクチャ設計の違い ROP攻撃 成立可否 LRの有無 命令長 PCの直接
書き換え可否 (A) x86環境 CentOS6 × 可変長 × 〇 -
x86の関数呼び出し ・関数呼び出し側 (caller)の処理 call命令でリターンアドレスのpushと、 関数へのジャンプを行う。 ・呼び出された関数側 (callee)の処理 callerのスタックベースポインタを pushした後、バッファの確保を行う。 23
buffer caller EBP リターンアドレス buffer caller EBP リターンアドレス -
ARM32環境 26 検証対象 OS アーキテクチャ設計の違い ROP攻撃 成立可否 LRの有無 命令長 PCの直接
書き換え可否 (B) ARM32 環境 Raspi OS 〇 固定長 〇 〇 実行ステート: AArch32 -
ARM32の関数呼び出し ・callerの処理 bl命令でリターンアドレスを リンクレジスタに格納して関数にジャンプ ・calleeの処理 基本的に、関数プロローグ時に push {fp, lr}命令があり、 その後にバッファを用意する。
27 buffer saved fp リターンアドレス buffer saved fp リターンアドレス -
ARM64環境 30 実行ステート: AArch64 検証対象 OS アーキテクチャ設計の違い ROP攻撃 成立可否 LRの有無
命令長 PCの直接 書き換え可否 (C) ARM64 環境 Nuttx 〇 固定長 × × -
検証結果 セキュリティ機構が無効であっても関数呼び出し⽅法⼀つで BOF攻撃、ひいてはROP攻撃を緩和できることが分かった。 35 検証対象 OS アーキテクチャ設計の違い ROP攻撃 成立可否 LRの有無
命令長 PCの直接 書き換え可否 (A) x86環境 CentOS6 × 可変長 × 〇 (B) ARM32 環境 RaspiOS 〇 固定長 〇 〇 (C) ARM64 環境 Nuttx 〇 固定長 × × -
考察 ARM64環境へのROP攻撃可能性 ・ARMv8.3から実装されたPointer Authentication Code (PAC) 関数ポインタの先頭16bitに認証コードを埋め込み、ROP攻撃を検出する ・ROP攻撃を困難にするアーキテクチャ設計 - 固定命令長
- PCレジスタの書き換え禁止 - リターンアドレス書き換えの緩和 37 リターンアドレスを格納できるレジスタを用意し そのレジスタの値のpushをcalleeに委ねることができる 設計にすれば他のアーキテクチャで実現可能 -
おわりに ・3種類のやられ環境に対してROP攻撃検証を行い、 x86,ARM32環境への攻撃は成立、ARM64環境への攻撃は不成立であった ・ARM64は、アーキテクチャ設計によりROP攻撃が困難。 アーキテクチャ設計での攻撃対策を行うことで、 低リソースな組込み機器でもROP攻撃対策が見込める 38 検証対象 アーキ テクチャ
実行 ステート OS ROP攻撃 成立可否 x86環境 x86 - CentOS6 〇 ARM32環境 Armv8-A AArch32 RaspiOS 〇 ARM64環境 Armv8-A AArch64 Nuttx × -
バッファオーバーフロー攻撃 ・プログラムが想定されるサイズを超えるデータをバッファに⼊⼒し、 誤作動やコンピュータの乗っ取りを⾏う攻撃。 スタック領域に対するBOF攻撃をスタックバッファオーバーフロー攻撃という。 43 変数A 変数B AAAA AAAA AAAA
AAAA 変数AにBOF攻撃 変数Bの値を改ざん スタックバッファオーバーフローの例 -
Non eXecutable bit (NX bit) ・指定した領域外でのコード実⾏を禁⽌にするセキュリティ機構。 攻撃コードがスタック領域に埋め込まれても、実⾏を阻⽌できる。 ・メモリ管理に使⽤されるページテーブル上で各ページにNX bitがあり、 NX
bitに1がセットされていたらそのページが指すコードは実⾏禁⽌となる。 ・ROP攻撃により突破が可能。ROP攻撃はROPチェーンに沿って 正常なプログラムの命令にジャンプしているだけであり、 コードを実⾏しているわけではないため。 47 -
Address Space Layout Randomization (ASLR) ・実⾏ファイルのコード領域などのメモリアドレスをランダム化し、 特定のコードやデータの不正利⽤を困難にするセキュリティ機構。 ・コード領域やデータ領域といった領域単位でランダム化を⾏う。 なお、関数単位でランダム化を⾏うFGKASLRも研究されている。 ・領域単位でのランダム化では、変数や関数のオフセットアドレスは
変化しないため、1つでもアドレスが特定できれば、 そのアドレスとオフセットアドレスを⽤いて任意のアドレスの特定が可能。 48 -
Stack Smash Protection (SSP) ・スタックバッファオーバーフロー攻撃を検知するセキュリティ機構。 ・スタック領域に乱数値(カナリア)を挿⼊し、 その値が書き換えられていたら、 スタックバッファオーバーフロー攻撃を受けたものとみなし、 プログラムを強制終了して保護する。 ・ヌル⽂字に関するバグImproper
Null Terminationにより、 カナリアを特定することができる。 また、環境によってはBlind ROPによってカナリアを特定できたりなど、 カナリア特定の⽅法は多い。 49