Super Hat Trick: Exploit Chrome and Firefox Four Times
Unknown
Black Hat USA 2024 · Day 1 · Briefing
Overview
This talk, "Super Hat Trick: Exploit Chrome and Firefox Four Times," presented at Black Hat USA, delves into the intricate world of browser vulnerability research and exploitation. The speakers, known by the nickname Sakura and their partner, both accomplished security researchers, unveil a series of four critical vulnerabilities—two affecting Google Chrome's V8 JavaScript engine and two impacting Mozilla Firefox—that could lead to remote code execution (RCE). The presentation highlights how subtle implementation flaws in new JavaScript language features, specifically the TC39 Set methods proposal, can introduce severe security risks in highly optimized browser engines.

Key moments
- 0:00 Welcome, speakers, organization, and talk agenda
- 1:10 Introducing the first Chrome bug and RCE bounty
- 2:00 Background: New JavaScript Set methods and proposal
- 3:00 Demonstrating the Chrome type confusion bug POC
- 4:00 Deep dive into the root cause of the bug
- 5:30 Overview of the exploitation strategy: faking JSArray
- 6:00 Understanding JSSet and OrderedHashSet internal object models
- 7:30 Demonstrating heap layout manipulation using the clean method
Super Hat Trick: Exploit Chrome and Firefox Four Times
Speakers: Unknown (Sakura and partner), Security Researcher at 360 Vulnerability Research Institute & Master's Student at University in China
Conference: Black Hat USA
YouTube: https://www.youtube.com/watch?v=VNTWm1iNhXY
Overview
This talk, "Super Hat Trick: Exploit Chrome and Firefox Four Times," presented at Black Hat USA, delves into the intricate world of browser vulnerability research and exploitation. The speakers, known by the nickname Sakura and their partner, both accomplished security researchers, unveil a series of four critical vulnerabilities—two affecting Google Chrome's V8 JavaScript engine and two impacting Mozilla Firefox—that could lead to remote code execution (RCE). The presentation highlights how subtle implementation flaws in new JavaScript language features, specifically the TC39 Set methods proposal, can introduce severe security risks in highly optimized browser engines.
The significance of this research lies in its demonstration of advanced browser exploitation techniques, particularly object faking to achieve arbitrary read/write primitives. The discovery of these vulnerabilities, including one that earned a $16,000 bounty from Chrome, underscores the continuous cat-and-mouse game between browser developers and security researchers. It serves as a crucial reminder for both engine developers to meticulously review new language feature implementations for side-effect-related bugs and for users to maintain up-to-date browser versions.
The talk provides a deep dive into the root cause and exploitation strategy for one of the Chrome vulnerabilities, illustrating how a type confusion bug, born from a race condition involving callback functions and internal object pointers, can be leveraged to compromise browser security. By meticulously dissecting the internal object models of JavaScript engines, the researchers showcase their prowess in turning complex software interactions into powerful exploitation primitives.
Background
▶ Watch: Welcome, speakers, organization, and talk agenda (0:00)
The landscape of modern web browsers is a complex tapestry of highly optimized components, with JavaScript engines like Google Chrome's V8 and Mozilla Firefox's SpiderMonkey forming its critical core. These engines are responsible for parsing, compiling, and executing JavaScript code at incredible speeds, often employing just-in-time (JIT) compilation and sophisticated garbage collection mechanisms. This complexity, while enabling rich web experiences, also introduces a vast attack surface for security vulnerabilities.
A significant source of these vulnerabilities often stems from the continuous evolution of the ECMAScript (JavaScript) standard, managed by TC39. As new language features are proposed and integrated, browser engine developers face the challenge of implementing them efficiently and securely. In 2015, the Set data structure was introduced into JavaScript, offering a collection of unique values. Initially, its functionality was basic, lacking methods for common set operations like union or intersection. To address this, TC39 later proposed new, more convenient methods such as union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, and isDisjointFrom.
While these additions enhance developer productivity, their implementation within the highly optimized and often C++-based JavaScript engines can be fraught with peril. The interaction between JavaScript code (especially user-defined callbacks) and the engine's internal C++ logic, particularly when dealing with memory management and object pointers, creates fertile ground for subtle bugs. Previous versions of V8 have seen vulnerabilities related to "rate types," indicating a recurring challenge in maintaining type consistency and memory safety within the engine's intricate runtime. The problem exists because engine developers, in their pursuit of performance, might overlook potential side-effects that user-defined JavaScript functions can introduce when called internally during the execution of a new language feature, leading to a desynchronization between the engine's assumptions and the actual state of memory.
Key Findings
▶ Watch: Background: New JavaScript Set methods and proposal (2:00)
The core contribution of this talk is the discovery and detailed analysis of four critical vulnerabilities, collectively demonstrating a "Super Hat Trick" of browser exploitation. These findings underscore the persistent security challenges within leading web browsers:
- Chrome V8 Type Confusion (Set Methods): The primary focus of the presentation was a type confusion vulnerability found in Chrome's V8 JavaScript engine. This bug was specifically related to the implementation of the new TC39 Set methods proposal, particularly when using methods like
isDisjointFromin conjunction with user-defined callbacks. The vulnerability allowed for memory corruption, leading to a remote code execution (RCE) primitive. This specific bug was reported to Chrome just before its public release and earned the researchers a substantial $16,000 bounty for an RCE exploit. - Second Chrome V8 Vulnerability: The talk briefly mentions a second vulnerability discovered in Chrome, though the transcript does not provide specific details about its nature, root cause, or exploitation. It is implied to also be a critical bug impacting the V8 engine.
- Two Firefox Vulnerabilities: In addition to the Chrome findings, the researchers also identified two distinct vulnerabilities affecting Mozilla Firefox. Similar to the second Chrome bug, the transcript does not elaborate on the technical details of these Firefox vulnerabilities. However, their inclusion in the "Super Hat Trick" implies they are significant and likely also lead to RCE or other severe security impacts.
The overarching finding is that the introduction of new, seemingly innocuous, JavaScript language features can hide profound security implications. The speakers demonstrated that a deep understanding of internal engine object models and the potential for side-effects from JavaScript callbacks is crucial for uncovering and exploiting such vulnerabilities. The ability to achieve arbitrary read/write through object faking, specifically by manipulating internal Set structures to craft a fake JSArray, stands out as a key technical contribution in the exploitation phase.
Technical Deep Dive
▶ Watch: Deep dive into the root cause of the bug (4:00)
The most detailed part of the presentation focuses on the first Chrome V8 vulnerability, a fascinating type confusion bug stemming from the implementation of new TC39 Set methods.
The vulnerability's genesis lies in the proposed Set methods, which aim to simplify operations like union and intersection. The specific method highlighted in the Proof of Concept (POC) is isDisjointFrom.
The Proof of Concept (POC) for V8 Type Confusion:
- Initialization: Two distinct
Setobjects,v0andv1, are created. - Callback Definition: A complex, user-defined function is set as a getter for the
sizeproperty ofv1. This function is designed to have a side effect: it callsv0.clear(), which removes all elements fromv0.
- Triggering the Vulnerability: The
isDisjointFrommethod is called onv0, passingv1as an argument:
When this POC is executed, it leads to a runtime error message indicating a type confusion: "tries to use objects as if it were an object of another type." This error signifies that the V8 engine has attempted to interpret a piece of memory as one type of object when it is, in fact, another, leading to a crash or exploitable state.
Root Cause Analysis:
The speakers meticulously explain the root cause by examining the V8 engine's internal logic for implementing the new Set methods:
- Initial Pointer Fetch: When executing methods like
isDisjointFromon aSetobject (e.g.,v0), the V8 engine first retrieves a pointer tov0's internal data structure, specifically theOrderedHashSetwhich actually stores the elements. This pointer is stored in a local variable, let's call ittable. getSetRecordCall & Side Effect: Subsequently, the engine calls a function namedgetSetRecord. This function is responsible for processing the argumentv1, which might involve accessing properties likev1.size. Critically, accessingv1.sizetriggers the user-defined getter function.- Pointer Invalidation: The user-defined getter for
v1.sizecontains the side effect:v0.clear(). Whenv0.clear()is executed:
- V8 creates a new, empty
OrderedHashSetobject. - The
JSSetobjectv0is updated to point to this newOrderedHashSet. - Crucially, the
elements_countproperty of the oldOrderedHashSet(the onev0originally pointed to) is modified to become a pointer to the newOrderedHashSet. This is the core of the type confusion: an integer field now holds a pointer.
- Stale Pointer Usage: After
getSetRecordreturns, the V8 engine continues execution, attempting to use the previously fetchedtablepointer. However, thistablepointer now points to the oldOrderedHashSet, whose internal structure has been unexpectedly modified by the side effect. Specifically, itselements_countfield, which should be a small integer, now contains a pointer to anotherOrderedHashSet. When V8 attempts to treat this pointer as an integer, type confusion occurs, leading to a crash or an exploitable primitive.
The Fix:
The solution to this vulnerability, as presented, is remarkably simple: reorder the operations. The getSetRecord function, which can trigger arbitrary JavaScript callbacks and thus side effects, should be called before any critical internal pointers are fetched and relied upon. By ensuring that all potential side effects are handled before sensitive internal state is accessed, the risk of stale pointers and type confusion is eliminated.
Exploitation Strategy: Object Faking for Arbitrary Read/Write
Exploiting this type confusion to achieve remote code execution typically involves gaining an arbitrary read/write primitive. The speakers outline a common and powerful technique: object faking, specifically faking a JSArray.
- Goal: Create a fake
JSArrayin memory. If an attacker can control the memory layout of an object that the JavaScript engine believes is aJSArray, they can manipulate its internal pointers (e.g.,elementspointer,lengthfield) to point to arbitrary memory addresses. This effectively grants arbitrary read and write capabilities across the browser's memory space. - The Hardest Part: The primary challenge is obtaining a "memory configurable object" through the vulnerability. This means finding a way to make the engine misinterpret an object's internal structure such that an attacker can control what its fields point to.
- Deep Dive into
SetObject Model:
JSSet: This is the JavaScript-levelSetobject. Internally, it holds a pointer to anOrderedHashSet.OrderedHashSet: This C++ internal structure is where the actual elements of theSetare stored. Crucially, it contains anelements_countproperty, which is normally a small integer representing the number of elements in the hash table.
- Leveraging
clear()'s Side Effect for Exploitation Primitive:
- Recall the
v0.clear()side effect: Whenv0(aJSSet) is cleared, its internal pointer is updated to a new emptyOrderedHashSet. - The
elements_countproperty of the oldOrderedHashSet(the onev0previously pointed to) is modified to contain a pointer to the new emptyOrderedHashSet. - This is the critical primitive: an
elements_countfield, which should be an integer, now holds a pointer. By carefully structuring theSetobjects and triggering the bug, an attacker can arrange for anOrderedHashSet'selements_countto be overwritten with an arbitrary controlled value (an address). - Once an attacker can control an
elements_countto point to an arbitrary memory address, they can then craft a fakeJSArrayheader at that address. By manipulating theelements_countof a specially preparedOrderedHashSetto point to the address of the fakeJSArrayheader, and then triggering the type confusion, the engine might misinterpret theOrderedHashSetas aJSArray. - This allows the attacker to read and write to arbitrary memory locations by performing operations on the "fake"
JSArray, which the engine believes is legitimate. With arbitrary read/write, an attacker can inject shellcode, modify execution flow, and ultimately achieve RCE.
The transcript concludes by detailing this specific primitive, emphasizing how the seemingly simple clear() operation, when triggered maliciously via a side-effect, can corrupt the internal state of OrderedHashSet objects, paving the way for full RCE. While the full RCE chain (e.g., finding gadget addresses, ROP chaining) is not explicitly detailed in the provided transcript, the establishment of an arbitrary read/write primitive is the most significant hurdle in browser exploitation, and the speakers clearly demonstrated how their vulnerability provides this capability.
Demo / Proof of Concept
▶ Watch: Overview of the exploitation strategy: faking JSArray (5:30)
The presentation included a clear demonstration of the Proof of Concept (POC) for the first Chrome V8 vulnerability. The speakers presented the JavaScript code snippet that triggers the type confusion bug, as detailed in the "Technical Deep Dive" section.
The POC involved creating two Set objects, v0 and v1, and then defining a custom getter for v1.size that, when invoked, calls v0.clear(). Subsequently, calling v0.isDisjointFrom(v1) leads to the vulnerability. The slide explicitly showed the error message generated when this POC was executed, indicating a type confusion: "tries to use objects as if it were an object of another type." This visual confirmation of the crash served as concrete evidence of the bug's existence and its immediate impact on the browser's stability.
While the transcript did not provide a live demonstration of full remote code execution (RCE) for any of the four vulnerabilities, the explanation of the exploitation primitive—specifically, how the type confusion can be leveraged to manipulate OrderedHashSet's elements_count to achieve arbitrary read/write, a critical step towards RCE—functioned as a conceptual demonstration of its exploitability. The $16,000 RCE bounty awarded by Chrome for this particular bug further validates its severe security implications and exploitability. The focus was on the root cause and the first steps of exploitation rather than a full end-to-end RCE demo.
Defensive Implications
▶ Watch: Demonstrating heap layout manipulation using the clean method (7:30)
The detailed analysis of these browser vulnerabilities carries significant implications for various stakeholders in the cybersecurity ecosystem:
- Browser Engine Developers (e.g., V8, SpiderMonkey teams):
- Side-Effect Awareness: The paramount lesson is the extreme caution required when implementing new language features, especially those that involve callbacks or user-defined functions. Developers must meticulously analyze all possible side effects that JavaScript code can introduce when called internally by the engine, particularly concerning internal object pointers and memory layouts.
- Strict Pointer Validation: Implement robust checks and validation mechanisms for internal pointers, ensuring they remain valid and consistent across different execution phases, especially after potential state changes caused by callbacks.
- Stale Pointer Prevention: Design code paths to prevent the use of stale pointers. If a memory region or object structure can be modified by a callback, any pointers to that structure should be re-fetched or re-validated after the callback returns.
- Security Reviews of New Features: New ECMAScript proposals and their implementations should undergo rigorous security reviews and fuzzing specifically targeting interactions between the new features and existing engine components, looking for race conditions and type confusions.
- Web Developers:
- Secure Coding Practices: While these are engine-level bugs, understanding their nature reinforces the importance of secure coding practices. Avoid unnecessary complexity in callback functions and be mindful of their potential impact on object states, even though the direct exploitation usually targets the engine.
- End Users:
- Keep Browsers Updated: The most critical defense for end users is to keep their web browsers updated to the latest stable versions. Browser vendors like Google and Mozilla promptly release patches for critical vulnerabilities like these, and timely updates ensure users are protected.
- Exercise Caution: While browser security is robust, users should still exercise caution when visiting untrusted websites, as these are often the vectors for delivering browser exploits.
- Security Researchers:
- Focus on New Language Features: This talk highlights a fruitful area for vulnerability research: newly introduced or proposed language features in JavaScript. The implementation of these features often introduces new, complex code paths that are less mature and more prone to subtle bugs.
- Deep Object Model Understanding: A deep understanding of the internal object models (e.g.,
JSSet,OrderedHashSet,JSArrayin V8) is essential. Exploiting these bugs requires moving beyond surface-level JavaScript to understand how the engine manages memory and objects at a low level. - Fuzzing and Static Analysis: These bugs are often found through advanced fuzzing techniques that can trigger obscure code paths and race conditions. Static analysis tools, if sophisticated enough, might also aid in identifying potential side-effect-related issues.
- Browser Bug Bounty Programs:
- The $16,000 bounty awarded for one of these RCE bugs demonstrates the significant value browser vendors place on external security research and responsible disclosure. These programs incentivize researchers to find and report critical flaws, ultimately making the web safer for everyone.
In essence, these findings serve as a stark reminder that even the most mature and heavily scrutinized software, like web browsers, remains susceptible to fundamental design and implementation flaws, especially at the intersection of complex language features and high-performance engine architectures.
Key Takeaways
- New JavaScript Features Introduce Risk: The implementation of new ECMAScript proposals, such as the extended
Setmethods, can introduce complex vulnerabilities in highly optimized browser JavaScript engines like V8. - Side-Effects in Callbacks are Critical: User-defined JavaScript callbacks, when triggered internally by the engine during the execution of new features, can introduce unexpected side effects that invalidate internal pointers, leading to severe type confusion bugs.
- Deep Object Model Understanding is Key to Exploitation: Successful exploitation of these vulnerabilities relies on a meticulous understanding of the browser engine's internal object models (e.g.,
JSSetandOrderedHashSetin V8) to manipulate memory structures. - Object Faking Enables Arbitrary Read/Write: Techniques like object faking, specifically crafting a fake
JSArrayheader by manipulating anelements_countfield, are powerful primitives for achieving arbitrary read/write capabilities, a crucial step towards remote code execution. - Browser Vendors Value and Reward Security Research: The $16,000 bounty awarded for one of the Chrome RCE vulnerabilities highlights the importance and financial incentive for security researchers to discover and responsibly disclose critical browser flaws.
- Continuous Updates are Essential for Defense: For end-users, keeping browsers updated to the latest versions is the most effective defense against these types of sophisticated, engine-level vulnerabilities.
About the Speaker(s)
The talk was presented by a team of accomplished security researchers, primarily identified by the nickname Sakura and a partner. Both speakers are affiliated with the 360 Vulnerability Research Institute, a prominent security organization, and Sakura is also pursuing a master's degree at a university in China.
They are distinguished experts in vulnerability hunting within web browsers, with a primary focus on Chrome and Firefox. Their expertise is evidenced by their recognition as top researchers in both the Chrome and Firefox vulnerability reward programs, indicating a consistent track record of discovering and responsibly disclosing critical bugs. The team has a history of presenting their significant findings at major international security conferences, including multiple appearances at Black Hat. Their work consistently demonstrates a deep technical understanding of browser internals and advanced exploitation techniques.