-
-
[原创]Internet Explorer漏洞分析(五)——CVE-2016-0199
-
发表于: 2021-4-21 21:47 784
-
Internet Explorer漏洞分析(五)——CVE-2016-0199
1 2 3 4 5 | 1. 本文一共 1233 个字 26 张图 预计阅读时间 13 分钟 2. 本文作者erfze 属于Gcow安全团队复眼小组 未经过许可禁止转载 3. 本篇文章是CVE - 2016 - 0199 漏洞的分析入手 详细的阐述漏洞的成因 4. 本篇文章十分适合漏洞安全研究人员进行交流学习 5. 若文章中存在说得不清楚或者错误的地方 欢迎师傅到公众号后台留言中指出 感激不尽 |
0x01 漏洞信息
0x01.1 漏洞简述
- 编号:CVE-2016-0199
- 类型:类型混淆(Type Confusion)
- 漏洞影响:远程代码执行(RCE)/拒绝服务攻击 (DoS)
- CVSS 2.0:9.3
mshtml.dll
组件在将CElement
—>CAttributeCollection
—>CAttrArray
—>Attribute.nodeValue
复制到CAttribute
—>Variant
时,并未对其进行校验,以致类型混淆,进而可造成任意代码执行。
0x01.2 漏洞影响
Microsoft Internet Explorer 9 through 11
0x01.3 修复方案
[MS16-063]https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-063
0x02 漏洞分析
0x02.1 分析环境
- OS版本:Windows 7 Service Pack 1 x86
- Internet Explorer版本:9.0.8112.16421
- mshtml.dll版本:9.0.8112.16684
- jscript9.dll版本:9.0.8112.16684
0x02.2 详细分析
分析用POC来自[exploit-db]https://www.exploit-db.com/exploits/39994:
1 2 3 4 5 6 7 8 9 10 11 | <!DOCTYPE html> <meta http - equiv = "X-UA-Compatible" content = "IE=7" > <script> oElement = document.createElement( "IMG" ); var oAttr = document.createAttribute( "loop" ); oAttr.nodeValue = oElement; oElement.loop = 0x41424344 ; / / Set original value data to 44 43 42 41 oElement.setAttributeNode(oAttr); / / Replace oElement with original value data oElement.removeAttributeNode(oAttr); CollectGarbage(); / / Use original value data as address 0x41424344 of a vftable < / script> |
document.createElement("IMG");
语句对应实现为mshtml!CDocument::createElement
,其执行流如下:
首先分配堆块用于存储CImgElement
对象:
之后由CElement::CElement
完成初始化操作:
完成CImgElement
对象创建:
var oAttr = document.createAttribute("loop");
语句对应实现为mshtml!CDocument::createAttribute
,其执行流如下:
分配堆块用于存储CAttribute
对象,之后由CAttribute::CAttribute
完成初始化操作:
CAttribute
对象偏移0x24处存储属性名:
oAttr.nodeValue = oElement;
语句对应实现为mshtml!CAttribute::put_nodeValue
,其调用CAttribute::PutNodeValueVariantHelper
完成功能。首先是复制VARIANT类型对象(存储nodeValue
值)至偏移0x28处:
之后判断该CAttribute
对象是否为Tracked Object,如果不是则将其设为Root Object,并加入CRootTracker中(感兴趣的读者可自行分析CTrackerHelper::SetAsRoot
及CRootTracker::AddRoot
函数,此部分与GC机制有关,不在此展开):
CAttribute
对象偏移0x5C处用于判断其是否为Root Object:
oElement.loop = 0x41424344;
语句设定CElement
对象属性,其属性使用数组存储,对应实现为CAttrArray::Set
。该函数首先判断CElement
对象偏移0x10处是否置值,若无则分配内存并将返回值写入该处:
于CImplAry::InsertIndirect
函数中对CAttributeCollection
(CElement
offset 0x10)偏移0x04处值与0x00处值进行比较以检查是否需要调整Attribute Array
存储空间:
由于是首次设定CElement
对象属性,并未开辟Attribute Array
空间,故调用HeapAlloc
进行分配,具体可分析CImplAry::EnsureSizeWorker
函数,完成后内存如下:
共4个元素(0x10>>2),每个元素占用内存空间为0x10。完成属性赋值,并将Attribute Array
当前元素数量加1:
CElement对象部分结构含义如下:
1 2 3 4 5 6 | + 0x10 CAttributeCollection + 0x00 The total size of the Attribute Array<< 2 + 0x04 Number of Attributes + 0x08 CAttrArray + 0x0c + 0x14 CTreeNode |
oElement.setAttributeNode(oAttr);
语句对应实现为mshtml!CElement::setAttributeNode
,其调用CElement::VersionedSetAttributeNode
完成功能。首先是执行MSHTML!CAttribute::PrivateQueryInterface+0x920
函数,该函数会对esp+30h+var_14
处内存置值,此值会决定后续执行CAttrArray::Set
函数orCAttrArray::SetAt
函数:
之后执行CAttribute::SetElement
函数,对CAttribute
对象偏移0x3c处及偏移0x08处进行置值,具体流程可自行跟进分析:
CAttrArray::Set
函数执行完成:
CAttribute对象部分结构含义如下:
1 2 3 4 | + 0x24 Attribute Name(Pointer to BSTR)、 + 0x28 Variant(Save the nodeValue) + 0x3c CElement + 0x5C IsRootObject |
oElement.removeAttributeNode(oAttr);
语句对应实现为mshtml!CElement::VersionedRemoveAttributeNode
。漏洞发生在将CElement
—>CAttributeCollection
—>CAttrArray
—>Attribute.nodeValue
复制到CAttribute
—>Variant
(0x28)时,并未对其进行校验,以致类型混淆。正常情形下:
1 2 3 4 5 6 7 8 9 10 | <!DOCTYPE html> <meta http - equiv = "X-UA-Compatible" content = "IE=7" > <script> oElement1 = document.createElement( "IMG" ); var oAttr1 = document.createAttribute( "loop1" ); oAttr1.nodeValue = 0x41424344 ; oElement1.setAttributeNode(oAttr1); oElement1.removeAttributeNode(oAttr1); CollectGarbage(); < / script> |
其执行流如下:
而在POC情形下,其执行流:
如此一来,CAttribute::EnumerateTrackedObjects
传递参数给jscript9!ScriptEngine::EnumerateTrackingClient
,其在mov ecx, [eax]
时便会发生访问错误:
0x03 参阅链接
- [对CVE-2016-0199的简单分析]https://bbs.pediy.com/thread-212058.htm
- [CVE-2016-0199 漏洞分析]https://www.jianshu.com/p/38001618bc2d