[CODE BLUE 2018] GLitch: WebGLを使って携帯電話を攻撃する ピエトロ・フリーゴ [レポート] #codeblue_jp

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

こんにちは、芳賀です。

『世界トップクラスのセキュリティ専門家による日本発の情報セキュリティ国際会議』でありますCODE BLUE 2018に参加していますのでレポートします。

このブログは下記セッションについてのレポートです。

GLitch: WebGLを使って携帯電話を攻撃する Presented by ピエトロ・フリーゴ

GLitchは(現在)悪名高いRowhammerの脆弱性を利用して、どんなソフトウェアのバグを利用することなくAndroidスマートフォンの制御を奪取できるJavascriptの悪用(エクスプロイト)だ。この新たな悪用方法が与える影響は大きく2つある。 (i) より広範囲ARMプラットフォーム(例えばあなたのスマートフォン)に対するJavaScriptベースのRowhammer攻撃の最初の例 (ii)GPUからトリガーされたRowhammerビットフリップ(ビット反転)の最初のPoC(概念実証) もしかしたら、「どのようにGPUからビットフリップを行うのか?」「しかもそれをJSからどのように行うのか?」と疑問に思う人もいるだろう。 その答えは「WebGL」だ。WebGLはJavaScriptからDRAMへの「高速なレーン」を用意しており、Rowhammerビットフリップを実行できるのだ。

もし、これらの用語のいくつか(もしくはほとんど)に精通していなくても恐れる必要はない。講演では、高度な悪用のための技術を構築するための基礎から始める。 また、我々は「Rowhammer 101」クラスから始め、攻撃を構築するためのGPU内部構造について説明を行っていく。 この後、実際のGLitchの脆弱性が残したゲストを用意する予定だ。 最後には、WebサイトからAndroidスマートフォンを制御するためのバグのないエクスプロイトプログラムの構築方法を紹介する。ここではRowhammerを利用してFirefoxブラウザを攻撃するために役に立つ悪用テクニックについて述べる。

レポート

  • DRAM のアーキテクチャ
    • つねにキャパシタが保持されているわけでは無い
    • データを読み出すために一度、Row Buffer へ読み込む必要がある
    • その読み出しの際にBit反転を仕込むことができる
  • Attacker primitives
    • DRAMは遅いのでCachからデータを持ってくる
    • Cashに無ければDRAMから取得する
    • このときに clflushを使う
    • JSでは clflushが使えないので evication setsを使う
    • Contiguous memory(連続メモリページ)の準備が必要
    • これらをモバイルで発生させるには?
      • clflush も evication setsも使えない
      • ION == DMA memory ならできる。
      • それ以外の方法を考えるために Attack Vectorを変えて試したらどうか?
        • JSでCPU経由ではなくWebGLを使えばどうか。
    • DRAMへGPUからアクセスする
      • GPUではRendering pipelineがある
      • input - vertex shader - fragment shader - output
      • GPU では DRAMからL2キャッシュ L1キャッシュ経由してSPで実行される
      • 結果がまたDRAMへ格納される
      • この流れは操作できる
    • GPUの場合、キャッシュが小さいので目指すBitFlipまでのloopが少ない
    • DRAMも小さいため、たとえば4kbyteずつ読み込むことで空きメモリからHammer可能な領域を見つける事ができる
  • Glitch の方法
    1. 連続メモリへアタッチする
    2. Memory templating
    3. Memory massaginh
    4. Exploitation
  • GLitchのexploitation
    • JS Attraysのやりかた
    • NaN-boxing
      • IEEE-754 floating point(double)
        • 1.125 = 1125 * 10^(-3)
        • 1.125 = 1125 * 10^(23)
            a = (bouble) 0x7fffff8c9a8b7c4d ← JSでdouble
            a = (bouble) 0xffffff8c9a8b7c4d ← JSでオブジェクトとしてArrayに入る
        
    • バッファの中では不明な領域がある
      • Inline ArrayBuffersを使う事でheader と dataを連続させることができる
    • 一連の流れを JSでおおよそ160秒前後で実行できることが確認できた
  • まとめ
    • RowhammerをJSからモバイルで実行できる
    • GPUが新しいAttack vectorになりえる
    • 現在のスレッドモデルをよく考えていく必要がある

感想

JavaScriptからWebGLを使ってメモリを固定的に操作できてしまう事はかなり興味深い話だった。