FlawOpen

flawopen.com/Teardowns/cve-2024-23222-apple-ios-webkit-type-confusion

● CVE-2024-23222 · CVSS 8.8 · High
FlawOpen Security Research

CVE-2024-23222: WebKit DFG Property Race

WebKit's DFG JIT could fold a property across an object-structure change; the fix revalidates assumptions before accepting optimized code.

💡 Plain English Explainer (ELI5)

Imagine a warehouse app learning a product's label while staff move it between shelves. A camera tracks the starting and final layouts but misses a temporary shelf layout. In the vulnerable fast path, the app copies a label from that missed stop and later uses it with the final layout without rechecking where the label came from. WebKit's fix records the object, layout, property position, and value, then rechecks them on the main thread; it rejects optimized code when those assumptions no longer match.

Core Concepts & Subsystem Terms

JavaScriptCore (JSC)
The open-source JavaScript engine powering Safari and all iOS web browsers.
DFG (Data Flow Graph) JIT
The mid-tier optimizing compiler in JavaScriptCore that optimizes types based on observed execution profiling.
Structure
WebKit's description of an object layout, including the locations and representations of its properties.
Watchpoint
A runtime notification that invalidates optimized code when an assumption it depends on stops being true.
CVSS 3.1 score and attribution
The CISA ADP enrichment in the CVE Program record assigns CVSS 3.1 8.8 (High). Apple describes the impact differently across release advisories; attribute each impact statement to its specific Apple advisory.
Impact wording by Apple release
Apple’s iOS/iPadOS 17.3 and Safari 17.3 advisories describe unexpected cross-origin behavior. The iOS/iPadOS 16.7.5 advisory says processing malicious web content may lead to arbitrary code execution, and the CVE Program CNA description uses that wording. Attribute impact to the specific release advisory or record.

Framework mappings

Root Cause Analysis

In Graph::tryGetConstantProperty, the DFG compiler could read a property while another thread changed the object's structure. If the object moved through an intermediate structure that was not covered by the installed watchpoints, the compiler could fold a value from that intermediate state into optimized code. The upstream patch records the object, property offset, value, and expected structure, then checks those assumptions on the main thread before the plan is accepted. Apple describes CVE-2024-23222 as a logic issue that could cause unexpected cross-origin behavior. CISA and the CVE record classify it as type confusion, while Google Threat Intelligence Group later attributed a Coruna WebKit RCE exploit to this CVE. The public sources therefore establish real-world use, but do not justify attributing the kit's separate PAC bypass or later chain stages to this single fix.

Affected and fixed Apple releases

ProductAffected beforeFixed release
iOS / iPadOS 17 branchearlier than 17.317.3
iOS / iPadOS 16 branchearlier than 16.7.516.7.5
iOS / iPadOS 15 branchearlier than 15.8.715.8.7
macOS Sonomaearlier than 14.314.3
macOS Venturaearlier than 13.6.413.6.4
macOS Montereyearlier than 12.7.312.7.3
Safariearlier than 17.317.3
tvOSearlier than 17.317.3
visionOSearlier than 1.0.21.0.2

Step-by-Step Attack Flow

Step 1

1. Web content reaches an affected WebKit build

Apple says malicious web content could trigger the issue. GTIG later reported recovering a Coruna WebKit RCE exploit for an iPhone running iOS 17.2 and attributed it to CVE-2024-23222.

Step 2

2. DFG compiles a property assumption

The DFG compiler reads a property while compiling optimized code. The upstream fix's commit explains that object transitions can occur concurrently with this compilation.

Step 3

3. A transition can stale the constant

An object can transition through an intermediate structure while compilation proceeds. If that structure is not watched, a value read from it can be folded into code whose later structure check accepts a different state.

Step 4

4. The plan must be revalidated

The patch records the expected object, structure, and property value, then rechecks them on the main thread. GTIG describes PAC bypass and other chain stages separately; they are not the WebKit fix shown here.

Race trace: a property value crossing object structures

Conceptual interleaving from the patch description; S0, S1, and S2 are illustrative state labels, not recovered runtime layouts or an exploit trace.

T0

DFG observes S0

While constant-folding, DFG observes object O and expects Structure S0.

T1

Object enters untracked S1

Compilation continues while O changes to intermediate Structure S1; installed watchpoints do not cover this state.

T2

A value is folded

DFG reads property at offset P from S1 and embeds value V in the optimized plan.

T3

The plan is checked

Before accepting the plan, the main thread rechecks O, P, V, and expected Structure. The patch rejects the plan if an assumption changed, so a stale value is not accepted under a different structure.

Source Code: Flaw vs. Secure Implementation

UNPATCHED FLAW
// Excerpt from WebKit before commit 6471469 (DFGGraph.cpp)
Locker cellLock { object->cellLock() };
Structure* structure = object->structure();
if (!structureSet.toStructureSet().contains(structure))
    return JSValue();
return object->getDirectConcurrently(cellLock, structure, offset);
HARDENED SECURE PATCH
// Excerpt from WebKit commit 6471469 (DFGGraph.cpp / DFGPlan.cpp)
// Record the property assumptions while compiling.
m_plan.weakReferences().addLazily(object);
m_plan.weakReferences().addLazily(result);
if (!m_plan.objectProperties().addLazily(object, offset, result, set.onlyStructure()))
    return JSValue();

// Before accepting the compiled plan on the main thread:
if (!m_objectProperties.areStillValidOnMainThread(*m_vm))
    return false;

Engineering & System Hardening Checklist

Sources