Full chain exploit for CVE-2019-11708 & CVE-2019-9810
This is a full browser compromise exploit chain (CVE-2019-11708 & CVE-2019-9810) targeting Firefox on Windows 64-bit. It uses CVE-2019-9810 for getting code execution in both the content process as well as the parent process and CVE-2019-11708 to trick the parent process into browsing to an arbitrary URL.
I have covered CVE-2019-9810's root-cause and exploitation in the past in A journey into IonMonkey: root-causing CVE-2019-9810 article and in the associated github repository.
CVE-2019-11708 has been fixed by the bulletin mfsa2019-19 and was assigned Bug 1559858 in the Mozilla bug tracker. Here is the summary of the issue:
Insufficient vetting of parameters passed with the Prompt:Open IPC message between child and parent processes can result in the non-sandboxed parent process opening web content chosen by a compromised child process. When combined with additional vulnerabilities this could result in executing arbitrary code on the user's computer.
You can find the commit addressing the issue here: Clean up prompt open calls in Prompter.jsm.
Overview of the issue
A full-write up of the issue as well as the techniques used in the exploit will be described in an upcoming article on doar-e.github.io.
The exploit has been tested against Windows 19H2 64-bit and it targets a custom build of Firefox so don't be surprised if a bit of work is required to make it work elsewhere :). However, if you just feel like running the exploit without compiling anything, I prepared a packaged browser that I uploaded in release/firefox-68.0a1.en-US.win64.7z. It also includes the
js.exe shell as well as private symbol information for
The exploit assumes that the support for BigInt is turned on in Firefox which you can do by toggling
The exploitation process uses a data corruption to gain privileged JS execution aka God Mode (which is basically an implementation of a technique used in Pwn2Own2014 by Jüri Aedla) which is very different (and much more convenient) from the way I had exploited CVE-2019-9810. This means that there is no control-flow getting hijacked during the exploit chain.
- The exploit uses CVE-2019-9810 to perform the God Mode data corruption and refreshes the current page.
- Once it can execute privileged JS, it finds the current frame message manager and triggers CVE-2019-11708.
- Now that the parent process visited our arbitrary page, we exploit CVE-2019-9810 again and get privileged JS execution there as well.
- At this point the entire browser (sandbox included) is compromised. The first stage is to download and drop a local payload dubbed slimeshady.exe that you can find in payload/ which draws a bunch of animated Slime shady sprites on the desktop with GDI. The exploit also drops and injects a frame script (privileged JS) in every tab to backdoor the whole navigation (already created tabs as well as newly created ones). The tab backdooring is similar to CVE-2019-9810/payload in effect (arbitrary JS injected in every tabs), but this time it is implemented using a Firefox feature (
Services.mm.loadFrameScript) instead of hacky and dirty hooks.
In reality, there are a bunch of more subtle details that are not described by the above and so if you are interested you are invited to go find the truth and read the sources / future article :).
Building the payload
To build the payload, you just have to run
nmake from a VS 2017 x64 prompt.
CVE-2019-11708\payload>nmake Microsoft (R) Program Maintenance Utility Version 14.16.27034.0 Copyright (C) Microsoft Corporation. All rights reserved. taskkill /f /im payload.exe ERROR: The process "payload.exe" not found. if not exist .\bin mkdir bin python src\genheaders.py sprites cl /O1 /nologo /ZI /W3 /D_AMD64_ /DWIN_X64 /sdl /Febin\payload.exe src\payload.cc /link /nologo /debug:full user32.lib payload.cc del *.obj *.pdb *.idb if exist .\bin del bin\*.exp bin\*.ilk bin\*.lib start .\bin\payload.exe
This creates a
payload.pdb file inside the
I wrote this exploit against a local Windows build synchronized to the following revision id: 2abb636ad481768b7c88619080cf224b2c266b2d (if you don't feel like building it yourself, I've uploaded my build here: release/firefox-68.0a1.en-US.win64.7z):
$ hg --debug id -i 2abb636ad481768b7c88619080cf224b2c266b2d
And I have used the following
. "$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