Full Report
In JavaScript interpretters, there's a map (known as a hidden class) that represents the memory layout of a object. A map holds an array of property descriptors that contain information about each property, as well as the elements and their types. These maps are shared between objects that have the same layout. If a map doesn't exist, then a new one is created. When this happens, the old and new map are related by a transition that occurs to go from one map to another. When doing this transition, the old map and new map have coinciding pointers to each other. A map can have multiple transitions. For instance, if property b is added and then property c is added, this creates two transition objects. If a field type is changed, such as going from an integer to a double, the map of the object is changed to reflect this via a transition. In the example above, with o1 and o2 having a as an integer, if o1 gets a set to a double then the map in o2 is set to deprecated. This is because SMI (internal small integer) can be represented by a more generalized value. Eventually, the o2 object will be updated to the map of o1 once a property is accessed. In v8, object properties can be stored in an array or a dictionary. Objects with properties stored in an array are fast objects while objects within properties in dictionaries are dictionary objects. Map transitions and deprecations specific to fast objects. Normally, when a map deprecation occurs, another fast map is created, but it's possible to make this not happen. In particular, if there are too many transitions in an object, then a new dictionary map is created instead. Most uses PrepareForDataProperty are safe, there are two locations where the type can be updated to a dictionary map instead of the original object map. In CreateDataProperty, it may result in a dictionary map after an update. There are multiple routes to this but the usage of the spread syntax ended up being the most interesting. When using the spread syntax (...obj1) and the usage of a property accessor, the function CreateDataProperty will be called while it's being cloned. While this cloning is happening, it's possible to deprecate the map while it's being used for the clone. This allows for the updated map to be a fast map instead of a dictionary map! A type confusion in the JavaScript engine leads to memory corruption now. To exploit this, they used the type confusion to overwrite the elements to a large value within the underlying data structure for NameDictionary. By doing this, we get an OOB read for property values that leads to improper object access. Creating a "fake object primitive" is one of the best primitives in JavaScript engine exploitation. So, just arrange the heap in a nice way to create a fake object. Once there, an arbitrary read/write is easy to gain. First, place an object into an array and use the OOB read to read the addresses of the objects stored within the array. For a write, do the same thing as a read but write to these objects instead. Chrome recently implemented the V8 heap sandbox to isolate the V8 heap from other process memory, such as code, to prevent corruption within the V8 heap and access to other memory. So, to get code execution, it's a requirement to escape this requirement. To work around this, they modified DOM objects implemented in Blink. These are objects allocated outside of the v8 heap but are represented as API objects in v8. By causing type confusion in the API calls, it's possible to obtain a read/write primitive over the entire memory space. Overall, a good post on exploitation and how to bypass a new defense-in-depth measure. Great stuff! If I had to guess how this bug was found, the author found a side effect that was not accounted for in some paths.
Analysis Summary
# Vulnerability: Chrome V8 Type Confusion via Map Deprecation in Spread Syntax
## CVE Details
- **CVE ID:** CVE-2024-5830
- **CVSS Score:** 8.8 (High)
- **CWE:** CWE-843 (Access of Resource Using Incompatible Type / Type Confusion)
## Affected Systems
- **Products:** Google Chrome, Chromium-based browsers (Edge, Opera, Brave), and V8 JavaScript Engine.
- **Versions:** Chrome versions prior to 126.0.6478.56/57.
- **Configurations:** Systems running JavaScript environments that utilize the V8 engine with optimization features (Fast Objects) enabled.
## Vulnerability Description
The flaw exists in how V8 handles **Map transitions** and **deprecations**. In V8, objects are typically "Fast Objects" using a Map to describe memory layout. When a property type changes (e.g., SMI to Double), the old Map is deprecated.
A race-like condition occurs during the use of **Spread Syntax** (`...obj`). When an object is being cloned via spread syntax, if a property accessor is triggered that deprecates the Map *while* the clone is in progress, the function `CreateDataProperty` may incorrectly update the object to a "Fast Map" when the internal state logic should have transitioned it to a "Dictionary Map" due to excessive transitions. This transition mismatch results in a type confusion where the engine treats a Dictionary Object as a Fast Object (or vice versa), leading to memory corruption.
## Exploitation
- **Status:** PoC available; detailed exploitation walkthrough published (RCE achieved).
- **Complexity:** High (Requires sophisticated heap grooming and sandbox escape).
- **Attack Vector:** Network (Remote). Usually triggered by a victim visiting a malicious website.
## Impact
- **Confidentiality:** High (Arbitrary memory read allows theft of sensitive data/tokens).
- **Integrity:** High (Arbitrary memory write allows for code execution).
- **Availability:** High (Can lead to reliable browser process crashes).
## Remediation
### Patches
- Update Google Chrome to version **126.0.6478.56** (Linux) or **126.0.6478.56/57** (Windows/Mac) or later.
- V8 engine integrators should pull the fix associated with Chromium bug **342456991**.
### Workarounds
- No practical end-user workaround exists other than updating the browser. Developers can avoid complex object spreads in Performance-critical code to reduce attack surface, though this is not a comprehensive fix.
## Detection
- **Indicators of Compromise:** Unexpected renderer process crashes; high memory usage patterns followed by shellcode execution.
- **Detection methods:** Use of specialized memory sanitizers (ASAN/MSAN) during browser testing. Security software may detect the exploitation of Blink/DOM objects used to escape the V8 sandbox.
## References
- **Vendor Advisory:** [https://chromereleases.googleblog.com/2024/06/stable-channel-update-for-desktop.html](https://chromereleases.googleblog.com/2024/06/stable-channel-update-for-desktop.html)
- **Technical Analysis:** [https://github.blog/security/vulnerability-research/from-object-transition-to-rce-in-the-chrome-renderer/](https://github.blog/security/vulnerability-research/from-object-transition-to-rce-in-the-chrome-renderer/)
- **GitHub Advisory:** [https://github.com/advisories/GHSA-fchp-8m28-g68f](https://github.com/advisories/GHSA-fchp-8m28-g68f)