Sandboxing V8
Samuel Groß - saelo@google.com
What?
Lightweight, in-process sandbox for V8
Attacker then needs:
V8 Vulnerability +
V8 Sandbox escape +
Chrome Sandbox escape
Why?
JavaScript engines are very attractive for attackers…
Fundamental problem: JS engine bugs are often 2nd order vulnerabilities
Root cause is a logic issue in a compiler or the runtime environment...
which can then be exploited for (more or less arbitrary) memory corruption at runtime
=> Powerful “superbugs”
CSE
(common subexpression elimination)
BCE
(bounds-check elimination)
Range Analysis
“Pureness” Analysis
Type Safety
Spatial Memory Safety
Temporal Memory Safety
Type-Check Elimination
Type Inference
GC Modelling
Write Barrier Elision
Array Length Computation
Register Allocation
Lowering
Runtime State
LICM
(loop-invariant code motion)
Optimization
Analysis
“Breaks”
Pattern Matching
Other
GVN
(global value numbering)
Alias Analysis
How?
Basically: No more Pointers in V8! :)
Lower Addresses
Higher Addresses
0xa38000000000
V8 Sandbox (e.g. 1TB)
0xa48000000000
Lower Addresses
Higher Addresses
0xa38000000000
V8 Sandbox (e.g. 1TB)
0xa48000000000
0xa38100000000
V8 Heap (4GB)
Lower Addresses
Higher Addresses
0xa38000000000
V8 Sandbox (e.g. 1TB)
V8 Heap (4GB)
0xa48000000000
0xa38100000000
HeapObj4
ExternalObj1
ArrayBuffer1
Wasm Memory
Cage (10GB)
HeapObj5
HeapObj2
HeapObj3
HeapObj1
Lower Addresses
Higher Addresses
0xa38000000000
V8 Sandbox (e.g. 1TB)
V8 Heap (4GB)
0xa48000000000
HeapObj4
ArrayBuffer1
32-bit offset (compressed pointer)
Wasm Memory
Cage (10GB)
HeapObj5
HeapObj2
HeapObj1
HeapObj3
0xa38100000000
ExternalObj1
Lower Addresses
Higher Addresses
0xa38000000000
V8 Sandbox (e.g. 1TB)
V8 Heap (4GB)
0xa48000000000
HeapObj4
ArrayBuffer1
32-bit offset (compressed pointer)
Wasm Memory
Cage (10GB)
40-bit offset from sandbox base
HeapObj5
HeapObj2
HeapObj1
HeapObj3
0xa38100000000
ExternalObj1
Lower Addresses
Higher Addresses
0xa38000000000
V8 Sandbox (e.g. 1TB)
V8 Heap (4GB)
0xa48000000000
HeapObj4
ExternalObj1
ArrayBuffer1
~20-bit
Index
32-bit offset (compressed pointer)
Wasm Memory
Cage (10GB)
40-bit offset from sandbox base
HeapObj5
HeapObj2
HeapObj1
HeapObj3
0
Type + Pointer
External Pointer Table
Type + Pointer
1
0xa38100000000
Performance?
void TurboAssembler::DecodeSandboxedPointer(const Register& value) {
// Sandbox overhead: single shift+add instruction
Add(value, kPtrComprCageBaseRegister,
Operand(value, LSR, kSandboxedPointerShift));
}
Implications (Beyond V8)
Lower Addresses
Higher Addresses
0xa38000000000
0xa48000000000
0xa38100000000
Everything in here is now
UNTRUSTED
Implications Beyond V8
int idx = ...;
v8_obj->SetInternalField(0, v8_num(idx));
...
...
uint idx = v8_obj->GetInternalField(0).to_uint();
return array[idx];
Implications Beyond V8
int idx = ...;
v8_obj->SetInternalField(0, v8_num(idx));
...
...
uint idx = v8_obj->GetInternalField(0).to_uint();
return array[idx];
Implications Beyond V8
int idx = ...;
v8_obj->SetInternalField(0, v8_num(idx));
...
...
uint idx = v8_obj->GetInternalField(0).to_uint();
CHECK_LT(idx, size_of_array); // Simple fix ...
// ... and a fuzzer will find this easily, at least ...
return array[idx];
Goals of the V8 Sandbox
Goals of the V8 Sandbox
V8-based Chrome exploit chains now requires 3 instead of 2 vulnerabilities
Goals of the V8 Sandbox
V8-based Chrome exploit chains now requires 3 instead of 2 vulnerabilities
V8 sandbox escape bug is likely a “standard” memory corruption bug
State of the V8 Sandbox (Dec. 2022)
State of the V8 Sandbox (Dec. 2022)
State of the V8 Sandbox (Dec. 2022)
Summary
V8 Sandbox architecture breaks down a hard problem�(secure and fast JS engine) into lots of smaller problems with�“relatively” easy solutions (OOB accesses, TOCTOU issues, UAFs, …).