
Exploit for CVE-2019-9810 Firefox on Windows 64-bit.
CVE-2019-9810 est une vulnérabilité découverte et exploitée lors du Pwn2Own 2019 par Richard Zhu et Amat Cama. Elle affecte le moteur JavaScript de Mozilla, Spidermonkey, et a été utilisée pour compromettre le processus de rendu.
Le problème a été corrigé dans mfsa2019-09 il y a environ deux mois.
En résumé, le bogue permet à une vérification des limites d'être jugée redondante et optimisée, ce qui permet au code d'accéder à une mémoire hors limites. Le problème réside dans l'étape d'analyse des alias (Alias Analysis) du pipeline d'Ion. L'image ci-dessous illustre la conséquence du bogue dans l'étape d'optimisation GVN (la vérification des limites étant optimisée) et constitue un bon résumé si c'est ce que vous cherchez :

Si vous voulez en savoir plus, je vous recommande de jeter un coup d'œil à A journey into IonMonkey: root-causing CVE-2019-9810.
Le dépôt contient le code de l'exploit ainsi qu'un ensemble d'outils que j'avais précédemment développés pour mes exploits blazefox. Je les ai simplement peaufinés et rendus compatibles avec BigInt. Par conséquent, l'exploit suppose que la prise en charge de BigInt est activée dans Firefox, ce que vous pouvez faire en basculant javascript.options.bigint dans about:config.

L'exploit a été testé sur Windows RS5 64 bits et cible une version personnalisée de Firefox, donc ne soyez pas surpris si un peu de travail est nécessaire pour le faire fonctionner ailleurs :). Cependant, si vous souhaitez simplement exécuter l'exploit sans rien compiler, j'ai préparé un navigateur empaqueté que j'ai téléchargé dans release/firefox-68.0a1.en-US.win64.7z. Il inclut également le shell js.exe ainsi que les informations de symboles privés pour js.exe, firefox.exe et xul.dll.
Le processus d'exploitation est très similaire à celui de mon précédent exploit kaizen.js comme mentionné ci-dessus. Il répartit l'exécution sur le ReflectiveLoader d'une dll reflective qui implémente la charge utile (payload) :
js.exe, elle se contente d'envoyer PWN sur stdout, lance une calculatrice et se termine.Firefox.exe. Pour ce faire, l'exploit JavaScript passe un pointeur vers la copie de la dll reflective, et la dll reflective la mappe dans les autres processus. Une fois cela accompli, elle crée un thread distant sur le chargeur réflectif et fait une pause. La raison en est que l'exploit est assez sale dans son état actuel et n'implémente pas la continuation de processus. Cependant, je ne pense pas que ce soit beaucoup de travail. Peut-être que je m'y mettrai un jour :-).Firefox.exe, elle accroche (inline-hook) la fonction xul!nsJSUtils::ExecutionContext::Compile. Cette fonction est exécutée lorsque des scripts doivent être évalués par le moteur JavaScript ; cela semblait donc un bon candidat pour ce que je voulais faire. La version accrochée ajoute simplement un charge utile JavaScript arbitraire de notre choix au début.En réalité, il y a beaucoup de détails plus subtils qui ne sont pas décrits ci-dessus, donc si vous êtes intéressé, vous êtes invité à aller chercher la vérité et à lire les sources :).
Pour construire la charge utile, il suffit d'exécuter nmake depuis une invite 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
Ceci crée un fichier payload.dll / payload.pdb dans le répertoire payload\bin. Ainsi qu'un fichier JavaScript appelé payload.js qui intègre la dll dans un Uint8Array avec le décalage vers le chargeur.
J'ai écrit cet exploit contre une version Windows locale synchronisée avec l'identifiant de révision suivant : 2abb636ad481768b7c88619080cf224b2c266b2d (si vous ne voulez pas la construire vous-même, j'ai téléchargé ma version ici : release/firefox-68.0a1.en-US.win64.7z) :
$ hg --debug id -i
2abb636ad481768b7c88619080cf224b2c266b2d
Et j'ai utilisé le fichier mozconfig suivant :
. "$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
Bien que cela ait convenu à mon objectif, je ne suis pas sûr que xul!nsJSUtils::ExecutionContext::Compile soit la fonction parfaite pour insérer des scripts arbitraires. Je suis sûr qu'en passant plus de temps à comprendre un peu comment fonctionne le front-end de xul, on pourrait trouver un meilleur point d'accrochage.
Quelques autres pistes que j'ai découvertes après avoir écrit l'exploit sont discutées dans cette entrée bugzilla : 982974 (System principal for the JavaScript interpreter and security.turn_off_all_security_so_that_viruses_can_take_over_this_computer). Il serait intéressant de voir dans quelle mesure cela est encore pertinent pour Firefox aujourd'hui.
Peut-être que quelqu'un a déjà recherché ce sujet et que je l'ai complètement manqué. Dans tous les cas, n'hésitez pas à me contacter pour tout retour !
Une autre chose intéressante serait d'explorer s'il existe un moyen d'avoir un mécanisme de persistance dans le navigateur. Je n'ai pas du tout exploré ce domaine, mais ce serait plutôt cool :).