\x01 前言

  • CVE-2017-11826 据说是 360 在 2017 年 9 月底发现的一个关于 XML 格式解析的一个漏洞,之后微软在 10 月份发布了关于 CVE-2017-11826 的补丁,补丁地址:https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-11826

  • 该漏洞的成因是由于在解析闭合元素时,没有对元素的完整性做出判断,导致将当前元素的嵌套关系加上 1。这样的话 wwlib 模块在处理闭合标签时,会错误的使用父级元素 w:name 属性 +44 的地址进行虚函数调用,攻击者通过修改 w:name 属性,就可以进行任意地址调用。
  • 受影响的 Office 版本。

\x02 调试环境

  • 操作系统:Windows 7 + VMware
  • 调试工具:x64dbg
  • 漏洞样本:POC(提取码:lxx6)

\x03 调试分析

  • GitHub 上下载关于 CVE-2017-11826 漏洞的文件夹,解压后发现包括解压过的 docx 文件、README 文件、俄文文档,俄文文档没有仔细看,好像是关于漏洞利用的。

  • 包含漏洞的 XML 文件为 document.xml,文件在 word 路径下。打开 document.xml 文件,分析后发现 <w:font> 标签使用了 </o:idmap> 标签进行闭合,而 <w:font> 标签的 w:name 属性有点奇怪,可能是用于控制某一个地址的值。

  • 将解压过的 docx 文档重新压缩,之后使用注册表附加调试器准备调试。

  • 附加完成之后打开含有漏洞的文档,运行后触发异常,其中 call [ecx+4] 指令是利用虚函数表调用虚函数,而 ecx 为虚函数表指针,通过 wwlib.41249DA0 函数返回。

  • 查看堆栈调用,发现用于处理 XML 格式的 msxml 模块,msxml 模块通过间接调用 wwlib 模块去协助解析 XML 格式。暂且将 wwlib.3161309E 函数定为漏洞函数。

  • 对漏洞函数下记录断点后查看日志内容,发现漏洞函数被调用了 6 次,结合 document.xml 文件中的标签元素分析漏洞函数很有可能是用于解析元素标签的,至于解析的是什么,目前还不清楚。



  • 选取最后一次调用漏洞函数的 esp 下条件断点,分析漏洞函数处理流程。

  • 函数断下后从传入的参数可以发现,esi 可能是储存标签信息的数据结构。

  • 单步进入该函数,在如图所示的位置会取出元素的嵌套关系,此时 <o:idmap> 标签已经插到了 w:font 标签的后面(以 ":" 符号为分隔符)。而 <w:font> 标签在未闭合的情况插入了 <o:idmap> 标签,说明嵌套关系已经被错误的解析。

  • 调试到 0x31613084 地址时发现会调用 wwlib.31249DA0 函数,经过分析后发现该函数的返回值和异常处的虚函数表调用有关,所以进入这个函数看看。

  • 通过分析发现该函数对 ecxedx 做了一些简单的计算,算法为 [[ecx]+8]*edx + [[ecx]+C] + [ecx],计算结果为 0x0751D140;而 ecx 是由 esi 传入,edx 又等于 [[esi]],所以算法变为 [[esi]+8]*([[esi]]-2) + [[esi]+C] + [esi],由传入的 esi 控制,经过后面的分析可以得出 [[esi]] 其实就是当前元素的嵌套等级。

  • 调用完 wwlib.31249DA0 后会将 [[0x0751D140+44]+44] 地址的值作为虚函数表指针进行虚函数调用,进而触发异常。如图所示可以看出 [0x0751D140+44] 地址被覆盖成了 <w:font> 元素的 w:name 属性,所以攻击者通过修改 <w:font> 标签的 w:name 属性就可以做到调用任意地址。



  • 接下来更改样本中的 document.xml 文件,手动添加 </w:font> 闭合标签,看看是否会触发异常。

  • 在漏洞函数处断下,这时的嵌套等级为 5。

  • 之后通过 wwlib.31249DA0 计算虚函数调用地址为 0x075098F4。由于嵌套等级为 5,所以计算出的结果为 F44C*(5 - 2) + 10),之前的为 1404C*(6 - 2) + 10)。

  • 虚函数调用后程序并没有触发异常。

