V8堆沙箱绕过方法分析总结
一、What is Sandbox 沙箱机制(Sandboxing)是一种安全技术,用来隔离运行中的应用程序或代码,使其在受限的环境中执行。这种机制的目的是限制应用程序或代码与系统资源(如文件系统、网络、硬件)的直接交互,从而防止恶意软件或不受信任的代码造成安全威胁或数据泄露。 当提到chrome沙箱时通常会想到的是用于限制应用程序或代码与系统资源的直接交互的沙箱,而在实际的漏洞利用层面内存安全仍然是一个重要问题,在众多chrome可利用的漏洞中,v8漏洞可以说占到大多数,而V8漏洞很少是"经典"的内存损坏错误(释放后使用、越界访问等),而是微妙的逻辑问题,反过来再利用这些问题来损坏内存。因此,现有的内存安全解决方案在很大程度上并不适用于V8,于是在此背景下衍生出了v8 Sandbox。本文主要对v8 sandbox的一些绕过方法进行汇总分析。 二、V8 Sandbox V8沙箱是一个基于软件的沙箱,其背后的基本思想是隔离 V8堆内存,使任何内存损坏都不会"扩散"到进程内存的其他部分,从而增加v8漏洞的利用难度。具体实现方式有两种: 第一种,如果buffer位于沙盒内,就将40位的地址偏移左移24位后得到的64位结果写入相应字段地址中: disable sandbox: enable sandbox: 通过对%DebugPrint具体的实现代码下断,可以找到具体的decode过程,首先从指定字段地址出得到64位值(sandboxed_pointer),再将sandboxed_pointer右移24位(kSandboxedPointerShift)得到偏移(offset),最后将offset与基址(cage_base)相加得到真实的地址指针: 第二种,如果buffer位于沙盒外,则会将指定字段地址内的值作为索引,通过指针表间接的引用buffer: 例如blink对象,在v8中所有的blink对象都分配在v8堆外,并以api对象的形式在v8中表示: V8 api对象实际上是blink对象的包装器,其中embedder fields字段存储内容用实际为一个表索引,此索引位置保存着对应的blink对象的实际地址及其类型: 同样也可以通过对%DebugPrint实现下断找到具体的decode过程: 三、V8 Sandbox Breaking 3.1 signature confusion breaking sandbox 在V8 webassembly中,wasm模块导出函数主要由函数签名(signature)和函数实现(call_target)组成,假设有以下代码,此代码可以导出read_0与read_1两个函数: (module (memory 1) (func $read_0 (export "read_0") (param $offset i32) (result i64) (i64.load (local.get $offset) ) ) (func $read_1 (export "read_1") (param $var1 i64) (result i64) i64.const 0 ) ) 在js代码中使用read_0(0x41)触发对read_0函数的调用,然后对Builtins_JSToWasmWrapper下断可以得到signature与call_target的获取过程: 先通过函数对象获取shared_info字段,其中r14寄存器存的一直都是基地址,而rdi则是函数对象地址: 通过shared_info字段得到function_data: 通过function_data获取signature,signature对象不在沙盒中,所以是通过外部表的形式间接引用的,所以此处得到的是一个表索引: 通过function_data获取func_ref: 通过func_ref可以得到internal,internal是一个外部对象,而call_target就在internal中并且也是一个外部对象,所以都只能得到一个表索引: 最后Builtins_JSToWasmWrapperAsm函数会通过call rdx进入call_target指向的地址,在通过几个Jmp后会进入真实的jited代码,rax为传入的地址偏移:...