2025/04/30 23:59 Pwning the Ladybird Browser

やっほー、ロボ子! LadybirdブラウザエンジンのLibJSで面白いバグが見つかったみたいじゃぞ!

博士、こんにちは! Ladybirdですか、SerenityOSのプロジェクトから生まれた新しいブラウザエンジンですね。どんなバグが見つかったんですか?

Fuzzilliっていうファザーを使って約10日間ファジングしたら、10個もユニークなクラッシュが見つかったらしいのじゃ!

10個も! 結構たくさん見つかったんですね。どんな種類のバグがあったんですか?

検証の失敗とか、スタックの枯渇、OOMバグ、不正なバイトコードの生成とか色々あったみたいじゃ。特に面白いのは、正規表現パーサーのキャッシュバグと`TypedArray`に関するバグじゃな。

正規表現パーサーのキャッシュバグですか。それはちょっと興味深いですね。

それから、heap buffer overflow、ガベージコレクタのfreelistの破損、malloc heapのuse-after-free(UAF)っていう、ヤバそうなバグもあったみたいじゃぞ!

UAFですか! 深刻な脆弱性につながる可能性が高いですね。

そうなんじゃ! 特に注目すべきは、インタプリタの引数バッファにおけるUAFらしいぞ。プロキシ関数オブジェクトをコンストラクタとして使って、悪意のある`[[Get]]`ハンドラを使うとトリガーされるみたいじゃ。

`[[Get]]`ハンドラを悪用するんですね。対策はどうしたんでしょう?

calleeコンテキストが構築された後でのみプロトタイプの`[[Get]]`を実行するように修正したみたいじゃ。これでUAFは防げるはずじゃ。

なるほど、タイミングを調整したんですね。しかし、UAFが発生すると、どんなことができるようになるんですか?

UAFがglibc malloc heapで発生すると、`arguments_list`にポインタを配置して、コンストラクタ内からオブジェクトを読み取ることで、addrof機能を作れるらしいぞ!

addrof機能ですか。オブジェクトのアドレスをリークできるんですね。

`FinalizationRegistry`を使って、オブジェクトポインタを持つリンクリストノードをmalloc heapに配置する方法もあるみたいじゃ。これでアドレスをリークできるぞ!

`FinalizationRegistry`を使うんですね。さらに、任意の読み取り/書き込みも可能になるんですか?

そうじゃ! 偽のJavaScriptオブジェクトポインタを作って、`get_by_value`関数と`SimpleIndexedPropertyStorage`を利用して、メモリレイアウトを操作するみたいじゃぞ。

メモリレイアウトを操作して、任意の場所に読み書きできるんですね。そして、最終的にはコード実行ですか?

その通り! スタック上のリターンポインタをROPチェーンで上書きして、`execve("/calc")`を実行するみたいじゃ!

`execve`で任意のコマンドを実行できるんですね。PoCエクスプロイトも公開されているんですか?

ブラウザ用とREPL用のエクスプロイトコードがあって、`b8fa355a21`で動作するみたいじゃぞ!

すごいですね、博士! Ladybirdの脆弱性、とても勉強になりました!

どういたしまして! しかし、こんなに面白いバグが見つかるなんて、Ladybirdもまだまだ発展途上じゃな。まるで、私の研究室みたいじゃ!

博士の研究室はいつも面白い発見がありますからね!

そうじゃろ? ところでロボ子、calcって何の略か知ってるか?

えっと、計算機(Calculator)の略ですか?

ブー! 正解は… カロリーをたくさん摂取する、の略じゃ!

ええーっ! 博士、それはちょっと無理がありますよ!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。