0x01-背景
2019 年 11 月 1 日,卡巴斯基报道Operation WizardOpium组织使用在野chrome0day进行攻击,
2019 年 10 月 30 日,卡巴斯基在职人员Anton.M.Ivanov在谷歌的issue list中上报该漏洞,并给出了poc,报告中虽然文件名为exploit.zip,但实际上的确是poc。2020 年 5 月 28 日,卡巴斯基两位作者BORIS LARIN和ALEXEY KULAEV对整个exp的实现给了详细的解释,不过仍旧没有给出完整exp。
本文在以上基础上,对CVE-2019-13720的exp做了完整拼装和实现,并最终弹出记事本。同时记录了在实现过程中需要注意的部分。
0x02-从任意读写开始
从卡巴斯基公开的代码进行拼凑,已经容易实现任意读写。在任意读写后,关键部分定位wasm的实现,卡巴斯基并没有给出代码。我在拼凑过程中,发现缺少关键部分,也是感觉很遗憾。以往的Chrome PartitionAlloc利用,一般是借助wasm构造LeakObj,泄露对象地址,然后定位wasm,结合任意读写实现最终exp。Operation WizardOpium在exp中通过创建FileReader,然后借助getPartitionPageFreeListHeadEntryBySlotSize函数解析PartitionAlloc,同时因为已知要分配对象的大小,来预测分配到的目标地址,最后借助fileReader.onerror = wasmFuncA;
实现执行shellcode。
本文在wasm定位过程中没有采用该思路。而是借助yytgravity笔记中提示的思路实现wasm定位。不过在实际操作中,仍旧需要注意一些关键的点。
0x03-wasm定位
一句话描述定位思路是isolate->heap_->old_space_->allocation_info_->top_->wasm->rwx
这里需要注意的是,定位出的top,在我们写exp过程中,随着新函数的申请、垃圾回收等操作,会动态改变。后面会提示如何规避该问题。
从卡巴斯基给出的exp,可以直接实现chrome_child基址的计算。如此,可定位到g_main_thread_per_isolate_data,而isolate的地址可以从g_main_thread_per_isolate_data计算得到。如下图所示:
windbg中鼠标点击下划线符号即可解析成员变量,这里的解析路径是:
g_main_thread_per_isolate_data->isolate_holder_->isolate
此时isolateholder持有的成员变量类型为v8::Isolate*
,这里如果按该结构进一步解析,实际上并不能获得heap_
成员信息。如下windbg中来进一步解析heap_
成员。
dx -r1 ((chrome_child!v8::internal::Isolate*)heap_addr)
在heap中,可根据old_space解析allocation_info,然后进一步获取top地址:
最后根据top,计算wasm的偏移,至此,我们便可不再依赖leakObj泄漏wasm对象,仅依赖任意读写便可实现exp利用。
0x04-补充
不过由于该漏洞是UAF,其中稳定性并不太理想,这里借助浏览器特性,会对不同站点使用不同进程思路,将exp放在iframe中,并多次刷新即可。
在该exp实现过程中发现,提前进行垃圾回收有利于加快webaudio的执行和崩溃,于是在main函数前,多次gc,在实际exp撰写过程中,可尝试类似技巧,增加exp的稳定性。
由于top变量容易改动,可根据需要,最后申请wasm对象,申请完后,立刻借助任意读写定位rwx内存即可。
最后附上完整exp和视频。
0x05-参考链接
https://securelist.com/the-zero-day-exploits-of-operation-wizardopium/97086/
https://bugs.chromium.org/p/chromium/issues/detail?id=1019226