目标达成 感谢每一位支持者 — 我们达成了 100% 目标!

目标: 1000 元 · 已筹: 1336

100%

CVE-2021-38003 PoC — Google Chrome 缓冲区错误漏洞

来源
关联漏洞
标题: Google Chrome 缓冲区错误漏洞 (CVE-2021-38003)
Description:Google Chrome是美国谷歌(Google)公司的一款Web浏览器。V8是其中的一套开源JavaScript引擎。 Google Chrome存在缓冲区错误漏洞,攻击者可利用该漏洞危及受影响的系统导致系统异常。
Description
Write Up & Exploitation For CVE-2021-38003
介绍
# CVE-2021-38003

This analysis documents my research into CVE-2021-38003, a vulnerability in V8’s `Map` object handling, using d8 9.5.172.21 on an ARM64 Ubuntu VM. 
My approach involves testing a reproducer, analyzing crashes with GDB, examining V8 source code, and refining the proof-of-concept (PoC) to try to achieve RCE.

## Reproducing the Vulnerability

### Basic System Environment & Setup 
- OS: Ubuntu 22.04 ARM 64
- V8: 9.5.172.21

<img width="919" alt="vulnerable_version" src="https://github.com/user-attachments/assets/51d62a83-601f-4540-a632-884db00671d8" />

I began by running the provided PoC (`poc.js`) in d8 to confirm the vulnerability in version 9.5.172.21, known to be affected by CVE-2021-38003. 

<img width="1426" alt="initial_poc_running" src="https://github.com/user-attachments/assets/bc736142-a3ed-4cb1-98ac-d60116fe2ddb" />

The output verified the V8 version and revealed a crash in `ordered-hash-table.cc` at line 290, where a debug check failed: `table->NumberOfDeletedElements() == removed_holes_index (2 vs. 1)`. This crash, occurring in `Runtime_MapShrink`, confirmed the PoC’s effectiveness.

The PoC manipulates a JavaScript `Map` by inserting a “hole” value with `%TheHole()`, deleting it multiple times next to another key, and iterating `0x3000` times to stress the heap. A garbage collection call (`gc()`) risks freeing referenced memory, and a `map1.set(foo_arr, 0xffff)` operation triggers resizing, exposing the bug. The `%DebugPrint(foo_arr)` call checks `foo_arr`’s state for corruption. The mismatch in deleted elements suggests heap corruption, as V8 processes an invalid `OrderedHashMap`, a structure for storing `Map` key-value pairs. In a release build, absent debug checks, this could enable exploitable memory errors, supporting possible RCE efforts.

This step validated the PoC, laying the beginning for possible RCE exploration and codebase navigation.

## Debugging with GDB

To investigate the crash, I used GDB to examine the `OrderedHashMap` state at the point of failure:

<img width="1444" alt="initial_gdb_debug" src="https://github.com/user-attachments/assets/04e95713-086c-45c7-853a-9da117db0591" />
<img width="1000" alt="initial_gdb_debug" src="https://github.com/user-attachments/assets/40d8dee2-6a3c-4572-8f39-77d6e9842e75" />

Execution halted at the `DCHECK` failure, with `NumberOfDeletedElements()` at 2 and `removed_holes_index` at 1, confirming the inconsistency. The `OrderedHashMap` object, with a pointer value of 12678878763661, was valid but corrupted. The stack held valid addresses, indicating heap-based corruption, and `x0` was null, as `table` was stack-passed. The backtrace connected `Runtime_MapShrink` to `OrderedHashTable::Shrink` and `OrderedHashMap::Rehash`, showing the PoC’s `set` operations triggered a `Map` resize.

The `OrderedHashMap`’s corrupted state, driven by `delete %TheHole()` and garbage collection, pointed to potential type confusion or memory writes, key for RCE. The backtrace also mapped JavaScript to C++ functions in `runtime-collections.cc` and `ordered-hash-table.cc`, facilitating codebase navigation.

## Exploring V8’s Source Code

I analyzed `ordered-hash-table.cc` and `runtime-collections.cc` to identify the bug’s root cause:

- ordered-hash-table.cc
<img width="964" alt="Screenshot 2025-05-19 at 16 49 05" src="https://github.com/user-attachments/assets/6b69587f-e4a7-470d-8694-044a4416675b" />

- runtime-collections.css
<img width="917" alt="Screenshot 2025-05-19 at 16 52 31" src="https://github.com/user-attachments/assets/b7c5b9e6-b8af-4156-9684-c2130e2fb6a8" />


In `ordered-hash-table.cc`, `OrderedHashTable::Rehash` iterates `Map` entries, tracking deleted elements with `removed_holes_index`. The `DCHECK` at line 290 fails when `NumberOfDeletedElements()` (2) exceeds `removed_holes_index` (1). `Runtime_MapShrink` in `runtime-collections.cc` initiates rehashing during resizing.

