
Exploit for CVE-2019-9810 Firefox on Windows 64-bit.
CVE-2019-9810 — это уязвимость, обнаруженная и использованная на Pwn2Own 2019 Ричардом Чжу и Аматом Камой. Она затрагивает JavaScript-движок Mozilla, Spidermonkey, и была использована для компрометации рендерера.
Проблема была исправлена в mfsa2019-09 около двух месяцев назад.
В двух словах, ошибка позволяет проверке границ быть признанной избыточной и оптимизированной, что позволяет коду обращаться к памяти за пределами границ. Сама проблема находится в этапе анализа псевдонимов (Alias Analysis) конвейера Ion. Нижеприведенное изображение иллюстрирует последствие ошибки в этапе оптимизации GVN (оптимизация проверки границ) и служит хорошим резюме, если вы ищете именно это:

Если вы хотите узнать об этом больше, я рекомендую взглянуть на A journey into IonMonkey: root-causing CVE-2019-9810.
Репозиторий содержит код эксплойта, а также набор инструментов, которые я ранее разработал для своих эксплойтов blazefox. Я просто их обновил и заставил работать с BigInt. В результате эксплойт предполагает, что поддержка BigInt включена в Firefox, что можно сделать, переключив javascript.options.bigint в about:config.

Эксплойт был протестирован на Windows RS5 64-bit и нацелен на пользовательскую сборку Firefox, так что не удивляйтесь, если потребуется немного работы, чтобы заставить его работать в другом месте :). Однако если вы просто хотите запустить эксплойт без компиляции, я подготовил упакованный браузер, который загрузил в release/firefox-68.0a1.en-US.win64.7z. Он также включает оболочку js.exe и приватную символьную информацию для js.exe, firefox.exe и xul.dll.
Процесс эксплуатации очень похож на мой предыдущий эксплойт kaizen.js, как упоминалось выше. Он передает выполнение на ReflectiveLoader рефлексивной DLL, которая реализует пейлоад:
js.exe, он просто заспамивает stdout сообщением PWN, запускает калькулятор и завершает работу.Firefox.exe. Для этого эксплойт на JavaScript передает указатель на копию рефлексивной DLL, и рефлексивная DLL отображает его в других процессах. После этого он создает удаленный поток в загрузчике и засыпает. Причина в том, что эксплойт в текущем состоянии довольно грязный и не реализует продолжение работы процесса. Хотя, на данный момент я не думаю, что это потребовало бы много работы. Возможно, я когда-нибудь это сделаю :-).Firefox.exe, он делает inline-хук функции xul!nsJSUtils::ExecutionContext::Compile. Эта функция выполняется, когда скрипты должны быть выполнены движком JavaScript; так что это звучало как достаточно хороший кандидат для моих целей. Хукированная версия просто добавляет в начало произвольный JavaScript-пейлоад по нашему выбору.В реальности есть множество более тонких деталей, не описанных выше, поэтому если вы заинтересованы, приглашаю вас найти истину и прочитать исходники :).
Чтобы собрать пейлоад, просто выполните nmake из командной строки VS 2017 x64.
CVE-2019-9810\payload>nmake
Microsoft (R) Program Maintenance Utility Version 14.16.27027.1
Copyright (C) Microsoft Corporation. All rights reserved.
ml64 /c src\trampoline.asm
Microsoft (R) Macro Assembler (x64) Version 14.16.27027.1
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: src\trampoline.asm
if not exist .\bin mkdir bin
type injected-script.js > src\injected-script.h
cl /O1 /nologo /W3 /D_AMD64_ /DWIN_X64 /DREFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN /Febin\payload.dll src\ReflectiveLoader.c src\ReflectiveDll.cc trampoline.obj /link /DLL /nologo /debug:full /PDBALTPATH:%_PDB%
ReflectiveLoader.c
Generating Code...
Compiling...
ReflectiveDll.cc
Generating Code...
Creating library bin\payload.lib and object bin\payload.exp
python jsify_payload.py bin\payload.dll
move payload.js ..
1 file(s) moved.
del *.obj
del src\injected-script.h
if exist .\bin del bin\*.exp bin\*.ilk bin\*.lib
Это создает файлы payload.dll / payload.pdb в каталоге payload\bin. А также файл JavaScript с именем payload.js, который встраивает DLL в Uint8Array со смещением до загрузчика.
Я написал этот эксплойт для локальной сборки Windows, синхронизированной с идентификатором ревизии 2abb636ad481768b7c88619080cf224b2c266b2d (если вы не хотите собирать его самостоятельно, я выложил свою сборку здесь: release/firefox-68.0a1.en-US.win64.7z):
$ hg --debug id -i
2abb636ad481768b7c88619080cf224b2c266b2d
И я использовал следующий файл mozconfig:
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
ac_add_options --disable-crashreporter
ac_add_options --enable-debug-symbols
. "$topsrcdir/build/mozconfig.clang-cl"
. "$topsrcdir/build/mozconfig.lld-link"
# Use the clang version in .mozbuild
CLANG_LIB_DIR="$(cd ~/.mozbuild/clang/lib/clang/*/lib/windows && pwd)"
export LIB=$LIB:$CLANG_LIB_DIR
ac_add_options --enable-js-shell
ac_add_options --enable-jitspew
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff64
Хотя для моих целей это было нормально, я не уверен, что xul!nsJSUtils::ExecutionContext::Compile является идеальной функцией для вставки произвольных скриптов. Я уверен, что, потратив больше времени на понимание того, как работает фронтенд xul, можно найти лучшую точку для хука.
Еще пара направлений, которые я обнаружил после написания эксплойта, обсуждаются в записи Bugzilla: 982974 (System principal for the JavaScript interpreter и security.turn_off_all_security_so_that_viruses_can_take_over_this_computer). Было бы интересно посмотреть, насколько это все еще актуально для Firefox сегодня.
Возможно, кто-то уже исследовал эту тему, и я полностью это пропустил. В любом случае, не стесняйтесь пинговать меня с любыми отзывами!
Еще одна интересная вещь — исследовать, есть ли какой-либо способ реализовать механизм персистентности в браузере. Я совсем не исследовал эту область, но это было бы довольно круто :).