Skip to content

Blink UAF 防御:CSSFontFeatureValuesMap 迭代器生命周期与浏览器沙箱加固(CVE-2026-2441) ​

1. 威胁模型与漏洞根因回顾 ​

CVE-2026-2441 位于 Chromium Blink 渲染引擎的 CSSFontFeatureValuesMap 迭代器实现中。漏洞根因在于 FontFeatureValuesMapIterationSource 在构造时仅保存底层 FontFeatureAliases(WTF::HashMap)的原始指针 const FontFeatureAliases* aliases_。当页面脚本在迭代过程中交替调用 map.delete() 与大量 map.set() 触发 HashMap rehash 时,旧桶数组被释放而迭代器指针悬空,随后 FetchNextItem() 访问已释放内存触发 Use-After-Free(UAF)。攻击者可结合堆整理(heap grooming)与 V8 对象混淆进一步尝试代码执行或配合沙箱逃逸链突破渲染进程边界。

2. 核心修复与缓解策略 ​

防线层级控制措施作用机制目标基线
上游代码补丁迭代器改为值拷贝/移动持有消除 rehash 导致的跨容器指针悬空Chrome/Edge/Brave >= 145.0.7632.75(Linux >= 144.0.7559.75)
容器与内存安全启用 PartitionAlloc + MiraclePtr (raw_ptr)将悬空解引用转为受控崩溃或隔离Chromium 官方默认开启
沙箱与缓解Renderer Sandbox + Site Isolation + CET/CFI阻断 UAF 后向任意读写和进程外提权全端强制启用 --site-per-process 且禁用 --no-sandbox
企业终端治理MDM / GPO 强制自动更新与重启提醒消除长周期未重启浏览器导致的旧内核驻留补丁发布后 48 小时内覆盖
威胁监测监控 @font-feature-values 异常循环与 Renderer Crash识别利用尝试与堆喷射特征EDR / Crashpad 遥测告警

源码层面补丁原理(63f3cb48) ​

修复前后的核心差异在于将迭代源中的原始指针替换为独立值副本:

cpp
// 加固后实现:FontFeatureValuesMapIterationSource 持有独立的 FontFeatureAliases 副本
class FontFeatureValuesMapIterationSource final
    : public PairSyncIterable<CSSFontFeatureValuesMap>::IterationSource {
 public:
  FontFeatureValuesMapIterationSource(const CSSFontFeatureValuesMap& map,
                                      FontFeatureAliases aliases)
      : map_(map), aliases_(std::move(aliases)), iterator_(aliases_.begin()) {}

 private:
  Member<const CSSFontFeatureValuesMap> map_;
  const FontFeatureAliases aliases_;  // 值语义快照,原 map rehash 不影响副本内存
  FontFeatureAliases::const_iterator iterator_;
};

对于自研或二开 Blink 内核、CEF(Chromium Embedded Framework)与 Electron 应用,若暂无法升级完整内核,应回port 提交 63f3cb4864c64c677cd60c76c8cb49d37d08319c,并在代码审查中禁止任何 WebIDL 迭代器直接持有 WTF::HashMap* / WTF::Vector* 裸指针。

防御工作流 ​

  1. 资产版本盘点:收集终端 Chrome、Edge、Brave 及内置 Electron/CEF 组件版本号,对照修复基线标记受影响资产。
  2. 源码与构建补丁核验:对自编译 Chromium/CEF 确认 FontFeatureValuesMapIterationSource 已包含值拷贝补丁,并启用 enable_backup_ref_ptr_support = true(MiraclePtr)与 CFI。
  3. 运行参数与策略加固:核查浏览器启动参数及企业组策略,确保 Renderer 沙箱、Site Isolation、ASLR 与硬件控制流保护未被关闭。
  4. 行为告警与回归验证:部署前端 WAF / 代理内容检查及终端 Crashpad 监控,最后运行版本比对与安全配置检查脚本确认达标。

3. 自动化版本基线与运行参数核查脚本 ​

以下 Python 脚本用于批量核查桌面浏览器或 Electron/CEF 导出版本清单是否达到 CVE-2026-2441 修复基线,并检查启动参数是否误关沙箱:

