Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

The V8 (Heap) Sandbox - 1862

v8Posted 2 Months Ago
  • v8 is a JavaScript engine that compiles JavaScript code into native machine code to make execution faster. The v8 Sandbox, a lightweight sandbox, is now a stable feature in Chrome. Why is this sandbox needed? Chrome is a huge target with a difficult history of memory corruption issues; these aren't classic memory corruption issues like UAF, and OOB reads though. These are very subtle logic issues that make languages like Rust or new features like memory tagging not useful.
  • The author includes an example that could likely lead to memory corruption from side effects. It's possible this could be solved by a good compiler check, like in Rust but this misses a fundamental issue with v8. v8 itself is a compiler! Memory safety cannot be guaranteed if the compiler is part of the attack surface.
  • Why doesn't memory tagging work though? A CPU side channel, which can easily be exploited in JavaScript because it's arbitrary code, can be used to leak these values. Hence, the attacker can bypass the mitigation. Additionally, due to pointer compression, there is no room in the bigs for v8.
  • The solution to this is using a sandbox to isolate the V8 heap's memory such that memory corruption cannot spread to other parts of the process memory. This is similar to userspace and kernel space in operating systems. The idea is that a bug in v8 shouldn't affect the rest of the hosting process.
  • In practice, the sandbox is replacing all data types that can access out-of-sandbox memory with sandbox-compatible alternatives. In particular, pointers and 64-bit sizes must be removed because an attacker could corrupt them. Due to constraints, the V8 heap is the only thing within the sandbox. They have a nice image that shows the security of it. The v8 objects are effectively entries into a table outside of the sandbox. This table entry then points to the external object. If you can only control the table index, there is not much you can do to exploit this.
  • This isn't perfect though. There are several invariants that this changes. For instance, they show an example with code that assumes that the number of properties stored in a JSObject is less than the total number of properties of the object. Theoretically, an attacker could corrupt one of them to break this invariant, leading to an out-of-sandbox access.
  • According to the author, this is okay though. First, many of these are simply memory corruption issues that can be fixed via simple bounds checks or UAF checks. These sandbox bugs are preventable by many other security features, such as Chrome's libc++ hardening.
  • To create a security boundary, it must be testable, and be created with a specific attacker model in mind. The attack model is assumed to have read/write access inside the v8 sandbox, with the goal of corrupting memory outside of it. To make this testable, debug builds include a memory-corruption API that can be used to read/write within the sandbox. Finally, they have a sandbox testing mode that determines whether a write violates the invariants.
  • A fantastic post on the v8 sandbox and the more in-depth v8 heap sandbox. I appreciated the well-defined threat model around the protection the most.