← Back to BrewedIntel
otherlowCVE-2024-44308

Aug 04, 2025 • Exodus Intel VRT

Oops Safari, I think You Spilled Something!

Overview In February 2023, researchers at Exodus Intelligence discovered a bug in the Data Flow Graph (DFG) compiler of WebKit, the browser engine used by...

Source
Exodus Intelligence
Category
other
Severity
low

Summary

Overview In February 2023, researchers at Exodus Intelligence discovered a bug in the Data Flow Graph (DFG) compiler of WebKit, the browser engine used by Safari. This bug, CVE-2024-44308, was patched by Apple in November 2024. While it was alive, its exploit was chained with PAC and APRR bypasses on Apple Silicon to yield renderer ... Read more Oops Safari, I think You Spilled Something! The post Oops Safari, I think You Spilled Something! appeared first on Exodus Intelligence .

Published Analysis

Overview In February 2023, researchers at Exodus Intelligence discovered a bug in the Data Flow Graph (DFG) compiler of WebKit, the browser engine used by Safari. This bug, CVE-2024-44308, was patched by Apple in November 2024. While it was alive, its exploit was chained with PAC and APRR bypasses on Apple Silicon to yield renderer ... Read more Oops Safari, I think You Spilled Something! The post Oops Safari, I think You Spilled Something! appeared first on Exodus Intelligence . Overview In February 2023, researchers at Exodus Intelligence discovered a bug in the Data Flow Graph (DFG) compiler of WebKit, the browser engine used by Safari. This bug, CVE-2024-44308, was patched by Apple in November 2024. While it was alive, its exploit was chained with PAC and APRR bypasses on Apple Silicon to yield renderer remote code execution capabilities on macOS and iOS. Such capabilities, and many others including LPEs and RCEs on Windows and Linux, are available to Exodus’ customers. In this blog post, we examine the technical details of the DFG vulnerability and walk through exploiting it. We cover some concepts pertinent to this bug, go over both the DFG source and generated assembly to show the root cause, and demonstrate how to reliably control the stack layout and register state in order to achieve stable object corruption and ultimately gain arbitrary read/write. Introduction The bug we are exploring in this post is a use-of-uninitialized-variable vulnerability found in the DFG compiler. Specifically, it exists in the code responsible for storing data to an index in a TypedArray. The next section will cover much of the important information needed to understand this bug, but we would highly recommend reading through our previous post on a Safari integer overflow vulnerability, which goes over many more topics, such as the JavaScriptCore (JSC) optimization pipeline. Background Browser engines are constantly seeking to improve user experience by increasing the responsiveness of web pages, with one of the biggest bottlenecks being JavaScript execution. The solution to this problem has been to switch from always interpreting the code, which is much too slow for modern web applications, to compiling the JavaScript with various optimizations. When JavaScript code is executed repeatedly, such as in a loop, it stops being interpreted and is instead just-in-time (JIT) compiled. The JavaScript engine in WebKit, JavaScriptCore, contains several compilers, each of which takes increasingly longer to compile and produce optimized code. As JavaScript code executes increasingly more times (i.e, the code gets “hotter”) it is fed into a higher tier compiler for better optimization. DFG Compiler The DFG is a mid-tier compiler that runs between the Baseline and the Faster Than Light (FTL) compilers, and is meant to generate machine code quickly with optimizations that are cheap in terms of computation time. It is the first tier in the optimization pipeline to use a separate intermediate representation (IR) instead of simply operating on bytecode. DFG IR consists of instructions or operations, which are also called nodes. DFG nodes are simultaneously nodes in a data flow graph and instructions in a control flow graph. Some examples of nodes are PutByVal , GetArrayLength , NewFunction , ArithMul . Speculation JSC relies heavily on speculation to be able to increase performance with optimizations meant for strongly typed languages. While the code is executing, JSC records information about the types that it has seen in order to apply optimizations specific to certain types. This makes sense since a function is likely to often see the same input type. For example, the compiler can generate very different code for the following function depending on whether it is always called with integers or strings. function add(a, b) { return a + b; } If whenever add() is called a and b are always integers, then this is extremely straightforward and can easily by compiled to just a few machine code instructions. This is much better than the generic version that the interpreter can handle in which the arguments may be integers, strings, objects, etc. This system can greatly increase the overall speed of the code being run given that the type information remains consistent. On-stack replacement (OSR) Exit But now the obvious question is “what happens when the compiler’s speculation is wrong?” Along with every piece of code optimized to deal with a specific type, the compiler must include some check to ensure that the runtime type matches the one it has prepared for and, if there is a mismatch, return to a lower-tier executor which can handle the more general case for the operation. This process is often called “deoptimization” or in WebKit “OSR exit.” Every DFG node contains the corresponding bytecode to jump to a lower-tier in case of a broken assumption at runtime. What Exactly is On-Stack Replacement? On-Stack Replacement (OSR) is a method that...

Linked Entities

  • CVE-2024-44308