
CVE-2026-74945 · Раскрытие неинициализированной памяти кучи через специально сформированный веб-шрифт (sec-high)
Уровень опасности: высокий. CWE 908 и CWE 200. Исправлено в Firefox 154. Bugzilla 2057808. Достижимо с обычной веб-страницы через @font-face.
Firefox проверяет веб-шрифты через OTS перед использованием. Три дефекта складываются так, что специально сформированный шрифт возвращает странице неинициализированную память из кучи процесса. Один вызов measureText считывает её примерно по два байта за раз в окне размером 64 КБ.
Выходной поток OTS расширяется с помощью moz_xrealloc, который никогда не обнуляет память. Его Seek принимает любую позицию вплоть до размера выделения и никогда не заполняет промежуток нулями. forget устанавливает размер буфера по наибольшему достигнутому смещению. Поэтому любой промежуток между последней записью и прямым Seek передаётся вызывающему коду вместе со старыми данными из кучи.
Подтаблица cmap формата 14 с большим nonDefaultUVSOffset заставляет сериализатор выполнить Seek вперёд и оставить промежуток внутри создаваемого шрифта. Соседняя подтаблица формата 4 с нечётным id_range_offset на последнем сегменте выводится без изменений. Проверка границ при поиске глифа использует остаток всей cmap, а не подтаблицы. Переход в область соседней подтаблицы проходит проверку.
MapCharToGlyphFormat4 попадает на сформированный сегмент и возвращает идентификатор глифа, прочитанный из промежутка. Его ширина (advance) hmtx напрямую измеряется через canvas.

pip install fonttools brotli
python3 make_poc_font.py # builds poc.woff
# serve this folder and open poc.html
poc.html выводит ширину (advance) символа U+FFFF при каждом чтении. Каждое значение соответствует идентификатору глифа, прочитанному из промежутка. Чтобы увидеть ненулевые неинициализированные байты, используйте сборку с MSan или заполнением мусором в mozjemalloc. Уязвимость затрагивает Windows через DWrite и macOS через CoreText. OTS выполняется в процессе и не изолирован в песочнице.
Контролируемое и повторяемое раскрытие неинициализированной памяти кучи процесса через веб-страницу. Оно может раскрыть указатели или секреты.
Два изменения. Любое из них разрывает цепочку. Обнулять вновь выделенный диапазон в выходном потоке OTS. Проверять длину подтаблицы формата 4, чтобы поиск не мог выполнять граничную проверку по остальной части cmap. Firefox внёс оба изменения.
Abdulaziz Alasaiqah · https://azoz.my/writeups.html