1. Vulnerability Description
1.1 The Issue
崩溃发生在CAttrArray::PrivateFindInl函数中。 在函数中rcx(this)指针应该指向一个CAttrArray,但它实际上指向一个CAttribute。
CAttrArray::PrivateFindInl只会执行读取操作,其返回值将被调用函数(CAttrArray::SetParsed)抛弃。
1.2 Affect version
Windows 10 Enterprise 64-bit (OS version 1607, OS build 14393.1198)
Microsoft Edge 38.14393.1066.0, Microsoft EdgeHTML 14.14393.
1.3 Timeline
01/12/2016 Advisory disclosed
01/12/2016 +0 days Countermeasure disclosed
01/12/2016 +0 days SecurityTracker entry created
01/12/2016 +0 days VulnerabilityCenter entry assigned
01/13/2016 +1 days VulnerabilityCenter entry created
01/14/2016 +1 days VulDB entry created
01/17/2016 +3 days VulnerabilityCenter entry updated
01/19/2016 +2 days VulDB last update
2. Technical description and PoC
2.1 Crash
从Google Project Zero的报告中获取的PoC如下
1 | <!-- saved from url=(0014)about:internet --> |
WinDBG attach到Edge上,运行PoC,发现Crash(注:这里用了一款Edge专用的辅助Debug的工具,可以比较方便的在命令行直接attach到进程上。)
1 | edgehtml!CAttrArray::PrivateFindInl+0xd6: |
可以看出,这里是引用了一个无效的指针,此时的调用栈如下
1 | 1:048> k |
寄存器的值如下
1 | 1:048> r |
在ida中查看相关的代码:
1 | int __fastcall CAttrArray::PrivateFindInl(__int64 this, int a2, signed int CAttrValue__AATYPE) |
其中引发问题的指令是
1 | if ( *(_BYTE *)(this_add_8 + 24 * v14 + 3) & 0x80 ) |
其中this_add_8变量对应的是 rcx+8
那么先查看下rcx的值
1 | 1:048> dps rcx |
这里rcx是this指针,在CAttrArray::PrivateFindInl这个类的函数中应该是一个CAttrArray对象的this指针,可是这里rcx存了一个CAttribute的虚表对象,也就是说,在之前有一个错误的调用。
那么根据调用栈继续上溯,我们可以看到CAttrArray::SetParsed函数,调用PrivateFindInl的代码如下
1 | if ( v6 || (v8 = *a1) == 0i64 || (LODWORD(v9) = CAttrArray::PrivateFindInl((__int64)v8, a2, 0), !v9) ) |
也就是说这里如果该函数返回错误的值,那么CAttrArray::Set将不会执行。
继续向上回溯,查看CssParser::RecordProperty函数
1 | void __fastcall CssParser::RecordProperty(CssParser *this, struct CssTokenizer *a2, __int32 a3, char a4, bool a5) |
CAttrArray::SetParsed的调用在下面两句:
1 | CAttrArray::SetParsed(*((struct CAttrArray ***)v8 + 2), v31, &pwzURI, v14); |
1 | CAttrArray::SetParsed(*((struct CAttrArray ***)v8 + 2), v26, v16, v14); |
这里v8是this指针,也就是说在这里发生了一次错误的调用,本来应该传入的是CAttrArray,但是传入了一个CAttribute,造成了Type confusion