viernes, 10 de abril de 2020

Setting up a vulnerable v8 on a Windows System

Disclaimer

I wasn't sure about releasing this blog post since it's a bit dated now and a few explanations are a bit more convoluted than these should. I am releasing it because there are a couple of things that might be of help (such as the untrusted code mitigation section) in the future or for anyone who wants to get started on v8 exploitation and compile it on a Windows environment. For a more general overview and not just a set-up I wrote a blog post on SensePost's blog about v8 internals and debugging.

Intro

One of the things that is now under the spotlight in terms of exploit development, is the area of browser exploitation. Nowadays, most of it happens within the JavaScript engines that these browsers make use of and, with the recent news of so many browsers moving to Chromium, I thought it was a very good time and a good X-mas project to give V8 a go. This blog post is geared towards having a set of notes and things that would help on setting up the environment to do some v8 exploitation on a Windows environment.
Credit: Most of the things learned, pitfalls and exploit mentioned on this blog post, are things learned while working on the following blog posts:

Goal

It's good to have short-term goals, so I tried to set myself up to an easy goal which was to try and build the exploit for this CTF challenge. This leads to the Project-0 Issue 1710, with the added difference of working on a Windows environment. I knew it wouldn't change much, since what we'll be attacking is the V8 engine itself and nothing OS specific. However, at a minimum, the shellcode will be different, and hopefully, more differences could be found along the way. This was also a good way to prevent myself just following blindly and copy pasting things from here and there and just seeing it work. Following and understanding the exploitation, plus setting up the environment to have a vulnerable V8 version, made for a nice small research project.

Takeaways

The takeaways that I got during this research and hopefully you'll have by the end of this blog post are:
  • Setting-up a dev environment for the v8 engine
  • Choose and set a vulnerable v8 commit

The environment

This section is a go-to section in order to have all the links to each of the software pieces that we'll need to set-up.

Windows VM

First things first, we'll need a Windows environment. For this, Microsoft provides free to test and download Virtual Machines of your choice: https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/. In my case I used VMWare Workstation Player.

Getting V8

This one was a really tricky one, it took a while to get all of this right. If you try to google your way out, you'll find yourself jumping like so (skip these points if you just want to go build v8):
  1. Land on https://v8.dev/docs/build because we want to build it
  2. Which gets you here https://v8.dev/docs/source-code and then gets you
  3. Here https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#Setting-up-Windows
  4. To finally realise that you need Visual Studio
  5. And after trying to compile all, since the vulnerable v8 version is older, we need an older VS: i.e. VS2017
So we'll have to do all of the above in reverse!
VS features needed to compile the vulnerable V8 version
  1. Go get Visual Studio 2017 from here and make sure to enable the features mentioned here: "You must install the “Desktop development with C++” component and the “MFC/ATL support” sub-components"
  2. Get the depot_tools bundle as mentioned here as these are needed to fetch and compile V8's source code. Extract the bundle into a folder WITHOUT SPACES!
  3. To obtain and compile the code I've modified a batch script to do this for us which will fetch the vulnerable version and compile V8. Do note that although it's one file, you need to split it into two parts (read the comments).
  4. Finally you can call V8 with something like: .\v8\out.gn\library\d8.exe expm0-exploit.js

Caveats and Pitfalls when compiling v8

While trying to follow the write-ups, I came across several pitfalls, all of them with the common subject of not allowing the exploitation of the bug.

Untrusted Code

In 2018 Google's Project-0 disclosed a new technique of exploitation called Speculative Side-Channel Attacks (remember, Spectre vulnerability). In certain scenarios this would lead to disclosure of memory and potentially crafting primitives to craft an exploit. What's concerning for us here is that V8, by default, includes the switch to enable this mitigation. All of this can be seen in the batch file when we add the flag v8_untrusted_code_mitigations=false.
However, if you are building Chrome itself, it doesn't have such a flag enabled. I am not sure of why this decision but my wild guess it's performance and that Chrome comes with what seems a robust sandbox. Finally, big big big thanks to @_tsuro who took some time to help me determine what was the issue and for mentioning this flag!

Debug Mode

If you are first approaching V8 for exploitation and you are using the debug version, let me tell you that you are going to run into very nasty asserts. I haven't had the time yet to research into disabling these while having a debug build but, for the time being and since the reference write-ups are really well done, I have done everything with a release build as there was no need to use WindDBG for the time being. This flag is is_debug=false in the batch file.

Prerequisites that I didn't know were required

Of all this research, the most valuable part for me were the requisites I should've known but didn't. In other words, the skills and knowledge that I needed to have in order to understand the write-ups without going wut. I had to re-read the write-ups more than 10 times in order to finally understand each an every line of code that I read and wrote. Still, there are some parts that I haven't mastered yet of the exploit, we'll see them later.

JIT Compilers

I already knew about Just in Time (JIT) compilers but I felt there was the need to introduce these here since this is a very basic scrap of notes/blog and should welcome anyone wanting to start on the same thing. In a nutshell V8 makes use of JIT compilation to optimise the execution of JavaScript code.
As you might know, JavaScript is interpreted by an engine (in our case V8) to later do the conversion into machine code so that it can be run. One drawback of being interpreted, is that there are extra-steps before it gets executed. There are certain situations that these extra-steps can be removed and just replace it with "set-in-stone" compiled code which runs way faster.
Imagine, the following snippet of JavaScript:
var finalresult = 0;

function add_ten(n) {
    return (n + 10);
}

for (let i = 0; i<10000; i++)
    finalresult = add_ten(finalresult);

console.log(finalresult);

In the previous snippet, the function add_ten is ran 10000 times. To prevent the interpreter from running all over this function and, it is a candidate to be optimised (in JIT compilation terms, it's a hot function). This is picked up by the "black magic in V8" (optimisation phases on TurboFan) and then compiled into machine code, so that every time we call the function, we jump straight into the machine code compiled code, and not the bytecode, to ensure it runs as fast as possible.
Note that this is a VERY simplified explanation and probably not very accurate one of how the V8 pipeline works. You'll find it's best to go into the "src" folder of V8 and start grepping/finding the functions related to this "black magic" in there to really start having an understanding or refer to the references at the end of this blog post.

Turbolizer

Turbolizer is a super-duper nice piece of software provided by the V8 project for the ease of debugging and tracing the optimisation/deoptimisation phases happening on Turbofan, the optimisation compiler. This helps having a visual representation of what's happening at a low level without needing to debug code. Turbolizer comes built into V8 so we can just start it by browsing into the folder and starting a web server of our choice in there: .\v8\tools\turbolizer>python -m SimpleHTTPServer 8000
If we  have a looksie on the previous snippet of code and choose the Simplified Lowering phase we should see something like the following image:

Turbolizer trace from example script
I took the hassle of highlighting the three buttons on the top left because those are the ones you'll need to see all the information - from right to left: Show labels, show entire graph and sort graph. Highly recommended to press these in that order.

Further references

- Sea of nodes blog post, to get an introduction before tackling turbolizer: https://darksi.de/d.sea-of-nodes/
- Introduction to turbofan: https://doar-e.github.io/blog/2019/01/28/introduction-to-turbofan/
- Typer - Gives a type to a node (Range, PlainNumber, MinusZero, etc.)
- Type lowering - Narrows the type of a node.
- Very nice slides towards understanding optimisation and turbofan graphs: https://docs.google.com/presentation/d/1sOEF4MlF7LeO7uq-uThJSulJlTh--wgLeaVibsbb3tc

No hay comentarios:

Publicar un comentario