导语:在5月发布的补丁中,微软修复了Edge浏览器Chakra引擎中的一个UAF漏洞。这一问题可能导致Chakra引擎访问释放后的函数地址,产生任意代码执行漏洞。
概述
在2018年5月发布的补丁中,微软修复了Edge浏览器Chakra引擎中的一个UAF漏洞。这一漏洞(CVE-2018-0946)可能导致Chakra引擎访问释放后的函数地址,受该漏洞影响的系统通过Microsoft Edge浏览网页时,恶意网站可能利用这一释放后的函数来执行任意代码。
当Chakra引擎试图执行即时编译器(Just-In-Time Compiler,JIT)生成的优化后函数代码时,会产生这一UAF漏洞,相应的编译器在关闭过程中就已经被释放。本文主要对Microsoft Edge浏览器Chakra引擎的汇编代码进行分析,从而揭示出导致此漏洞的根本原因。
理论上,CrossSite类会控制对不同上下文中JavaScript对象的访问过程。然而,当DataView类的对象访问另一上下文中Chakra即时编译器生成的优化后函数代码时,则不会进行相应检查。如果对象在相关上下文关闭后,访问已经释放的函数代码就会发生访问冲突。假如已经释放的函数地址此时已经被即时编译器生成的其他函数代码覆盖,那么就可以利用这一漏洞实现任意代码执行。
对PoC的详细分析
基于Google安全研究团队公开的信息,我们经过分析后编写出此漏洞的PoC,具体如下。
这是一个经典的Use-After-Free漏洞,我们使用相关函数来演示“使用”(Use)、“释放”(Free)和“使用后释放”(UAF)的全过程。以下的汇编代码来自于11.00.14393.447版本的chakra.dll,代码中一些值得注意的地方我均加入了注释。
首先,我们来看“使用”过程。Chakra引擎在执行脚本“let opt = buffer.opt;”时将优化后函数代码的地址存储在全局属性“opt”之中,而JavaScript对象是作为全局对象的属性被Chakra引擎进行引用。“PropertyId”是一个int32类型的值,用来对属性进行检索。
接下来,让我们看看地址“0x0f2b5620”位置的内存:
“0x0f2b5620”是一个ScriptFunction对象,Chakra引擎使用这一对象来存储有关JavaScript函数“opt()”的相关信息。我们很容易看出,其中包含了上面代码中的FunctionBody对象(“0xfb70360”)。FunctionBody对象的第一个字段是优化后函数代码的地址:
接下来,让我们继续分析一下内存中地址为“0x10e20000”中的优化后函数代码。
对部分JIT生成的优化后代码的分析
我们进展到第二步,“释放”。当“f.src = 'about:blank';”被执行时,Chakra引擎会关闭iframe“f”的上下文。在内存0x10e20000的位置是优化后函数代码,会在chakra!Memory::CustomHeap::Heap::DecommitAll调用时被释放。
随后,ntdll!NtFreeVirtualMemory会被调用,从而实现真正的释放。
下一步,让我们来看看栈和栈的调用过程。
接下来,我们查看内存所发生的改变。
在此过程之前:
在此过程之后:
最后,我们来分析一下“释放后使用”。优化后函数代码的地址需要从全局属性“opt”中进行检索,其代码会在“let obj = opt();”语句执行时被执行。chakra!Js::JavascriptOperators::PatchGetMethodFromObject用于从全局属性“opt”中提取优化后函数代码的地址。
在此之后,chakra!Js::JavascriptOperators::GetPropertyReference_Internal会对chakra!Js::RootObjectBase::GetRootProperty进行调用,从而确保能够使用PropertyId从全局对象中获取到全局属性。
在从全局属性“opt”中获取到ScriptFunction对象后,Chakra引擎会返回到chakra!Js::JavascriptOperators::PatchGetMethodFromObject:
chakra!Js::InterpreterStackFrame::OP_CallCommon是Chakra引擎用于执行优化后函数代码的函数。
chakra!Js::InterpreterStackFrame::OP_CallCommon负责从FunctionBody对象中提取优化后函数代码的地址,随后执行优化后函数代码:
解决方案
通过部署IPS等设备,可以有效发现对这一漏洞的利用过程,Fortinet针对这一漏洞对IPS特征库进行了更新,该漏洞所对应的特征名称为:Edge.Chakra.DataView.Object.Cross.Context.UAF。