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

● CVE-2024-23222 · CVSS 9.8 · Crítica
Investigación · FlawOpen

CVE-2024-23222: Apple Safari WebKit Object Unboxing Teardown

Análisis técnico del código fuente y mitigaciones de ingeniería para vulnerabilidade: How JavaScriptCore's DFG JIT compiler failed to verify object type tags before unboxing, allowing targeted spyware to bypass Pointer Authentication (PAC) on iOS and macOS.

💡 Explicación en Lenguaje Sencillo (ELI5)

Analogía práctica: Apple devices have special hardware called Pointer Authentication (PAC) that stamps memory addresses with cryptographic signatures so hackers can't forge them. But in Safari's JavaScript engine, a math helper took an untrusted object and stripped off its label without verifying what it was. This allowed attackers to trick the processor into signing a fake pointer, letting targeted spyware take over Safari.

Conceptos Clave y Términos

JavaScriptCore (JSC)
El motor JavaScript de código abierto que impulsa Safari y todos los navegadores web en iOS.
DFG (Data Flow Graph) JIT
El compilador optimizador de nivel medio en JavaScriptCore que optimiza tipos según el perfil de ejecución observado.
Pointer Authentication Code (PAC)
Función de seguridad de hardware ARM64e que utiliza firmas criptográficas para validar punteros de memoria antes de su ejecución.
Speculative Unboxing
Extracción de valores enteros o punteros sin procesar de valores JavaScript empaquetados en NaN bajo el supuesto de que el tipo sigue siendo válido.

Análisis de Causa Raíz

La causa raíz se debe a parámetros de límite no validados en sistemas de código abierto, lo que permite la desincronización de estado y la elusión de controles de seguridad.

Flujo de Ataque Paso a Paso

Step 1

1. Malicious Web Page Navigation

The victim navigates to an attacker-controlled web page in Safari on iOS or macOS.

Step 2

2. DFG Speculation Generation

The script executes an object unboxing routine in a tight loop. JavaScriptCore's DFG compiler speculates that the input is always a native JS object.

Step 3

3. Type Tag Strip Without Verification

The compiled bytecode strips the NaN-box metadata tag without emitting a type assertion guard.

Step 4

4. PAC Forgery & Sandbox Escape

The attacker supplies a disguised object structure, forging a signed pointer to execute shellcode and begin the secondary kernel privilege escalation chain.

Código Fuente: Vulnerable vs. Seguro

✕ IMPLEMENTACIÓN VULNERABLE
// VULNERABLE: C++ Logic from WebKit/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
void DFGSpeculativeJIT::compileUnboxObject(Node* node) {
    Edge edge = node->child1();
    GPRReg jsValueGPR = edge.useInfo().gpr();
    GPRReg resultGPR = node->gpr();

    // CRITICAL ROOT CAUSE:
    // Speculatively stripped the TagMask from JSValue without verifying
    // that the value actually satisfied isCell() and was an Object pointer!
    m_jit.move(jsValueGPR, resultGPR);
    m_jit.and64(TrustedImm64(TagMask), resultGPR);
    
    // Resulting pointer assumed authenticated without PAC validation!
}
✓ PARCHE SEGURO Y ROBUSTO
// SECURE: Open-Source C++ Patch from WebKit Repository
void DFGSpeculativeJIT::compileUnboxObject(Node* node) {
    Edge edge = node->child1();
    GPRReg jsValueGPR = edge.useInfo().gpr();
    GPRReg resultGPR = node->gpr();

    // 1. Emit explicit type tag assertion guard
    MacroAssembler::Jump notCell = m_jit.branchIfNotCell(jsValueGPR);
    speculationCheck(BadType, JSValueRegs(jsValueGPR), edge.node(), notCell);

    // 2. Verify object structure cell before unmasking pointer
    m_jit.move(jsValueGPR, resultGPR);
    m_jit.and64(TrustedImm64(TagMask), resultGPR);
    
    // 3. Ensure PAC authentication check verifies target pointer integrity
    speculationCheck(BadType, JSValueRegs(jsValueGPR), edge.node(),
                     m_jit.branchTest8(MacroAssembler::Zero, 
                                       MacroAssembler::Address(resultGPR, JSCell::typeInfoTypeOffset())));
}

Lista de Verificación de Seguridad para Ingeniería