経緯
Chromeの緊急アップデートがあるというニュースが流れてきたものの、型混乱??ヒープ破壊??と分からない単語ばかり並んでいたため、自分なりにいろんなサイトやAIを駆使してどのような攻撃が出来るようになっていたのか調べてみました。全然知識なくてオハズカシ、、、
👇流れてきたニュース(というより会社のSlackで流れてきた記事)
https://forbesjapan.com/articles/detail/85308?s=ns
JavaScriptを普段使用していない文系卒エンジニアがAIにへばりついて書いたため、
所々認識異なる点があるかもしれません。
お気づきの点ありましたらコメントいただけるとありがたいです。
原因
型混乱によるヒープ破壊
👆deoptが機能しないバグ
詳細を簡単に
V8はJavaScriptを高速化するため、実行時観察した型に基づいて「その型専用の最適化機械コード」を生成
⇒最適化後、異なる型のデータが送り込まれたにもかかわらず最適化コードが実行され、隣接するメモリへの読み書き(Out-of-Bounds)が発生する【ここがバグ】
👆
本来なら
V8が最適化したコードの型と指定された型が違っていた場合、deopt(型推測して処理を最適化したコードからインタプリタ(遅い処理)に戻す)が起こる
、、が、攻撃者はdeoptの直前又は直後に型混乱が発生させるような処理を実行する
★V8が型を誤解したまま処理を続ける瞬間を利用した攻撃
JSのJITコンパイルって?
JavaScriptの実行を高速化するためによく使われるコードをその場で機械語に変換して最適化する仕組み
JavaScriptはインタプリタ言語&動的型付け言語
実行時に一行ずつ機械語に翻訳しながら実行していく方式の言語 ⇒ 変数に何の型のデータが入ってくるのか確認しながら実行するため遅い
JITコンパイル(実行しながらコードの最適化)
実行しつつよく呼ばれる関数やループを最適化して機械語に変換しメモリに保存 ⇒ 次回以降そのコードを実行する ⇒ 高速処理可能
V8エンジンとは
GoogleのオープンソースでJavaScript,WebAssemblyのエンジン
ChromeやEdge,Braveで使用されている
👆
JSとWasm(C#などが変換されたもの)を同じ内部基盤の上に載せている
⇒JSとWasmが同じランタイムで動くため高速に連携でき、データ連携がスムーズになる 適材適所の処理実行
WebAssembly(Wasm)って?
Webアプリケーションを高速実行するための実行フォーマット
プログラミング言語と多様な実行環境の間に位置する中間層的な役割
「Wasm」と略されることもある。
直接記述するためのプログラミング言語ではなく、多様な言語(JS以外)からコンパイルすることが可能なバイナリ形式で配布されるプログラム
👆
WASMに変換することによりJS以外の言語をWebで高速に動かすことが出来る
V8エンジンでの型管理
V8は高速化のために内部で「型/レイアウト」を強く管理している
👇
実行時に型・レイアウトを学習し、学習した型・レイアウト専用の機械コードが作られる
機械コードが作られると、、
⇒配列範囲チェック・オブジェクト構造チェック・配列の要素型チェックをスキップ
⇒直接アドレス計算をしてヒープに直に読み書きする
問題
今回は学習した型専用の機械コードが作られた後、別の型が送り込まれた際に最適化の解除+インタプリタに戻らないというバグが起こり(バグを起こし??)
隣接するメモリへの上書きが行われ、メモリ破壊につながった。※隣接メモリになにも値がない場合などただのクラッシュで終わる場合もある
攻撃方法(一例)
型混乱~リモートコード実行までの流れを記載
以下のようなソースを記載したWebページを配置
👆ユーザがこのページを開くようにSEOや広告で誘導
⇒ユーザがページを開いた時(onload)などにソースを実行
⇒型混乱が起こる
function f(arr) {
return arr[20]; // JIT は「範囲内」と誤解し bounds check を消す
}
for (let i = 0; i < 10000; i++)
f([1,2,3,4,5,6,7,8,9,10]); // 長さ10で訓練
// → JIT「この配列は長さ10固定!要素10個、FastElements!」と確信
// ここで
f([1, 2]); // 長さ2の配列を渡す(危険)
// 新しい構造体に対して確信した構造体と同じ方式でアクセスしてしまう
// JITのアクセス
[map][elements ptr][length][0][1][2]...[9]
// 実体
[map][elements ptr][length][0][1]
上記により、新しい構造体に対して確信した構造体と同じ方式でアクセスするため
本来の配列データの外側を読み書きし始める(OOB/Out-of-Bounds Read)
その後の流れ
範囲外のデータを読み込み(OOBRead)
👇
ポインタやJSオブジェクト内部レイアウトなどの情報漏洩
👇
範囲外の重要データ(配列のポインタや長さの情報)を書き換え(OOBWrite)
👇
任意アドレスを配列の一部として扱う
👇
JITが生成した機械コードのアドレスを探す
👇
JITの機械コードを書き換える
👇
RCEの完成
・任意コマンド実行(OSアクセス)
・任意ファイル読み書き
・乗っ取り
調査後の感想
今回の攻撃の入り口が「Webページをクリックするだけ」ということを知り、セキュリティに対する意識が強まりました。怖すぎますね、、。
また、何かふと耳に入った情報を調べて投稿していきます!