ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Google V8 engine 대상 VR에의 Structured Approach
    Archive 2025. 4. 13. 13:02

    본 문서는 @xvonfers의 관련 tweet에 기반하며, 한국어를 모국어로 하는 취약점 연구자들이 Google V8을 대상으로 하는 VR을 수행하는 과정에 있어 도움이 되었으면 하는 바램을 담아 @2rr0r4o3의 개인적 경험을 포함하여 작성하였다.


     

    0. 서론

     Google V8 engine은 Chromium / Google Chrome 및 Node.js의 실행 기반을 구성하는 JavaScript engine으로, 고성능 실행을 목적으로 하여 다계층으로 구성된 Just-In-Time Compilelation pipeline(JIT Complie layer)을 채택하고 있다. 내부적으로 Preparser, Parser, Interpreter, JIT Complie layer, Memory management module, Type Feedback system 등 다계층적 구조를 지니며, 각각의 구성 계층은 서로 상이한 Attack vector를 지닌다. 대규모의 Codebase에서 널리 관측되는 이러한 특성으로 인하여 Google V8 engine에 대한 Vulnerability Research(VR)는 단일한 기법 혹은 단순 정적 분석만을 통하여 그 효과성과 효율성을 온전히 담보할 수 없다. 본문은 Google V8 engine을 대상으로 하는 VR에 익숙하지 않은 취약점 연구자들을 위하여 기술적 접근 방법을 5단계로 나누어 정리하고, 이를 구조적으로 제시함으로써 대상에 대한 효과적인 접근법을 문서로써 정립하고자 한다.


    1. JavaScript 및 WebAssembly의 설계와 그 구조적 측면에 대한 심도있는 이해

     JavaScript(JS)는 Dynamic type을 사용하는 언어로, 변수의 Type이 실행 시점에 결정된다. 이러한 특성은 Type 관련 Bug를 유발하는 요인으로 작용할 수 있다. 특히 Type confusion, Hidden class transition to memory corruption, Closure 및 Prototype chain의 구조적 오용 등 JS engine 특유의 요소들에서 기인하는 취약점들은 Realworld에서의 악용으로 이어지고는 한다. 따라서 Google V8 engine(V8)이 수행하는 동작을 이해하기 위한 전제 조건으로서 JS의 언어적 구조, 즉 JS의 설계와 그 구조적 측면에 대한 심도있는 이해가 요구된다. 이는 단순한 문법적 / 기능적인 관점을 의미하는 것이 아닌 Runtime에서의 Variable binding, Execution context, Promise 및 async/await 구문 등의 내부 실행 구조, Event loop 및 Call stack의 전개 순서 등 JavaScript의 설계 및 그 구조적 측면에서 해당 언어가 Runtime에 어떠한 방식으로 동작하는지에 대해 이해함을 의미한다. 이와 같은 지식들은 Google V8 engine에 의해 그 내부에서 Optimization의 단위가 되는 연산 및 객체의 구조가 어떻게 구성되고 변화되는지 이해하는 데 있어 중추를 구성한다.

     아울러 V8은 JavaScript 외에도 WebAssembly(WASM)의 실행 환경을 함께 제공하는 통합된 런타임으로써 기능한다. WASM은 C, C++, Rust 등의 언어로부터 Compile되는 Low-level binary format으로, V8은 WASM를 처리하기 위해 별도의 Compile pipeline을 제공한다. WASM execution path에서는 Liftoff로 대표되는 Compile pipeline가 존재하며, Memory management를 위한 Linear memory로 대표되는 호출 체계를 지닌다. 이와 같은 이질적 환경에 따라서 V8의 실행 특성을 포괄적으로 분석하기 위해서는 JS의 설계 및 구조뿐 아니라, WASM의 설계 및 구조에 대한 심도깊은 이해 역시 동시에 수반되어야 한다.

     

    ECMA-262_15th_edition_june_2024.pdf
    4.58MB
    WebAssembly.pdf
    1.44MB


    2. V8 아키텍처의 다층 구조에 대한 이해

     V8의 내부적 구조는 개략적으로 Preparser, Parser, Igniotion, JIT compilier(SperkPlug, Maglev, TurboFan, TurboShaft, Turbolev, Liftoff, etc), Memory management, Optimization feedback collection, Garbage Collector 등으로 구분할 수 있으며, 각각의 계층은 VR적 관점에서 1개의 분석 단위로 간주할 수 있다.

     

     초기 단계에서는 Parser를 통해 Abstract Syntax Tree(AST)가 생성되며, Interpreter인 Ignition은 이를 Bytecode로 변환하여 실행한다. Sparkplug는 이를 빠르게 Native code로 변환하는 baseline JIT compiler로써 동작한다. Maglev는 Mid-level optimization를 수행하는 light-weight JIT compiler이며, TurboFan은 Type feedback 기반의 추론에 기반하는 복합 연산자들의 lowering 및 speculative optimization등을 수행한다. 최근에는 TurboFan의 SSA based Intermediate Representation을 대체하기 위한 TurboShaft 및 TurboFan을 대체하고 Maglev와 TurboShaft를 연동하는 Control Flow Graph based JIT compiler로서 Turbolev가 도입 중에 있다. 이와 같은 JIT optimization path의 세분화는 각각의 구성요소마다 Optimization 전략, lowering 기법, Type Verification 방식 등에 차이를 지니게 하므로 연구자는 각 계층의 기능적 요소와 내부적 동작 구조 -입력 및 출력 노드 구조와 transformer의 특성 등- 을 정확히 이해해야 한다.

     

     또한 Hidden Class와 Inline Cache는 JIT optimization path에서 실행 중인 객체의 구조적 안정성이 충족되었다는 전제로 속성 접근을 최적화하지만, Transitions 과정에서 공격자가 이를 오용/악용 가능할 경우 Type confusion을 유발할 수 있다. 더불어 TypedArray, ArrayBuffer, WebAssembly, V8 Sandbox 등은 V8이 외부 메모리 공간과 상호작용하는 주요 인터페이스로 기능하며, 각각이 갖는 접근 제약, buffer detach 여부, bounds check 유무 등에 따라 고위험성을 지니는 공격 벡터로써 작용할 수 있다. 특히 WebAssembly는 Linear memory, 개별 Module 단위의 isolation을 기반으로 동작하기 때문에, 분석자는 JavaScript runtime의 내부 동작뿐 아니라 이와 이질적인 측면을 지니는 WASM의 Runtime model 또한 동시에 고려해야 한다. 상술한 여러 요소를 대상으로 하는 통합적 관점에서의 분석은 V8의 Heap allocation, GC Trigger condition, Memory boundary check 등을 이해하는 데 있어 결정적인 기반이 된다.


    3. 기존 취약점 사례 분석

     공개된 상태의 기존 취약점 최초 제보 보고서와 사후에 이를 면밀히 분석한 보고서를 탐독하여 숙지하는 일련의 과정은 과거에 발생한 취약점과 그것이 유도된 과정을 추적함으로써 실질적으로 취약점이 유도되는 시나리오와 악용의 전반적 전개 과정을 학습할 수 있게 한다. 이 과정은 단순한 사례 수집 수준에서 그쳐서는 안되며, 각각의 기존 취약점에 대한 발생 기전을 깊이 있게 이해하고 취약한Type cast 또는 Optimization path, 등을 코드 수준에서 식별하여 구체적인 발생 조건 하에서 취약점이 실제로 발생하는지 추적하는 등의 심도있는 분석을 수반하여야 한다. 이와 같은 분석과정은 commit hash를 통해 기존 취약점의 최초 보고 시점, 혹은 Introduce 시점과 동일한 Source Code를 유지한 상태에서 PoC의 작성 및 실행을 통한 재현을 시도해야 한다. 이를 통해 V8에서 발생하는 type confusion, out-of-bounds access, use-after-free, heap corruption, integer overflow, logic bug 등 주요 취약점 유형별 공격 패턴을 일반화할 수 있으며, 이는 이후 fuzzing input 구성 시 효과적인 제약조건을 수립할 수 있도록 하는 요인으로 작용할 뿐만 아니라 실제 취약점 식별 후 악용으로 이어질 수 있음을 증명할 수 있는 역량을 키우는 과정으로써 기능한다.

    https://tracker.ret2happy.com/

     

    Chrome Bug Tracker

    Solana CMsnJ8QGN41PzihoZDs4pHP45FJpmn6FMMmGargrK9Zt

    tracker.ret2happy.com


     4. 최신 Commit에 대한 추적과 분석을 통한 0-day 취약점 식별

     V8의 최신 Commit은 GitHub 및 Chromium Gerrit을 통해 공개되며, 해당 commit으로 말미암아 발생하는 변화를 지속적으로 추적하는 것은 새로운 취약점이 포함될 가능성이 있는 코드 블록 및 실행 흐름을 식별하는 데에 있어 일정 수준 이상의 효과성을 보인다. Function 단위 또는 Opcode handler 수준에서 수정이 발생한 경우, 해당 Commit의 원인과 그 영향 범위을 판단하기 위한 추론에 있어 충분한 신뢰성을 담보할 수 있는 근거는 단일 Commit에 대한 이해로는 충분하지 않은 경우가 많으며, 의미론적 차원에서 일련으로 연결된 다수의 Commit을 시각적 Graph에 기반하여 분석하는 것이 효과적이다. 이때 Sourcetrail을 통한 Call graph visualization과 Doxygen을 활용한 code documentation는 구조적 변화의 영향을 탐지하고, 최적화 파이프라인 내의 propagation 경로를 추적하는 데 유용하게 작동한다. 이를 통해 과거 유사한 수정이 이루어진 경로와의 유사성을 비교하거나, 실수로 삭제된 검증 로직의 여파를 역으로 추적하는 것이 가능하다.

    Commits · v8/v8 · GitHub

     

    GitHub - v8/v8: The official mirror of the V8 Git repository

    The official mirror of the V8 Git repository. Contribute to v8/v8 development by creating an account on GitHub.

    github.com

    project:v8/v8 · Gerrit Code Review

     

    https://chromium-review.googlesource.com/q/project:v8/v8

     

    chromium-review.googlesource.com


    5. Fuzzing 등 Software test automation technique 기반 취약점 탐색과 고도화

     자동화된 취약점 식별을 위해 JS engine을 Target으로 하는 Fuzzer인 Fuzzilli를 기반으로 하는 Fuzzing이 널리 사용된다. Fuzzilli는 FuzzIL이라는 고유의 IR로 프로그램을 생성하고, 이를 JS로 Lifting한 후 Target engine에 입력하는 과정을 반복함으로써 충돌을 유도한다. 이 과정에서 Coverage Instrumentation을 통해 Code Coverage를 추적하며, Crash가 발생한 경우 해당 input은 triage 및 minimize 단계를 거쳐 Reproducer로 저장된다.

     특정 구성요소를 Target으로 하는 효과적인 Fuzzing을 수행하기 위해 연구자는 Fuzzilli 혹은 libfuzzer 등 여타의 opensource fuzzer에 기반하여 custom fuzzer를 작성하고, Target 내 특정 경로에 도달하는 조건을 부여하는 등 다양한 접근을 통해 커버리지를 확장하고 Crash의 발생 확률을 증가시킬 수 있다. 또한 AddressSanitizer (ASAN), UndefinedBehaviorSanitizer (UBSAN), ThreadSanitizer (TSAN) 등의 Sanitizer를 통합하여 Crash를 탐지할 수 있다. 최종적으로는 coverage-guided fuzzing을 기반으로 Target oriented feedback loop를 구성함으로써 효과적이라 식별된 input을 유용하게 활용함으로써 보다 정밀하게 넓은 공간을 탐색하는 Fuzzing infrastructure를 구축할 수 있다.

    GitHub - googleprojectzero/fuzzilli: A JavaScript Engine Fuzzer

     

    GitHub - googleprojectzero/fuzzilli: A JavaScript Engine Fuzzer

    A JavaScript Engine Fuzzer. Contribute to googleprojectzero/fuzzilli development by creating an account on GitHub.

    github.com


     

    6. 결론

     V8을 대상으로 하는 VR은 피상적 수준에서의 단순한 접근만으로는 그 수행이 난해하며, JS의 설계 및 그 구조에 대한 심도 있는 이해와 Runtime에서의 Optimization flow, Type Feedback path, Memory model 등 다수의 구성요소에 대한 정밀한 분석ㅇ,ㄹ 요구한다. 본문에서 제시한 구조적 접근법은 V8 내 각 계층의 구성요소를 대상으로 하는 분석이 취해야 할 방향성을 명확히 제시하고, 이를 도구 기반 시각화 및 문서화와 기존 취약점 분석 및 최신 Commit에 대한 추적에서 Fuzzer의 활용으로 이어지는 유기적인 방법론으로 구성된다. 본문이 부디 한국어를 모국어로 하며 V8 등 JS engine에 익숙하지 않은 취약점 연구자들에게 좋은 시작으로써 기능하길 희망하며 마무리한다.

    'Archive' 카테고리의 다른 글

    Computer Science 자료 목록  (0) 2024.05.05
    Linux kernel N-day vulnerability analysis  (0) 2024.01.14
    Linux kernel  (0) 2024.01.14
Designed by Tistory.