安全严重性:高危。CWE 908 和 CWE 200。已在 Firefox 154 中修复。Bugzilla 2057808。可从普通网页通过 @font-face 触达。
Firefox 在使用前会通过 OTS 对 Web 字体进行净化。三个缺陷串联起来,使特制字体将未初始化的进程堆内容交还给页面。仅一次 measureText 调用就能在 64 KB 窗口内以每次约两个字节的方式将其读出。
OTS 输出流通过 moz_xrealloc 增长,而该函数从不将内存清零。它的 Seek 接受任何不超过分配大小的位置,也从不将间隙填零。forget 将缓冲区大小设为访问到的最高偏移量。因此,最后一次写入与前向 Seek 之间的任何间隙,都会被带着旧堆内容交给调用方。
带有较大 nonDefaultUVSOffset 的 cmap 格式 14 子表会让序列化器向前 Seek,并将间隙留在生成的字体中。配套的格式 4 子表在最后一段带有奇特的 id_range_offset,被原样输出。字形查找的边界检查使用的是整个 cmap 的剩余长度,而非该子表本身的长度。因此,跳入相邻子表区域的访问能够通过检查。
MapCharToGlyphFormat4 落到特制段上,并返回从间隙中读取的字形 ID。其 hmtx 前进量可直接从 canvas 中测量。

pip install fonttools brotli
python3 make_poc_font.py # builds poc.woff
# serve this folder and open poc.html
poc.html 在每次读取时打印 U+FFFF 的前进宽度。每个值对应一个从间隙中读取的字形 ID。要观察到非零的未初始化字节,请使用 MSan 或带有垃圾填充的 mozjemalloc 构建版本。Windows 上通过 DWrite 受影响,macOS 上通过 CoreText 受影响。OTS 在进程内运行,未经过沙箱隔离。
一种可由 Web 控制且可重复发生的未初始化进程堆泄露。它可能揭示指针或机密信息。
两项修改。其中任何一项都能打断该利用链。将 OTS 输出流中新分配的范围清零。检查格式 4 子表的长度,使查找不能以整个 cmap 的剩余部分作为边界。Firefox 已同时合入这两项修改。
Abdulaziz Alasaiqah · https://azoz.my/writeups.html