漏洞成因
CVE-2013-3893发生原因是浏览器中函数SetMouseCapture()在事件响应中处理了一个已经被释放的引用而导致了Use-After-Free型漏洞的发生。该漏洞对IE6-11版本全覆盖。本次利用是windows xp sp3环境下的IE8版本中进行。下面结合POC详细分析漏洞调试复现。
详情描述
首先创建两个元素。
利用document.body.appendChild将两个元素加入到DOM节点树中。
内存中可以看到指针指向关系。
申明father节点是child节点的父节点。
内存中可以看到指针指向关系。
为father节点添加鼠标焦点丢失触发函数。
father[‘outerText’]=“”将元素本身复制为空对象,执行了这条语句,所有跟father有关的操作对象(DOM树中所有father节点的子孙)都会被析构。
father节点捕获到鼠标焦点。
child节点捕获到鼠标焦点,同时导致father丢失鼠标焦点。
father节点丢失鼠标焦点,从而触发onlosecapture函数。
程序执行该条语句后,页面清空,Dom树重置。但由于执行返回正常程序后,程序中还存在一个指向CBody_ctreenode的指针,并且该指针会在后续getinterface()或doc()中被引用,从而导致UAF漏洞的发生。
利用过程
利用主要有两个问题需要解决。
第一是目标地址的堆喷射,由Heapspray()实现;
第二是EIP的劫持,由Hijack()实现。
这里主要涉及两个问题,第一是unescape后执行length函数返回的是实际内存大小的一半;第二是了解BSTR类对象的结构。
截图可见,内存0x12121212处已被slide代码覆盖。
截图为执行Hijack前Cbody指针的对象的内存情况。
截图为执行Hijack后Cbody指针的对象的内存情况。已经成功占位目标。
接着正常流程往下go。
到达Pumpmessage函数中的NodeAddRef调用位置。
到达NodeAddRef函数中的GetLookasidePtr调用位置。
到达GetLookasidePtr函数中的doc调用位置。
进入doc函数内,程序call了已经被占位的0x12121212地址。
最终程序跳转到了目标地址0x12121212,执行一连串的slide代码,最终执行shellcode。
利用总结
本次我对该漏洞的利用过程中,有几点感受:
1、对于IE浏览器的调试中非常重要的一点是断点的设置。正确的断点能够很快的帮助你定位程序的关键位置。由于IE浏览器的JS脚本执行经过了中间层翻译执行,因此利用特殊函数结合IDA分析进行断点设置能够事半功倍;
2、关注关键函数。对于栈溢、堆溢或者UAF等漏洞,在前期漏洞分析和后期漏洞利用方面都需要对关键内存大小分配掌握清楚,因此需要关注内存分配的相关函数;
3、在分析过程中,发现metesploit中集成了shellcode生成和许多现成的漏洞利用脚本。后面可能有必要在这方面进行一定的深入。