
Exploit für CVE-2019-9810 Firefox unter Windows 64-bit.
CVE-2019-9810 ist eine Schwachstelle, die auf der Pwn2Own 2019 von Richard Zhu und Amat Cama gefunden und ausgenutzt wurde. Es betrifft Mozillas JavaScript-Engine Spidermonkey und wurde verwendet, um den Renderer zu kompromittieren.
Das Problem wurde vor etwa zwei Monaten in mfsa2019-09 behoben.
Im Kern ermöglicht der Fehler, dass eine Bereichsprüfung als redundant erkannt und wegoptimiert wird, sodass Code auf Speicher außerhalb der Grenzen zugreifen kann. Das Problem selbst liegt im Alias-Analyse-Durchlauf der Ion-Pipeline. Das folgende Bild verdeutlicht die Konsequenz des Fehlers im GVN-Optimierungsdurchlauf (die Bereichsprüfung wird wegoptimiert) und dient als gute Zusammenfassung, falls Sie danach suchen:

Wenn Sie jedoch mehr darüber erfahren möchten, empfehle ich einen Blick auf A journey into IonMonkey: root-causing CVE-2019-9810.
Das Repository enthält den Exploit-Code sowie eine Reihe von Tools, die ich zuvor für meine blazefox-Exploits entwickelt hatte. Ich habe sie nur aufpoliert und mit BigInt kompatibel gemacht. Daher geht der Exploit davon aus, dass die Unterstützung für BigInt in Firefox aktiviert ist, was Sie durch Umschalten von javascript.options.bigint in about:config tun können.

Der Exploit wurde unter Windows RS5 64-Bit getestet und zielt auf einen benutzerdefinierten Build von Firefox ab, seien Sie also nicht überrascht, wenn etwas Arbeit nötig ist, um ihn woanders zum Laufen zu bringen :-). Wenn Sie jedoch einfach den Exploit ausführen möchten, ohne etwas zu kompilieren, habe ich einen gepackten Browser vorbereitet, den ich in release/firefox-68.0a1.en-US.win64.7z hochgeladen habe. Er enthält auch die js.exe-Shell sowie private Symbolinformationen für js.exe, firefox.exe und xul.dll.
Der Ausnutzungsprozess funktioniert ähnlich wie bei meinem vorherigen kaizen.js-Exploit, wie oben erwähnt. Er verteilt die Ausführung auf den ReflectiveLoader einer reflektiven DLL, die die Payload implementiert:
js.exe aufgerufen wird, spammt sie einfach stdout mit PWN, startet einen Taschenrechner und beendet sich.Firefox.exe-Prozesse. Dazu übergibt der JavaScript-Exploit einen Zeiger auf die Kopie der reflektiven DLL, und die reflektive DLL mapped sie in die anderen Prozesse. Sobald dies abgeschlossen ist, erstellt es einen Remote-Thread auf dem Reflective Loader und macht ein Nickerchen. Der Grund dafür ist, dass der Exploit im aktuellen Zustand ziemlich schmutzig ist und keine Prozessfortsetzung implementiert. Allerdings glaube ich nicht, dass es viel Arbeit wäre. Vielleicht komme ich dazu :-).Firefox.exe-Prozessen ausgeführt wird, hakt sie die Funktion xul!nsJSUtils::ExecutionContext::Compile per Inline-Hook ein. Diese Funktion wird ausgeführt, wenn Skripte von der JavaScript-Engine ausgewertet werden müssen; das erschien also wie ein guter Kandidat für das, was ich tun wollte. Die gehackte Version stellt einfach eine beliebige JavaScript-Payload unserer Wahl voran.In Wirklichkeit gibt es eine Reihe subtilerer Details, die oben nicht beschrieben werden. Wenn Sie interessiert sind, sind Sie eingeladen, die Wahrheit zu finden und die Quellen zu lesen :-).
Um die Payload zu erstellen, müssen Sie lediglich nmake von einer VS 2017 x64-Eingabeaufforderung aus ausführen.
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
Dies erstellt eine payload.dll / payload.pdb-Datei im payload\bin-Verzeichnis. Sowie eine JavaScript-Datei namens payload.js, die die DLL in einem Uint8Array mit dem Offset zum Loader einbettet.
Ich habe diesen Exploit gegen einen lokalen Windows-Build geschrieben, der mit der folgenden Revisions-ID synchronisiert ist: 2abb636ad481768b7c88619080cf224b2c266b2d (wenn Sie ihn nicht selbst bauen möchten, habe ich meinen Build hier hochgeladen: release/firefox-68.0a1.en-US.win64.7z):
$ hg --debug id -i
2abb636ad481768b7c88619080cf224b2c266b2d
Und ich habe die folgende mozconfig-Datei verwendet:
. "$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
Obwohl es für meinen Zweck in Ordnung war, bin ich mir nicht sicher, ob xul!nsJSUtils::ExecutionContext::Compile die perfekte Funktion zum Einfügen beliebiger Skripte ist. Ich bin sicher, dass man mit etwas mehr Zeit, um zu verstehen, wie das xul-Frontend funktioniert, einen besseren Hooking-Punkt finden könnte.
Einige weitere Ansätze, die ich nach dem Schreiben des Exploits entdeckt habe, werden in diesem Bugzilla-Eintrag diskutiert: 982974 (Systemprincipal für den JavaScript-Interpreter und security.turn_off_all_security_so_that_viruses_can_take_over_this_computer). Es wäre interessant zu sehen, wie viel davon heute noch für Firefox relevant ist.
Vielleicht hat jemand dieses Thema bereits erforscht und ich habe es völlig verpasst. In jedem Fall können Sie mich jederzeit mit Feedback kontaktieren!
Eine weitere interessante Sache wäre zu untersuchen, ob es eine Möglichkeit gibt, einen Persistenzmechanismus im Browser zu haben. Ich habe diesen Bereich überhaupt nicht erforscht, aber das wäre ziemlich cool :-).