[レポート]ファイルシステムファザーを使用したカーネルエクスプロイトのハンティング – CODE BLUE 2020 #codeblue_jp

CODE BLUE 2020で行われた「ファイルシステムファザーを使用したカーネルエクスプロイトのハンティング」というセッションのレポートです。
2020.10.30

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

こんにちは、臼田です。

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

ファイルシステムファザーを使用したカーネルエクスプロイトのハンティング

われわれは、JANUS(「GeorgiaTech Systems Software&Security Lab」(SSLab)によって開発された)というファイルシステムファザーを使用し、3つのファイルシステムに16の固有の脆弱性を発見した。ファイルシステムの脆弱性を悪用した結果、R / Wプリミティブ攻撃とカーネル制御フローハイジャック攻撃に成功した。 (われわれが発見した脆弱性はすべて報告されており、一部はパッチに含まれている)。この講演では、このプロセスに必要なすべての技術内容について詳しく説明する。 世界中で、一人当たりのデバイスの数は増加している。 われわれが見つけた統計によると、2020年には1人あたりのデバイス数は6.58であり、合計では約500億のデバイスが存在することになる。これらのデバイスはOSによって制御され、各OSはさまざまなファイルシステムをサポートする。したがって、ファイルシステムの脆弱性は、このファイルシステムをサポートする複数のOSにとって致命的な脆弱性であり、世界中のデバイスを脅かす可能性があるといえる。このことから、1つのファイルシステムの脆弱性を使用して、複数のOSに対していくつの脅威を発生させることができるかを調査し始めた。 ファイルシステムにはいくつかの制限がある。というのも、少なくとも5万行ものコードからなるために、その制約は非常に大きなものとなっている。脆弱性を探したい場合は、コードのすべての行を理解する必要があるように、ファイルシステムのコードを深く理解する必要がある。この講演では、ファイルシステムの構造と機能について説明するとともに、このファイルシステムを攻撃対象領域として使用する際の制限について議論する。 ファイルシステムでクラッシュを起こす方法を説明する。まず、使用したJanusファザーを簡単に紹介し、Janusを最新のカーネルバージョンに移植するプロセスについて説明する。 ファイルシステムは複雑だが、クラッシュを見つけることと、そのクラッシュに対して任意のコード実行を使用することの間には大きなギャップがある。任意のコードの実行には、さまざまなカーネルエクスプロイト手法が必要になる。われわれが示すのは以下のとおり。この部分で必要なLinuxカーネルのエクスプロイトテクニック、既知の脆弱性を悪用するR / Wプリミティブ攻撃、われわれが発見したゼロデイ脆弱性を利用したカーネル制御フローハイジャック攻撃。これらのプロセスを紹介する。これらすべてを管理するため、われわれは新たにクラッシュプルーフ・トリアージ・プログラムとファイルシステム・ファジング・モニター・プログラムを製作した。講演ではこれらも紹介する予定だ。 ファイルシステムはOSとは別に開発されており、メインブランチの更新サイクルは遅れている。最新のOSで管理されているさまざまなデバイスのファイルシステムが既知の攻撃にさらされる可能性があることを確認した。われわれはこの目的のためにさまざまなOSで実験を行ってきた。そして、講演ではその結果を紹介する。

Presented by : キム・ドンヒ - Donghee Kim ホン・ソンピョ - Seungpyo Hong ウォンヨン・ジョン - Wonyoung Jung ホウンジン・ジョー - Heoungjin Jo

レポート

  • JANUSによって開発されたファイルシステムファザーを使って脆弱性を発見した
  • 背景
    • EXT4はたくさんのOSに自動マウントされる
    • 自動で細分化防止ができる
    • SSD向けに最適化されている
    • ファイルシステムはこ別に管理されている
  • いろいろなOSで評価した
  • Smart TVで検証
    • デモ
    • 悪意のあるUSBをテレビにさす
    • カーネルパニックを起こす
    • エクスプロイトできるかも
  • トリアージとモニタリング
    • たくさんのクラッシュがあった
  • 報告したCVEは全部で16あった
  • 詳細な解説
  • ファイルシステム毎の分類
    • BoBFuzzer発見したものが多い
    • ファイルシステムの脆弱性研究が進むことを祈っている
    • それぞれのクラッシュについてエクスプロイトのスコアをつけた
  • Null pointer dereference
    • CVE-2019-19037
    • *bhがext4の関数が利用される
    • カーネルパニックぐらいしか起こせない
    • エクスプロイトスコアは1とした
  • Slab-out-of-bounds
    • CVE-2019-19319
    • old_sizeはle32_to_cpuで計算される
    • 32bitと64bitの差で予想外に大きい値が設定される可能性がある
    • 後に続く値を確認するコードがない場合に発生する
    • 最初のコードポインタが初期化された後に空きがある場合利用できる
    • memsetは0
    • エクスプロイトスコアは4としあ
  • Use-After-Free
    • CVE-2019-19377
    • *wqがfreeになるときに別のオブジェクトをpushできればいい
    • 意味のないfunctions pointerがある
    • control flow hijackingできる
    • 極めて利用しやすいのでスコアは8
    • Heap Sprayingをやっていく必要がある
      • アロケートできるサイズが有る
      • kernelでsyscall管理されている
      • 条件
        • ユーザーが呼べるsyscall
        • サイズを調整できる
    • ゼロデイの全体的な話
    • BTRFSにUAFが見つかった
    • asyncの処理が多なわれる
    • unmount時にclose_ctreeが呼び出される
    • UAFできる
    • このときHeap Sprayingする必要がある
    • free reallocateできなかった
    • 全てがclose_ctreeでおおなわれる
      • バックグラウンドプロセスを利用
    • ターゲットが16Byteだった
      • 別のHeap Sprayingが必要になった
    • BeVX2018で発表されたテクニックを利用
    • 8Byteから利用可能
    • しかしsyscallだけではHeap Sprayinできない
    • kmalloc(16)で割り当てられる
    • re-allocationされてしまうので、されないようにする必要がある
    • allocationを遅らせるテクニックを利用する
    • 2ページにまたがるようにする
    • ページフォルトが起きるようになる
    • re-allocationを遅らせられる
    • userfaultfdを間に設定しkmalloc(16)
    • カーネルメモリにコピーされる
    • AのつぎBをコピーされる
    • Page Faultでコールバック
    • Sleep(5000)へ
    • 特定の時間仕込んだものがカーネルメモリに残る
    • Heap Sprayingできる
    • Control Flow Hijacking
      • unmountするときにinsert_work()が呼び出される
      • wake_up_worker()でスレッド作成
      • select_task_rq()でworker structureを読み込む
      • カーネル保護がオフになればこのポインタを操作できる
    • 最終的に仕込んだSHELLCODEをポイントできた

感想

どのように脆弱性を見つけて最終的にコード実行まで持っていくかということが詳しく説明されていて感銘しました。

見つけられるのがすごい!

詳細はこちらでも公開されていますので見に行ってみましょう!