Browser Exploitation on Windows — Chakra/ChakraCore (CVE-2019-0567)

Last updated: 2026-04-10
Primary source: Connor McGarr — 3-part blog series (2022-03-11)
Related: Type Confusion, Mitigations
Tags: user-mode, browser, jit, type-confusion, cfg, acg, chakra, cve-2019-0567


Summary

CVE-2019-0567 is a type confusion vulnerability in Microsoft’s Chakra/ChakraCore JavaScript JIT compiler. Connor McGarr’s 3-part series documents end-to-end modern browser exploitation on Windows: JIT type confusion → R/W primitive → ASLR/DEP/CFG bypass → ACG bypass → code execution in Edge. This page provides a conceptual framework and key techniques; see the raw sources for step-by-step details.


Environment

  • Target: Microsoft Edge (pre-V8 Chakra engine) + ChakraCore shell (ch.exe)
  • Windows version: Windows 10 1703 (pre-KB4480961 patch)
  • CVE-2019-0567: Type confusion in Chakra JIT
  • CVE-2017-8637: ACG bypass (patched Windows 10 RS4+)
  • Mitigations present: ASLR, DEP, CFG, ACG, CIG (no child processes), CET absent

JIT Type Confusion Fundamentals

Why JIT is an Attack Surface

JIT compilers must:

  1. Observe JavaScript value types at runtime
  2. Emit optimized machine code assuming those types stay stable
  3. Insert type guards (bailout checks) when assumptions might be violated

The attack: violate type assumptions without triggering the guard → JIT emits code that treats one type as another → type confusion.

Chakra-Specific: Array Type System

Chakra tracks array element types for optimization:

JavascriptNativeIntArray    → elements are 32-bit integers
JavascriptNativeFloatArray  → elements are 64-bit floats
JavascriptArray             → elements are JS Values (boxed, 64-bit)

A type confusion from NativeIntArrayJavascriptArray means code treats 32-bit int storage as 64-bit JS Value pointers → addrof (leak object address) and fakeobj (create fake object at address) primitives.

CVE-2019-0567 Root Cause

The JIT compiler incorrectly infers that two arrays of different types are the same type, allowing a native (unboxed) array to be treated as an object array. Accessing elements of the confused array reads raw memory bytes as JavaScript object pointers → addrof/fakeobj primitives.


Exploit Primitive Ladder

1. Type confusion (CVE-2019-0567)
   → addrof(object)   — read object's kernel address as JS integer
   → fakeobj(address) — treat raw memory address as JS object

2. addrof + fakeobj → AAR/AAW (arbitrary address read/write)
   → Craft fake DataView/TypedArray object at known address
   → Manipulate internal buffer pointer → read/write arbitrary process memory

3. ASLR defeat
   → Use AAR to read function pointers from DOM object vtables → leak module base

4. DEP bypass (ROP)
   → Use AAW to write ROP chain to stack → redirect stack pivot
   → Or: overwrite return address

5. CFG bypass
   → Valid indirect call targets via CFG bitmap lookup
   → Find "safe" CFG-allowed function that acts as trampoline
   → Route ROP through CFG-valid jump

6. Code execution (ChakraCore)
   → Write shellcode to RWX JIT page (present in ChakraCore without ACG)
   → Jump to shellcode via ROP

7. ACG bypass (Edge — CVE-2017-8637, patched RS4+)
   → Edge enforces ACG (no dynamic code generation from renderer)
   → Bypass: Content process → injecting into broker or other non-ACG process
   → Or: Use NtMapViewOfSection to map pre-existing executable pages

Key JavaScript Exploit Primitives

// addrof: leak address of a JavaScript object
function addrof(obj) {
    // ... type confusion: read obj as raw integer
    return address_as_float;
}

// fakeobj: create JavaScript "object" at arbitrary address
function fakeobj(addr) {
    // ... type confusion: treat raw address as object pointer
    return fake_object;
}

// AAR using fake DataView:
function read64(addr) {
    // Create fake DataView pointing buffer to addr
    // Read 8 bytes via DataView.getBigInt64()
}

// AAW using fake DataView:
function write64(addr, value) {
    // Same technique, DataView.setBigInt64()
}

Windows-Specific Mitigations (Edge Context)

MitigationImpactBypass
ASLRAll module bases randomizedLeak via vtable pointer from known heap object
DEPNo exec on data pagesROP chain
CFGValidates indirect call targetsFind CFG-valid trampoline; Windows 10 1703 has weaker CFG
ACGNo dynamic code pagesCVE-2017-8637 (patched RS4+); write to existing JIT pages
CIGCode integrity in rendererBlock unsigned DLL injection
No child procCannot spawn child processesUse existing processes; inject into broker

ChakraCore vs Chakra/Edge Differences

AspectChakraCore (ch.exe)Chakra (Edge)
JIT pagesRWX (no ACG)W^X enforced (ACG)
Child processesAllowedBlocked
CIGNot enforcedEnforced
SymbolsAvailable (open source)No symbols

Development strategy: exploit in ChakraCore first → port to Edge in Part 3.


Resources

  • Connor McGarr — Parts 1, 2, 3 (2022-03-11) — connormcgarr.github.io/type-confusion-part-{1,2,3}
  • Bruno Keith — “Attacking Edge Through the JavaScript Compiler” — Nullcon 2019
  • Google Project Zero — CVE-2019-0567 issue tracker
  • Perception Point — CVE-2019-0539 writeup (sister vulnerability)
  • ChakraCore source: github.com/chakra-core/ChakraCore (commit 331aa39)