IE 0day分析(CVE-2020-1380)

  • A+
所属分类:安全文章

IE 0day分析(CVE-2020-1380)

文章作者:FPX_niupi

微软于本月(8月)修补了一个针对Internet Explorer 11的0day--CVE-2020-1380。这是一个存在于IE中JavaScript引擎jscript9.dll中的UAF漏洞。在过去的几年中,我们观察到对IE的0day攻击通常利用vbscript.dll(译注:IE中vbscript的解析引擎)和jscript.dll运行shellcode。二这次目标更改为了jscript9.dll,并使用现代JavaScript引擎的JIT引擎来触发该错误。因此,我决定深入研究jscrtip9.dll JIT引擎以尝试找出这个漏洞的根本原因。


Jscirpt9.dll的解释执行概述


Jscript9.dll是IE默认的JavaScript解析引擎,从IE 9开始替换了原JS解析引擎jscript.dll。图1显示了jscript9.dll的解释执行过程。


IE 0day分析(CVE-2020-1380)


1. jscript9.dll解释执行过程


通常,jscript9.dll中解释执行的JS代码有五个主要步骤:


1. 解析器解析JavaScript代码以获得抽象语法树(AST)。


2. 字节码生成器(ByteCodeGenerator)遍历AST并生成字节码(ByteCode)。


3. 解释器是执行字节码(ByteCode)的虚拟机。执行字节码(ByteCode)时会收集诸如类型信息之类的配置文件数据。


4. 当多次调用某些代码段时(例如在for循环中),解释器将字节码(ByteCode)和配置文件数据发送到后端的JIT引擎以生成机器码,然后将字节码(ByteCode)入口点替换为生成的机器码地址。


5. 当执行机器代码时,如果某些状态违反了配置文件假设,则机器代码将向解释器提供援助以便再次执行字节码(ByteCode)从而避免安全问题。


定位机器码


在讨论本漏洞前,我们首先需要找到由JIT引擎生成的机器码。for循环通常在解释器中会调用JIT引擎(译注:因为反复执行同一代码,直接执行机器码会更快)。图2显示了可以调用JIT的简单JavaScript代码:


IE 0day分析(CVE-2020-1380)

2.一个简单的JavaScript代码片段触发了JIT


当循环次数大于某些阈值时(图3中的代码片段中为0x32),循环主体和内部调用函数opt将被发送到后端的JIT引擎作业队列以生成优化的机器码: 


IE 0day分析(CVE-2020-1380)

3.前端JIT触发器的代码片段


后端的JIT引擎线程从队列中获取作业,最后调用jscript9!Func::Codegen生成优化的机器码:


IE 0day分析(CVE-2020-1380)

4.后端JIT代码生成的代码片段


后端JIT引擎经过几个步骤来生成优化的机器代码,例如:构建中间表示(IR)、内联、构建CFG、数据流分析、分配寄存器、布局、编码等:


IE 0day分析(CVE-2020-1380)

5. Func :: Codegen的代码片段


生成优化的机器代码后,它将用于替换字节码(ByteCode)循环主体。接下来调用for循环时,将改为在函数Js::InterpreterStackFrame::CallLoopBody中调用机器码:

 

IE 0day分析(CVE-2020-1380)

6.循环主体机器代码


最后,for循环主体的机器码将调用内部调用函数opt的机器码,我们可以在此处看到:


IE 0day分析(CVE-2020-1380)

 

7. Opt功能机器代码


译注:以上JavaScript解释执行过程很值得一看,因为所有浏览器解释执行JavaScript都主要如此。


CVE-2020-1380的分析


