[レポート]Frankenstein – フルスタックファジングによる組込みファームウェアとAndroidのバグの発見 – CODE BLUE 2020 #codeblue_jp

CODE BLUE 2020で行われた「Frankenstein - フルスタックファジングによる組込みファームウェアとAndroidのバグの発見」というセッションのレポートです。
2020.10.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、臼田です。

今回はCODE BLUE 2020で行われた以下のセッションのレポートです。

Frankenstein - フルスタックファジングによる組込みファームウェアとAndroidのバグの発見

クローズドソースな組込み用ファームウェアのバグを発見することは簡単なことではない。解析の最初のステップである、ソフトウェアにデバッガーを接続するなどの単純な方法は不可能である。デバッグ用インタフェイスがない、ソフトウェアはホストのオペレーティングシステム上で動作している可能性がありファームウェアの実行が監視できないなどの理由で解析が行き詰まることもよくある。

この講演では、ARMベースのファームウェアの解析、ファジング、パッチの適用が可能な、Frankenstein [1]と名付けられた新しいアプローチを紹介する。 これは、Linuxで実行できるようバイナリを変更することでエミュレーションを利用するものである。さらに、クローズドソースなファームウェアのバイナリダンプに対してCコードのコンパイルとリンクを有効にすることで、追加の抽象化レイヤーなしで関数呼び出しやメモリアクセスが可能となる。 これらのパッチは元のファームウェアとエミュレーター内で実効可能であり、たとえばヒープサニタイザーをエミュレートされたファジングセッション中と同様に物理ターゲットでのデバッグで使用することもできる。

FrankensetinをBroadcomのBluetoothチップに適用することで、ファジングやエミュレートされたチップのLinuxホストへの接続などを行うことができる。 さまざまなワイヤレスのフレームをBluetoothチップに与え、それをLinux BlueZプロトコルスタックに接続することで、これらのファームウェア内の2つのヒープオーバーフローを発見した。 このようなオーバーフローによりデバイスのペアリングの前にゼロクリックのリモートコード実行(RCE)が可能になる。メモリ破損のバグの1つを利用した完全に機能する概念実証(PoC)エクスプロイトをわれわれは開発した。このエクスプロイトを無線上で実装するため、リンクマネージャプロトコル(LMP)の挙動をBluetoothファームウェア内で終了しホストオペレーティングシステムからアクセスできないよう変更する必要があった。これらの変更により、エミュレーションに使用されたコードを再利用して、エクスプロイトに必要なパッチを実装することができた。

最後に、同じアプローチによってオペレーティングシステムのBluetoothスタックからアクセスできない下位層のBluetoothフレーム内で変異を発生させるファジーファームウェアを実装する。これらの変異には、生のBluetoothフレームのパケットおよびペイロードヘッダーが含まれる。 このファジーBluetoothファームウェアを無線で使用し、AndroidオペレーティングシステムのバグであるBlueFragが発見された。 これはペアリング前に存在するものであり、2020年2月のパッチリリースの前にAndroid8および9で動作するPoCを開発した。この脆弱性はCVE-2020-0022として知られている [2]。

[1] https://github.com/seemoo-lab/frankenstein [2] https://insinuator.net/2020/04/cve-2020-0022-an-android-8-0-9-0-bluetooth-zero-click-rce-bluefrag/

Presented by : ヤン・ルージュ

レポート

  • 動機
    • 無線について攻撃者は利用できる
    • 今回はBluetooth
    • OSが処理をしている
    • ユーザーが知らないうちにterminateすることもある
  • なぜエミュレーションを使うか
    • 組み込みは特に難しい
    • Bluetoothはタイミングがあるから難しい
    • 大きなファームウェアで300ほど機能があった
    • どんな機能かわからなかった
  • 今回のデバイスCYW 20735B-01
    • 良かったのはファームウェアとアプリケーションが別れていなかった
    • IDEがほぼすべてをリークできた
  • Frankenstein
    • メモリのイメージを取得してそれに合わせたCコードを書く
    • シンボルデータベースがある
    • コンパイルではパッチをコンパイルする
    • ELFにコンパイルしてqemuで実行も
  • メモリイメージをどう取得するか
    • xmit_stateを実行
    • インターラプトをdhisableする
  • エミュレーションのためにどうにかコンパイルする必要がある
    • Cコードをコンパイルして合わせてelfにする
  • Broadcom Bluetoothファーム
    • ThreadX
    • BCS: コアのスケジューラー
    • L2CAP: コミュニケーションデバイス
    • HCI/H4: シリアルインターフェース
    • LMP: ペアリングを確立したりする
    • ThreadXエミュレーション
      • ファームウェアを最初に実行すると一部関数でエラーが出る
      • Linuxで動かないのでオーバーライドしておく
      • idleスレッドにアクセスできるように
    • BCS
      • 少し厄介だった
      • 312.5us毎に実行される
      • ファームが受け取った段階での一番早いエントリーポイント
      • ペイロードヘッダに完全なアクセスができる
      • 変更もできる
      • 生の無線パケットを注入している
      • BT Clockの末尾2桁によってステータスが分かる
      • 物理デバイスがないのでbtclkも自分たちでやる
  • ファームウェアエミュレーション
    • 生のパケットとして扱えるように
    • デバッグもいろいろ追加した
  • デモ
    • ファームウェアがクラッシュした
    • ヒープサニタイザーが追加されている
    • ヒープの破壊が検知された
    • 通常なら見れないけど何が起きたか確認できる
    • どの関数から来ているかわかる
    • これはファームウェアのリアルなバグ
  • CVE-2019-11516(Broadcom)
    • これに対するRCEを作ってみた
    • ペイロードの末尾3bitを削除
    • 将来利用する領域を1にする
  • ACLのファジング
    • カバレッジファジングをしようとした
    • でもクラッシュしなかった
    • ただNexus 5で奇妙なことが起こった
    • bluetooth daemonをクラッシュさせてしまった
    • 今回はアンドロイドはターゲット外だった
    • 早い段階で諦めた
    • フラグメントエクスポージョンだと考えた
    • 全てを再度試験してみた
    • 新しい携帯を買ったばかりだったので気になった
    • L2CAPフラグメンテーション
    • S10eクラッシュ検証
      • memcpyをエンドレスに行っていた
      • そしてクラッシュしていた
      • しかしランダムな箇所でも起きている
      • リアルなバグを見つけた
      • 1つのプリミティブにメモリリークとBOFがあった
    • CVE-2020-0022 Disclosure
      • Googleでもパッチを当てるのに90日かかった
      • 32bitのAndroid TVをハックした人もいた
  • まとめ
    • 大規模なエミュレーションをする必要がある
    • Cコードで書いているので効率的にできる
    • PythonでAPIを呼ぶよりいい
    • コードはデバイスのパッチとして部分的に再利用できる
    • チップ上で直接実行できる
    • デメリットもある
    • プロセスは長くて退屈

感想

Bluetoothのエミュレータを作って解析していくというのはすごいなと思いました。

是非ブログで詳細を見てみてください!