The PoC’s sequence—`m.set(%TheHole(), 1); m.delete(%TheHole()); m.delete(%TheHole())`—creates a `Map` with two deleted entries but one hole counted, corrupting the `OrderedHashMap`. Garbage collection and heap stress amplify this, risking out-of-bounds writes or type confusion in a release build. This analysis confirmed the bug’s exploitability and demonstrated my ability to trace JavaScript operations to C++ functions.

## Refining the PoC for Possible RCE

### First PoC Refinement

I made `exploit_attempt1.js` to spray the heap with 5,000 `ArrayBuffer` objects, including a crafted `ArrayBuffer` whose `DataView` set a pointer to `0x4141414141414141`, aiming to plant a fake object exploitable via `OrderedHashMap` corruption. To induce type confusion, I treated `foo_arr`, a floating-point array, as an `ArrayBuffer` through a `DataView`, seeking invalid memory access. A `map1.set(foo_arr, 0xffff)` call stressed the `OrderedHashMap` to trigger resizing errors.

<img width="964" alt="Screenshot 2025-05-19 at 16 49 05" src="https://github.com/user-attachments/assets/414d0d66-0139-4b86-acec-63ba90405f2e" />

The PoC triggered a `DCHECK` failure at `ordered-hash-table.cc:290`, where `table->NumberOfDeletedElements()` (2) mismatched `removed_holes_index` (1). The d8 crash reported a fatal error in `Runtime_MapShrink`, with a stack trace through `OrderedHashTable::Shrink` and `OrderedHashMap::Rehash`. GDB revealed no stack or register corruption, as the debug check halted execution before `DataView` operations. This highlighted the debug build’s protective assertions but confirmed the PoC’s potential to disrupt V8’s heap, a step toward RCE in a release build.


### Second PoC Attempt: Experimental `DCHECK` Bypass

I made `exploit_attempt2.js`To reveal the corruption’s full impact, I commented out the `DCHECK` in `ordered-hash-table.cc:290`, **recognizing that source modification isn’t viable in real-world exploits**. This experiment mimicked a release build, where `DCHECK`s are absent, allowing the corruption to propagate.

I modified the source, rebuilt d8 after resolving a build directory issue, and ran the PoC:

<img width="964" alt="Screenshot 2025-05-19 at 16 49 05" src="https://github.com/user-attachments/assets/0ec8fccf-9baa-4df5-a096-c3096b8d88ec" />


The result was a new crash in `builtins-collections-gen.cc:790`, where a `CSA_ASSERT` failed during `m.delete(1)` in the `getmap` function’s loop (0x4000 iterations). The assertion, checking an entry’s index against the `Map`’s element counts, failed due to the corrupted `OrderedHashMap` from `delete %TheHole()` calls. The heap, sprayed with 20,001 objects including a fake pointer (`0x4141414141414141`), was stressed by `map1.set` operations, but the crash preceded the `DataView` type confusion attempt.

This crash marks significant progress toward RCE. The corruption’s impact on V8’s optimized `Map.delete` builtin suggests potential for out-of-bounds access or type confusion in a release build, where the `CSA_ASSERT` would be absent. The early crash limited the `DataView`’s role, but the heap spraying’s effectiveness positions the PoC for further escalation with minimal tweaks, such as adjusting loop iterations or testing in a release environment.

**Limitations**: The `DCHECK` bypass, while insightful, **deviates from real-world exploit constraints, a choice I made just for experimentation**. 

## Conclusion

My analysis of CVE-2021-38003 demonstrated the vulnerability’s heap corruption potential and advanced toward RCE through systematic PoC refinements. I reproduced the bug, pinpointed its cause in `OrderedHashMap`’s handling of `delete %TheHole()`, and navigated V8’s codebase to trace JavaScript to C++ functions,  addressing the second screening question. Three PoC iterations, culminating in a `CSA_ASSERT` crash after an experimental `DCHECK` bypass, showed progress toward RCE, meeting the first question’s challenge despite debug build limitations. The corruption’s impact on optimized builtins underscores its exploitability in production environments. 
文件快照

登录后查看神龙缓存的 POC 文件快照

登录查看
备注
    1. 建议优先通过来源进行访问。
    2. 本地 POC 快照面向订阅用户开放;当原始来源失效或无法访问时,本地镜像作为订阅权益的一部分提供。
    3. 持续抓取、验证、维护这份 POC 档案需要不少投入,因此本地快照已纳入付费订阅。您的订阅是让这份资料能继续走下去的关键,由衷感谢。 查看订阅方案 →