このディレクトリには、Firefoxのフォント処理における未初期化メモリの情報漏えいに関する、誠実な再現パッケージが含まれています。細工された @font-face フォントがOTSの出力ストリームを未初期化ヒープの隙間へと誘導し、通常のコンテンツがその隙間のバイト列をcanvasの measureText APIを通じて読み戻します。これはローカルにダウンロードした脆弱なFirefoxビルドに対して、合成データのみを用いて実行することを想定しています。稼働中のシステムや第三者システムには一切触れません。
対応するPoCリポジトリ: https://github.com/defineid/Palimpsest
解説記事: このポートフォリオ内の writeup-font-cmap-leak.html。
| 項目 | 値 |
|---|---|
| CVE | CVE-2026-74945 |
| コンポーネント | Core / Graphics: Text |
| 分類 | 未初期化メモリの情報漏えい (CWE-908 · CWE-200) |
| 深刻度 | sec-high (Web経由で到達可能なメモリ情報漏えい) |
| 修正済み | Firefox 154 · ESR 140.14 |
| バグ | bugzilla.mozilla.org/show_bug.cgi?id=2057808 |
| 操作 | なし · ページ読み込みのみ |
Firefoxは使用前にOTSを通じてWebフォントをサニタイズします。3つの独立した欠陥が重なり合うことで、細工されたフォントがサニタイズ後の出力内に未初期化ヒープの隙間を残し、コンテンツがそれを読み戻せるようになります。
moz_xrealloc) で成長します。nonDefaultUVSOffset を持つ cmap フォーマット14サブテーブルにより、OTSがサニタイズ済みフォントを再シリアライズする際に出力ストリームを前方へシークさせます。書き込まれたバイト列とシーク先の間のスキップされた区間は、未初期化ヒープを抱えたまま呼び出し元に渡され、forget() は到達した最大オフセットまでバッファのサイズを設定します。cmap テーブル全体の残りに対して境界チェックを行うため、idRangeOffset がフォーマット4データの末尾を越えてしまうセグメントでもチェックを通過し、隣接するサブテーブルの未初期化バイト列を読み取ってしまいます。細工されたフォントは、最後のセグメント (0xFFFF) が奇妙で範囲を越える idRangeOffset を使用するフォーマット4サブテーブルと、大きな nonDefaultUVSOffset を持つフォーマット14サブテーブルを組み合わせ、さらに maxp.numGlyphs = 65535 とグリフIDごとに異なる hmtx のアドバンス (アドバンス == グリフID) を備えています。したがってU+FFFFを測定すると、未初期化の隙間から読み取られたグリフIDに解決され、そのアドバンス幅はスクリプトから読み取り可能で、約64 KBのウィンドウにわたり測定1回あたり約2バイトのヒープを漏えいします。
通常のWebページが @font-face を通じて細工されたフォントを配信し、ctx.measureText("") を呼び出します。クリック、権限、拡張機能、設定変更は一切不要です。OTSはプロセス内で動作し、サンドボックス化されたライブラリには含まれないため、漏えいするバイト列はポインタや秘密情報を含む可能性のあるコンテンツプロセスのヒープです。
| ファイル | 目的 |
|---|---|
make_font.py | 細工されたフォント leak.otf と leak.woff をビルドします。 |
trigger.html | @font-face でフォントを読み込み、U+FFFFのアドバンスを measureText 経由で読み戻すだけのページです。 |
https://ftp.mozilla.org/pub/firefox/releases/140.9.0esr/ から、一致するプラットフォーム向けビルドをダウンロードしてください。pip install fonttools brotli
python3 make_font.py # writes leak.otf and leak.woff in this directory
次に、脆弱なビルドで trigger.html を、file:// パスまたは自分で管理するローカル静的サーバーから開き、Measure をクリックします。
.notdef) に解決され、アドバンスは 0 になります。出力ストリームがゼロ埋めされ、format-4 ルックアップが自身のサブテーブル内に制限されるため、ギャップは漏洩しません。make_font.py はここで fontTools 4.63.0 を用いて実行され、leak.otf (393816 バイト) と leak.woff (132372 バイト) を生成しました。生成されたフォントは生バイトから再パースされ、すべての細工された要素が確認されました: maxp.numGlyphs = 65535、hhea.numberOfHMetrics = 65535、グリフ ID ごとに異なる hmtx アドバンス (アドバンス == グリフ ID)、2 つの cmap サブテーブル (platform 3 encoding 1 format 4、および platform 0 encoding 5 format 14)、format-4 の最終セグメント endCode = 0xFFFF と奇数のオーバーランする idRangeOffset = 0x4001、そして format-14 の nonDefaultUVSOffset = 0x8000。trigger.html をご自身で実行してください。このパッケージは細工された入力と読み戻し経路を示すものであり、武器化されたエクスプロイトではなく、制御されたコード実行プリミティブも含みません。これは、著者自身が報告し既に修正済みの CVE に関する解説のために、合成された自己生成のフォントデータを用いてローカルにダウンロードしたビルドを対象としています。稼働中または第三者のサービスを攻撃するものではありません。