CVE-2020-1380的POC如图8所示(注:https://securelist.com/ie-and-windows-zero-day-operation-powerfall/97976/):


IE 0day分析(CVE-2020-1380)

8. CVE-2020-1380PoC


以下步骤可以触发该漏洞:


1. for循环使得opt函数传给JIT引擎。


2. 在函数opt中,三行参数对象操作可以将value2设置 为value1(注:自行搜索Javascript function arguments),然后Float32Array第一个元素arr [0]由value1设置。


3. 将函数opt传到JIT引擎后,它将参数value2从整数0x1337更改为具有valueOf回调函数的对象。


4. 在函数opt的最后一次调用中,由于flag参数的值为0,因此不执行“ if(flag == 1)”的基本块,该块将value2设置为arr [0]。因为对象替换了value2,所以发生了隐式类型转换,所以会在机器码中调用valueOf回调函数。(译:这里可能很多人不清楚,“该块将value2设置为arr [0]。因为对象替换了value2,所以发生了隐式类型转换“,这句是说,根据arguments对象的定义,我们可以知道这个对象是本次函数调用所传进来的参数序列,那么3行arguments操作可以使得arguments对象只有一个成员,且arguments[0]为value2,也就是理解为本次调用的第一个参数为value2的值)


JavaScript是一门动态语言,可以在其中隐式转换变量的类型或属性。生成的机器码若直接进行JavaScript隐式调用而不进行任何检查的机器码是不可信的。Jscript9.dll使用函数ExecuteImplicitCall来保证JavaScript隐式调用的安全。


首先,将操作参数的三行JavaScript代码更改为“ arguments [0] = value2”,其效果相同。图9显示了生成的JIT代码段。


IE 0day分析(CVE-2020-1380)

9. JIT代码片段


在调用类型转换函数

jscript9!Js::JavascriptConversion::ToFloat_Helper之前,将设置地址为

0x140F3F68和0x140F3E86的标志的值。存储在0x140F3F68中的标志是

ImplicitCallFlags,

存储在0x140F3E86中的另一个标志是DisableImplicitFlags。


DisableImplicitFlags设置为3


(DisableImplicitCallFlag | DisableImplicitExceptionFlag),

这意味着从要调用的JavaScript代码(例如valueOf)进行隐式调用时,不允许将类型转换为float。


函数

Js::JavascriptConversion::ToFloat_Helper检查输入类型,以决定选择哪种类型转换路径。


因为value2是一个对象,所以将调用Js::DynamicObject::ToPrimitive,然后最终将调用ExecuteImplicitCall:


IE 0day分析(CVE-2020-1380)

10. Js :: DynamicObject :: ToPrimitive的代码片段


ExecuteImplicitCall

会检查DisableImplicitFlags;如果该值不为数字0,则不会调用JavaScript隐式调用而直接返回undefined。最后,机器码将转交给Interpreter并安全地在Interpreter中调用隐式调用:


IE 0day分析(CVE-2020-1380)

11. ExecuteImplicitCall的代码片段


但是,当用三行参数操作的JavaScript代码代替了“ arguments [0] = value2”时,我们可以看到生成的机器码直接调用Js :: 

JavascriptConversion::ToFloat_Helper而未设置DisableImplicitFlags:

 

IE 0day分析(CVE-2020-1380)

12. JIT代码片段


最后,隐式调用valueOf将直接从机器码中调用。攻击者可以利用此无检查回调机会来触发UAF漏洞,例如通过Worker线程将TypedArray的ArrayBuffer内存清除:


IE 0day分析(CVE-2020-1380)

13. UAF触发器的代码片段


为什么三行参数操作就可以去掉DisableImplicitFlags设置机器码引起了我的好奇心。我认为后端JIT GlobOpt阶段中arguments[0]的类型推断错误是根本原因。JIT引擎不知道Array.prototype.push的副作用,该副作用可用于更改arguments[0]的类型。在执行Array.prototype.push操作后应终止arguments[0]的类型,以避免出现这种类型推断错误的问题。


其他方法也可以触发此错误,例如使用

Array.prototype.splic

或使用

Float64Array

调用

Js::JavascriptConversion::ToNumber_Helper

的转换路径。

此错误也已在8月补丁中一同修补。


IE 0day分析(CVE-2020-1380)

14. Float64Array的崩溃快照


结论


在过去的几年中,针对IE的0day攻击通常利用vbscrpt.dll和jscript.dll漏洞。CVE-2020-1380比较特别,因为它针对jscript9.dll的JIT引擎(译注:其实也不特别,浏览器漏洞早就这样了,不知道作者为何会这么说)。JIT漏洞是V8、JavascriptCore、Spidermonkey和Chakra等现代JavaScript引擎中的常见问题。也许攻击者现在正在选择针对IE的JIT引擎进行攻击。

 

原文:

https://www.trendmicro.com/en_us/research/20/h/cve-2020-1380-analysis-of-recently-fixed-ie-zero-day.html

IE 0day分析(CVE-2020-1380)


推荐文章++++

IE 0day分析(CVE-2020-1380)

*CVE-2017-0261及利用样本分析

*Oracle cve 2020-14644 分析利用以及回显思路(附工具下载)

*CVE-2018-8639 简单利用


IE 0day分析(CVE-2020-1380)

IE 0day分析(CVE-2020-1380)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: