Internet Explorer漏洞分析(四)——CVE-2016-0199
字数 2656 2025-08-05 13:25:32
CVE-2016-0199 Internet Explorer类型混淆漏洞深入分析
漏洞概述
漏洞编号: CVE-2016-0199
漏洞类型: 类型混淆(Type Confusion)
影响范围: Microsoft Internet Explorer 9至11版本
危害等级: CVSS 2.0评分9.3,可导致远程代码执行(RCE)或拒绝服务攻击(DoS)
受影响组件: mshtml.dll
修复方案: 微软安全更新MS16-063
漏洞原理
该漏洞存在于mshtml.dll组件中,当处理CElement→CAttributeCollection→CAttrArray→Attribute.nodeValue到CAttribute→Variant的复制过程时,缺乏必要的类型校验机制,导致类型混淆(Type Confusion)漏洞。
环境准备
分析环境配置:
- 操作系统: Windows 7 Service Pack 1 x86
- Internet Explorer版本: 9.0.8112.16421
- 关键DLL版本:
- mshtml.dll: 9.0.8112.16684
- jscript9.dll: 9.0.8112.16684
漏洞详细分析
POC代码分析
<!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; // 设置原始值数据为44 43 42 41
oElement.setAttributeNode(oAttr); // 用原始值数据替换oElement
oElement.removeAttributeNode(oAttr);
CollectGarbage(); // 使用原始值数据作为vftable的地址0x41424344
</script>
关键函数调用链
-
document.createElement("IMG")
- 对应实现:
mshtml!CDocument::createElement - 执行流程:
- 分配堆块存储
CImgElement对象 - 通过
CElement::CElement完成初始化
- 分配堆块存储
- 对应实现:
-
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中
- 对应实现:
-
oElement.loop = 0x41424344
- 对应实现:
CAttrArray::Set - 执行流程:
- 检查
CElement对象偏移0x10处是否置值 - 若无则分配内存并将返回值写入该处
- 通过
CImplAry::InsertIndirect检查是否需要调整Attribute Array存储空间 - 首次设定属性时调用
HeapAlloc分配空间(4个元素,每个0x10字节) - 完成属性赋值并将Attribute Array当前元素数量加1
- 检查
- 对应实现:
-
oElement.setAttributeNode(oAttr)
- 对应实现:
mshtml!CElement::setAttributeNode - 调用
CElement::VersionedSetAttributeNode完成功能:- 执行
MSHTML!CAttribute::PrivateQueryInterface+0x920函数 - 执行
CAttribute::SetElement函数,对CAttribute对象偏移0x3c及0x08处置值
- 执行
- 对应实现:
-
oElement.removeAttributeNode(oAttr)
- 对应实现:
mshtml!CElement::VersionedRemoveAttributeNode - 漏洞触发点: 将
CElement→CAttributeCollection→CAttrArray→Attribute.nodeValue复制到CAttribute→Variant(0x28)时未进行类型校验
- 对应实现:
关键数据结构
CElement对象结构:
- +0x10:
CAttributeCollection- +0x00: Attribute Array总大小<<2
- +0x04: 属性数量
- +0x08:
CAttrArray - +0x0c+0x14:
CTreeNode
CAttribute对象结构:
- +0x24: 属性名(指向BSTR的指针)
- +0x28: Variant(保存nodeValue)
- +0x3c:
CElement - +0x5C: IsRootObject标志
漏洞触发流程
-
正常流程:
- 创建元素和属性
- 设置属性值为合法值(如0x41424344)
- 添加和移除属性节点
- 垃圾回收
-
漏洞利用流程(POC):
- 创建
IMG元素和loop属性 - 将属性值设置为元素对象本身(
oAttr.nodeValue = oElement) - 设置元素的
loop属性值为0x41424344 - 添加属性节点到元素
- 移除属性节点
- 触发垃圾回收
- 创建
关键差异在于类型混淆后,CAttribute::EnumerateTrackedObjects传递参数给jscript9!ScriptEngine::EnumerateTrackingClient时,mov ecx, [eax]指令会尝试访问错误的内存地址(0x41424344),导致访问违例。
漏洞利用思路
通过精心构造的JavaScript代码,攻击者可以:
- 利用类型混淆漏洞控制内存中的对象布局
- 通过垃圾回收机制重用已释放的内存
- 最终实现任意代码执行
防护措施
- 及时安装微软安全更新MS16-063
- 升级到更高版本的Internet Explorer
- 考虑使用更现代的浏览器替代IE
- 在企业环境中可通过组策略限制ActiveX控件和脚本执行
参考链接
- 微软安全公告: https://docs.microsoft.com/en-us/security-updates/
- Exploit-DB上的POC: https://www.exploit-db.com/
- 类型混淆漏洞原理: https://cwe.mitre.org/data/definitions/843.html