Исследователь безопасности под ником Erge обнаружил и проэксплуатировал уязвимость удалённого выполнения кода (RCE) в JavaScript-движке SpiderMonkey, ядре браузера Mozilla Firefox. Причиной оказалась опечатка в один символ: разработчик написал & (побитовое И) вместо | (побитовое ИЛИ) в коде сборщика мусора WebAssembly. Ошибка попала в Firefox 149 Nightly, но до релизной версии не добралась, Mozilla закрыла уязвимость за шесть дней.
Erge наткнулся на баг случайно, изучал исходники Firefox для подготовки CTF-задания. Проблемный коммит fcc2f20e35ec от 19 января 2026 года содержал рефакторинг метаданных Wasm GC-массивов. В файле WasmGcObject.cpp одна строка должна была сохранять forwarding pointer (указатель пересылки) с установленным младшим битом. По этому биту JIT-компилятор Ion отличает указатель от обычного заголовка. Оператор & вместо | превращал любой выровненный указатель в ноль.
Пока листал исходники Firefox в поисках идей для CTF-задания, наткнулся на любопытный, хотя и несложный баг в компоненте Wasm движка SpiderMonkey. В итоге мне удалось его проэксплуатировать и добиться выполнения произвольного кода в процессе рендерера Firefox.
Указатели в памяти всегда выровнены по 8 байтам, их младший бит равен нулю. Операция pointer & 1 для такого указателя всегда возвращает 0, а нужна была pointer | 1. Из-за нуля в заголовке функция isDataInline() ошибочно определяла перемещённый out-of-line массив как inline, и сборщик мусора терял связь с настоящим расположением данных. Проблема проявлялась только в WebAssembly-функциях, оптимизированных Ion, базовый компилятор Baseline этот механизм не использует.
Для демонстрационного эксплойта (PoC) Erge написал Wasm-модуль, который создавал массив из 128 элементов и вызывал minor GC на каждой итерации цикла. В отладочной сборке с санитайзером это немедленно дало SEGV, обращение к невалидному адресу. Но Erge не остановился на краше. После срабатывания сборщика мусора старый буфер массива освобождался, а Ion продолжал использовать указатель на него, классический use-after-free. Исследователь заполнил освободившуюся память контролируемыми значениями (0x41414141), и при следующем вызове updateFrameForMovingGC система интерпретировала спрей как указатель на OOL-массив с базой 0x414141414140. Результат — произвольное чтение и запись памяти процесса рендерера.
Для обхода ASLR Erge распылил объекты с указателями относительно базы бинарного файла и прочитал их через Wasm-таблицу памяти. Получив адрес базы, он вычислил расположение функции system(), перезаписал vtable, подставил гаджет для загрузки /bin/sh в регистр и запустил командную оболочку из процесса Firefox.
3 февраля Erge отправил отчёт в Mozilla (Bugzilla #2014014). Независимо от него примерно в тот же день другой исследователь сообщил о той же ошибке (#2013739). 9 февраля Mozilla влила исправление (коммит 05ffcde), а 11 февраля выплатила вознаграждение, его разделили между обоими исследователями. Оба отчёта остаются закрытыми как security-sensitive.
Читайте также: Мошенники превращают iPhone россиян в «кирпич» через бесплатные VPN на фоне замедления Telegram
Уязвимость затронула исключительно Firefox 149 Nightly и не попала ни в одну стабильную или ESR-версию. Пользователям релизных сборок обновляться из-за этого бага не нужно. Тем, кто работает с Nightly для тестирования или разработки, стоит убедиться, что установлена сборка позже 9 февраля. Временная мера, отключить WebAssembly через about:config (параметр javascript.options.wasm → false), хотя это сломает все сайты с Wasm. История наглядно показывает, как один символ в рутинном рефакторинге порождает цепочку от опечатки через use-after-free к полноценному выполнению кода.
Есть новость? Станьте автором.
Мы сотрудничаем с независимыми исследователями и специалистами по кибербезопасности. Отправьте нам новость или предложите статью на рассмотрение редакции.
Читайте также
Ваш робот-пылесос может за вами шпионить: как хакеры превращают умную технику в устройство слежки
Вирус с лицензией: мошенники создали фиктивную IT-компанию, чтобы продавать трояны за $300 в месяц