\x04 分析 msxml 模块处理步骤

  • 为了快速了解 msxml 模块的处理流程,对调用堆栈中的所有 msxml 模块函数下记录断点,查看日志。

  • 从日志中可以发现漏洞函数的调用都是通过 sub_78887830 函数中的 call [ebx+200] 的指令实现的,但是倒数第二个漏洞函数的调用却没有经过 call [ebx+200] 而是直接跳到了 MSO 模块。

  • 对倒数第二个漏洞函数下断点。断下后分析堆栈调用,发现 msxml.78887830 函数中的 call [ecx+20] 的指令也会调用漏洞函数。



  • 这样的话函数调用流程图就能分析出来了,函数调用流程如下图所示:

  • 下面根据 msxml.78887830 函数的最后一次调用,简单分析 call [ebx+200] 下的函数链调用。



  • msxml.78887830 函数开头会将元素标签对象储存在 ebx 中,元素标签对象储存当前解析元素的信息,主要是元素的嵌套关系,嵌套等级等。

  • 向下调试后发现 msxml.788872F7 函数会获取 <w:font> 元素的 w:name 属性字符的指针。

  • 而下面的 msxml.78887335 函数会获取 o:idmap 元素字符的指针

  • 获取完 o:idmap 元素字符的指针后,调用 msxml.788872F7 函数解析 o:idmap 元素,在内存窗口可以看出字符指针已经指向了 incer 的位置,说明已经把 idmap 标签解析出来了。

  • 之后调用 msxml.788873F0 计算元素的嵌套等级,可以看出元素的嵌套等级计算出为 6,但此时元素的嵌套等级依旧是 5,还没有更新为 6

  • 在将 [ebx+1e8] 赋值给 eax 之后,发生了跳转,从而跳过了 call [ecx+20] 的调用转而进行 call [ebx+200] 的调用。





  • 调用的函数为 mso.32751CAA,其实 MSO 模块的函数调用没有太大的作用,只是给后面 wwlib 模块的做间接处理。

  • 到达 0x32751D5C 的位置后执行 call [ecx+20] 指令调用 sub_3277FAC0 函数,此时 esi = [esi+60]

  • 接着 sub_3277FAC0 函数中会执行 call [eax+10] 指令调用 wwlib.3127D3FB

  • 进入 wwlib.3127D3FB 函数之后继续向下调试,此时 [[esi+b14]] 的地址中储存着元素的嵌套关系。



  • 之后调用完 wwlib.3127E6B3 函数后会进行一个判断,如果 ebx 等于 0x80004001 就跳转。

  • 跳转完成之后调用漏洞函数,下面的流程刚刚已经分析过了。

  • 根据上面调试分析的结果对其中几个位置下记录断点。查看日志可以发现 msxml.78887830 函数会逐一对元素进行解析,当解析到 <idmap> 标签时嵌套关系为 5



  • 但是在异常处嵌套关系为 6,对最后一次调用 msxml.78887830 函数下断点,查看嵌套关系是何时变为 6 的。

  • 重新运行后断下,此时嵌套关系为 5

  • 当调试到 wwlib.3127D3FB 函数中的 0x3128E3AD 位置时,嵌套关系变为了 6,说明 wwlib.312C6142 函数更新了嵌套关系。

  • 接着分析一下 w:name 属性是何时被复制的。通过对漏洞异常处的分析发现 w:name 属性储存在元素对象中,通过对元素对象储存 w:name 位置下写入断点发现在 WWLIB.sub_3127D3FB 函数中会调用 wwlib.3127E773 函数复制 w:name 到元素对象当中,之后漏洞函数中会把 w:name 属性取出来进行虚函数表调用。





  • 需要注意的是再上面的分析中该跳转并没有实现,也就是说这里在复制完 w:name 属性之后直接返回了。而判断跳转的值是由 wwlib.3127E6B3 返回的,进入该函数,分析后发现在函数末尾处会将 0x80004001 赋值给 eax,在这之前会以 0x3149BFA3 作为基址,以 eax * 4 做为偏移地址进行调用,而 eax 是通过 [ebp-1c] 传进来的,对该位置下记录断点后查看日志。

  • 根据日志可以发现当 [ebp+1c] 的值为 0xFFFF 时才会调用漏洞函数。而且解析 <w:font> 标签前调用一次,解析 <o:idmap> 标签后调用一次。

  • 之后把 <o:idmap> 标签删除,再对比日志信息。

  • 可以发现只有在 <w:font> 标签解析前才会将此值设置为 0xFFFF,所以这一个值可能是用于判断元素是否闭合。

\x05 总结

  • msxml.78887830 函数解析到 <w:font> 标签时,会误以为标签已经闭合,从而将 <w:font> 标签的 w:name 属性(假如有的话)添加到对象之中,同时更新元素的嵌套关系(嵌套关系变为 6),导致最后使用 call [ecx+4] 进行虚函数表调用时虚表指针被错误的覆盖成了 w:name 属性中的数据触发了异常。



关于 CVE-2017-11826 的漏洞分析到此结束,如有错误,欢迎指正