python
#!/usr/bin/env python3
"""CVE-2026-2441 Chromium/Blink 版本基线与启动参数核查工具。"""

from dataclasses import dataclass
from typing import Iterable


@dataclass(frozen=True)
class BrowserAsset:
    product: str
    platform: str
    version: str
    flags: tuple[str, ...] = ()


PATCHED_BASELINES = {
    ("chrome", "linux"): (144, 0, 7559, 75),
    ("chrome", "windows"): (145, 0, 7632, 75),
    ("chrome", "macos"): (145, 0, 7632, 75),
    ("edge", "windows"): (145, 0, 7632, 75),
    ("brave", "windows"): (145, 0, 7632, 75),
}
UNSAFE_FLAGS = ("--no-sandbox", "--disable-site-isolation-trials", "--disable-seccomp-filter-sandbox")


def parse_version(ver: str) -> tuple[int, int, int, int]:
    parts = [int(x) for x in ver.strip().split(".")]
    if len(parts) != 4:
        raise ValueError(f"invalid version format: {ver}")
    return tuple(parts)  # type: ignore[return-value]


def evaluate_assets(assets: Iterable[BrowserAsset]) -> list[dict[str, object]]:
    results = []
    for asset in assets:
        key = (asset.product.lower(), asset.platform.lower())
        baseline = PATCHED_BASELINES.get(key, (145, 0, 7632, 75))
        ver_tuple = parse_version(asset.version)
        flagged = [f for f in asset.flags if f in UNSAFE_FLAGS]
        compliant = (ver_tuple >= baseline) and not flagged
        results.append({
            "product": asset.product,
            "platform": asset.platform,
            "version": asset.version,
            "required": ".".join(map(str, baseline)),
            "unsafe_flags": flagged,
            "status": "PASS" if compliant else "ACTION_REQUIRED",
        })
    return results


if __name__ == "__main__":
    sample_inventory = [
        BrowserAsset("chrome", "windows", "145.0.7632.75", ("--site-per-process",)),
        BrowserAsset("chrome", "linux", "144.0.7559.60", ()),
        BrowserAsset("edge", "windows", "145.0.7632.80", ("--no-sandbox",)),
    ]
    report = evaluate_assets(sample_inventory)
    for row in report:
        print(row)
    assert report[0]["status"] == "PASS"
    assert report[1]["status"] == "ACTION_REQUIRED"
    assert report[2]["status"] == "ACTION_REQUIRED"

企业策略与沙箱加固配置示例(Chrome/Edge JSON Policy) ​

json
{
  "AutoUpdateCheckPeriodMinutes": 60,
  "RelaunchNotification": 2,
  "RelaunchNotificationPeriod": 86400000,
  "SitePerProcess": true,
  "SandboxExternalProtocolBlocked": true,
  "RendererCodeIntegrityEnabled": true
}

验证与判定标准 ​

检查项判定为已加固(PASS)判定为存在风险(FAIL)验证方式
浏览器版本Windows/macOS >= 145.0.7632.75,Linux >= 144.0.7559.75低于修复版本或未重启生效新内核evaluate_assets 脚本与 chrome://version
迭代器实现(自研构建)FontFeatureValuesMapIterationSource 持有值副本 aliases_仍保存 const FontFeatureAliases* 裸指针源码审查 63f3cb48 补丁存在
沙箱与隔离参数无 --no-sandbox,SitePerProcess 与 CFI/ASLR 启用存在 --no-sandbox 或关闭 Site Isolation进程命令行与企业策略核查
回归页面行为迭代期间调用 delete()/set() 完成全部初始条目且进程不崩溃渲染进程出现 STATUS_ACCESS_VIOLATION / SIGSEGV受控测试页观测 Crashpad 与 console 输出

MCP 工具映射 ​

防御步骤MCP 工具说明
漏洞与防御知识检索kb_router按 CVE-2026-2441 / Blink UAF / sandbox 检索配对攻防文档
读取配对攻击文档kb_read_file读取 ctf-website/09-cve/01-browser-sandbox-escape 核对触发条件
查看防御文档目录kb_catalog确认 09-cve 板块中关联浏览器 CVE 防护条目

Apache-2.0 · For authorized learning and defensive research only · Disclaimer