在2018年5月发布的补丁中,微软在2018年5月修复了Edge 浏览器Chakra引擎中的一个UAF(Use-After-Free)漏洞。这个漏洞(CVE-2018-0946)可能导致Chakra引擎访问一个释放的函数地址,当受该漏洞影响的系统通过微软Edge浏览恶意网页时,恶意网站可能会利用这个释放后的函数来执行任意代码。
当Chakra引擎试图执行由即时(JIT)编译器生成的优化函数代码时,就会产生这个UAF漏洞,相应的编译器在关闭过程中就已经被释放。在这篇文章中,FortiGuard实验室深入分析了微软Edge浏览器Chakra引擎的汇编代码,以揭示导致整个漏洞的根本原因。
理论上,在不同的上下文中对Javascript对象的访问始终由CrossSite类控制。 然而,当DataView类的对象访问另一个上下文中的Chakra 即时编译器生成的优化函数代码时,则你会进行相应的检查。如果对象在相关上下文关闭之后访问已释放的函数代码,则会发生访问冲突。如果已释放的函数地址已经被即时编译器生成的其他函数代码覆盖,则可以利用这个漏洞执行任意代码。
我们使用了以下PoC,它基于谷歌安全研究团队在我们分析期间公开的信息。
分析PoC
由于这是一个典型的UAF漏洞,我们使用了相关函数来演示“使用(Use)”、“释放(Free)”和“使用后释放(Use-After-Free)”的全过程。以下所有的汇编代码均取自chakra.dll(版本号11.00.14393.447)。我补充的注释已经被突出显示。
首先,让我们来看看“使用(Use)”过程。当Chakra引擎执行脚本“let opt = buffer.opt;”时,它会将优化后的函数代码的地址存储到全局属性“opt”中,而Javascript对象将作为作为全局对象的属性被Chakra引擎引用。“PropertyId”是一个int32类型的值,用于检索属性。 让我们来看看地址“0x0f2b5620”处的内存: “0x0f2b5620”是一个ScriptFunction对象,Chakra使用它来存储有关Javascript函数“opt()”的信息。我们可以很容易地发现,它包含了上面代码中的一个FunctionBody对象(“0xfb70360”)。FunctionBody对象的第一个字段是优化后的函数代码的地址: 让我们来看看内存中地址 “0x10e20000”处的优化后的函数代码。
分析部分由即时编译器生成的优化后的代码
接下在,让我们看看“释放(Free)”过程。当“f.src = ‘about:blank’;”被执行时,Chakra引擎将关闭iframe“f”的上下文。在内存地址“0x10e20000”处是优化后的函数代码,会在chakra!Memory::CustomHeap::Heap::DecommitAll被调用时被释放。
“ntdll!NtFreeVirtualMemory”随后将会被调用,以执行实际的释放。接下来,让我们来看看堆栈和堆栈的调用过程:
现在,让我们来看看内存的变化:
之前: 之后:最后,让我们来看看“释放后使用(Use-After-Free)”。优化后的函数代码的地址从全局属性“opt”中检索,其代码会在“let obj = opt();”被执行时执行。chakra!Js::JavascriptOperators::PatchGetMethodFromObject用于从全局属性“opt”中提取优化后的函数代码的地址。
chakra!Js::RootObjectBase::GetRootProperty由chakra!Js::JavascriptOperators::GetPropertyReference_Internal随后调用,以便能够通过使用PropertyId从全局对象中获得全局属性。
在从全局属性“opt”中获得ScriptFunction对象后,Chakra引擎将返回到chakra!Js::JavascriptOperators::PatchGetMethodFromObject:
chakra!Js::InterpreterStackFrame::OP_CallCommon被Chakra引擎用来执行优化后得函数代码。
chakra!Js::InterpreterStackFrame::OP_CallCommon负责从FunctionBody对象中提取优化后得函数代码的地址,随后执行优化后得函数代码:
解决方案
Fortinet发布了IPS签名MS.Edge.Chakra.DataView.Object.Cross.Context.UAF来解决此漏洞。
审核人:yiwang 编辑:边边