CVE-2017-11826:Office Open XML 标签嵌套解析混淆漏洞的更多相关文章

  1. [Java] 解决spring的xml标签内不能自由增加说明的难题,方便调试、部署时进行批量屏蔽

    作者:zyl910 以往我们想在spring的xml配置文件中增加说明文本时,只能使用xml注释(<!-- 注释 -->).这对于"调试.部署时想批量屏蔽部分bean" ...

  2. Freemarker的初次使用之FTL标签嵌套与map的使用

    入职第二周了,在熟悉了公司自动化测试脚本的编写(使用什么数据库,使用哪种语言,框架带了哪些方法)后,现在开始熟悉模拟器,我们把请求发到服务器1,服务器1根据请求参数处理后将结果发给模拟器,模拟器根据服 ...

  3. .NET使用Office Open XML导出超大数量数据到 Excel

    我相信很多人在做项目的都碰到过Excel数据导出的需求,我从最开始使用最原始的HTML拼接(将需要导出的数据拼接成TABLE标签)到后来happy的使用开源的NPOI, EPPlus等开源组件导出EX ...

  4. [转] Spring4.3.x 浅析xml配置的解析过程(6)——解析context命名空间之property-placeholder和property-override标签

    在上一篇解析自定义命名空间的标签中,我们已经知道解析自定义命名空间的标签需要用到NamespaceHandler接口的实现类,并且知道spring是如何获取命名空间对应的命名空间处理器对象的.因此我们 ...

  5. .NET使用Office Open XML导出大量数据到 Excel

    我相信很多人在做项目的都碰到过Excel数据导出的需求,我从最开始使用最原始的HTML拼接(将需要导出的数据拼接成TABLE标签)到后来happy的使用开源的NPOI, EPPlus等开源组件导出EX ...

  6. Office Open XML导出大数据

    Office Open XML导出大量数据到 Excel .NET使用Office Open XML导出大量数据到 Excel我相信很多人在做项目的都碰到过Excel数据导出的需求,我从最开始使用最原 ...

  7. div标签嵌套原则详解(转载)

    这个也许平时人们不注意,但是非常有用,尤其是当你实在找不到原因为什么网页显示错误的时候. XHTML 的标签有许多:div.ul.li.dl.dt.dd.h1~h6.p.a.addressa.span ...

  8. HTML5标签嵌套规则

    × 目录 [1]分类 [2]子元素 [3]总结 前面的话 在html5中,<a>元素的子元素可以是块级元素,这在以前是被认为不符合规则的.本文将详细介绍html5的标签嵌套规则 分类 ht ...

  9. XML标签

    SQL标签库提供了创建和操作XML文档的标签. 引入语法:<%@ taglib prefix="x" uri="http://java.sun.com/jsp/js ...

随机推荐

  1. Java基础 随笔整理

    Java基础随笔整理 为了方便阅读,特整理了相关的学习笔记 Java感想 操千曲而后晓声 Java入门 Java其他 Java虚拟机详解 语言入门百题 Java开发工具 · Eclipse Java语 ...

  2. git clone 提速

    将类似于 git clone https://github.com/graykode/nlp-tutorial 的命令改成 https://github.com.cnpmjs.org/graykode ...

  3. 痞子衡嵌入式:盘点国内Cortex-M内核MCU厂商高性能产品

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内Cortex-M内核MCU厂商高性能产品. 在8/16位中低端MCU领域,国内厂商的本土化产品设计以及超低价特点,使得其与国外大厂竞 ...

  4. Python中的描述器

    21.描述器:Descriptors 1)描述器的表现 用到三个魔术方法.__get__()   __set__()  __delete__() 方法签名如下: object.__get__(self ...

  5. Quartz基础使用

    Quartz基本组成部分: 调度器:Scheduler 任务:JobDetail 触发器:Trigger,包括SimpleTrigger和CronTrigger . using Quartz; usi ...

  6. Azure Front Door(三)启用 Web Application Firewall (WAF) 保护Web 应用程序,拒绝恶意攻击

    一,引言 上一篇我们利用 Azure Front Door 为后端 VM 部署提供流量的负载均衡.因为是演示实例,也没有实际的后端实例代码,只有一个 "Index.html" 的静 ...

  7. Centos7安装nexus(maven私服)以及maven的相关配置

    一.nexus安装: 1.获取nexus下载地址: 查询nexus最新版本地址:https://help.sonatype.com/repomanager3/download 当前最新版本为nexus ...

  8. Android学习之CoordinatorLayout+FloatingActionButton+Snackbar

    CoordinatorLayout •简介 CoordinatorLayout 协调布局,可以理解为功能更强大的 FrameLayout 布局: 它在普通情况下作用和 FrameLayout 基本一致 ...

  9. Java学习之数组的简单用法

    •概念 其实所谓的数组指的就是一组相关类型的变量集合,并且这些变量可以按照统一的方式进行操作. 数组本身属于引用数据类型,那么既然是引用数据类型,这里面实际又会牵扯到内存分配: 而数组的定义语法有两种 ...

  10. Java中的集合Set - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合Set - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,映射Map,最后再简单介绍下集合Set,相关类如下 ...