Mozilla FireFox <= 2.0.16 UTF8 stack overflow
|
来源:http://0xc3.blogbus.com/ 作者:0xc3 发布时间:2008-09-27
|
|
IBM ISS Xforce的研究员发现的,好像没有什么人关注这个漏洞,这其实是一个非常好利用的漏洞.
该漏洞存在于ConvertUTF8toUTF16:write()函数中:
PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N ) { if ( mErrorEncountered ) return N;
// algorithm assumes utf8 units won't // be spread across fragments const value_type* p = start; const value_type* end = start + N; buffer_type* out = mBuffer; for ( ; p != end /* && *p */; ) { char c = *p++;
if ( UTF8traits::isASCII(c) ) { *out++ = buffer_type(c); continue; }
PRUint32 ucs4; PRUint32 minUcs4; PRInt32 state = 0;
if ( UTF8traits::is2byte(c) ) { ucs4 = (PRUint32(c) << 6) & 0x000007C0L; state = 1; minUcs4 = 0x00000080; } else if ( UTF8traits::is3byte(c) ) { ucs4 = (PRUint32(c) << 12) & 0x0000F000L; state = 2; minUcs4 = 0x00000800; } else if ( UTF8traits::is4byte(c) ) { ucs4 = (PRUint32(c) << 18) & 0x001F0000L; state = 3; minUcs4 = 0x00010000; } else if ( UTF8traits::is5byte(c) ) { ucs4 = (PRUint32(c) << 24) & 0x03000000L; state = 4; minUcs4 = 0x00200000; } else if ( UTF8traits::is6byte(c) ) { ucs4 = (PRUint32(c) << 30) & 0x40000000L; state = 5; minUcs4 = 0x04000000; } else { NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings."); mErrorEncountered = PR_TRUE; mBuffer = out; return N; }
while ( state-- ) { c = *p++;
if ( UTF8traits::isInSeq(c) ) { PRInt32 shift = state * 6; ucs4 |= (PRUint32(c) & 0x3F) << shift; } else { NS_ERROR("not a UTF8 string"); mErrorEncountered = PR_TRUE; mBuffer = out; return N; } }
if ( ucs4 < minUcs4 ) { // Overlong sequence *out++ = UCS2_REPLACEMENT_CHAR; } else if ( ucs4 <= 0xD7FF ) { *out++ = ucs4; } else if ( /* ucs4 >= 0xD800 && */ ucs4 <= 0xDFFF ) { // Surrogates *out++ = UCS2_REPLACEMENT_CHAR; } else if ( ucs4 == 0xFFFE || ucs4 == 0xFFFF ) { // Prohibited characters *out++ = UCS2_REPLACEMENT_CHAR; } else if ( ucs4 >= PLANE1_BASE ) { if ( ucs4 >= 0x00110000 ) *out++ = UCS2_REPLACEMENT_CHAR; else { // surrogate, see unicode specification 3.7 for following math. ucs4 -= PLANE1_BASE; *out++ = (PRUnichar)(ucs4 >> 10) | 0xd800u; *out++ = (PRUnichar)(ucs4 & 0x3ff) | 0xdc00u; } } else { *out++ = ucs4; // 拷贝2字节 } } mBuffer = out; return p - start; }
指针p指向我们传入的参数,for循环依次读取并且转换成unicode,经过转换后存放于out所指向的stack buffer,在这个过程中并没有检测拷贝的长度,导致一个stack buffer overflow。
关于利用的方法,一种是覆盖nsACString_internal::SetLength()的参数可以控制一个vtable指针,并且这个指针会立即执行。
603afc4d 8b01 mov eax,dword ptr [ecx] ds:0023:0012ef34=00410041 603afc4f 3b0538383d60 cmp eax,dword ptr [xpcom_core!nsObsoleteACString::sCanonicalVTable (603d3838)] 603afc55 7505 jne xpcom_core!nsACString_internal::SetLength+0xf (603afc5c) 603afc57 e9791c0000 jmp xpcom_core!nsCSubstring::SetLength (603b18d5) 603afc5c ff6024 jmp dword ptr [eax+24h] // execution
另外一种方法是覆盖SEH handler,但是得要找一个符合编码的跳转地址:
0:000> !exchain 0012fc94: *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Mozilla Firefox\firefox.exe - firefox!NS_RegistryGetFactory+50fd (00410041) Invalid exception stack at 00410041 0:000> g (e1c.da4): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000000 ebx=00000000 ecx=00000004 edx=01109760 esi=00000000 edi=00000000 eip=00410059 esp=0012e9f8 ebp=0012ea18 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246 firefox!NS_RegistryGetFactory+0x5115: 00410059 8b01 mov eax,dword ptr [ecx] ds:0023:00000004=????????
覆盖vtable,得要依赖stack地址,依赖版本,和当时打开htm的方式,比如本地拖拽打开和File -> open打开会导致不同的stack地址,如果结合JS进行Firefox版本判断我想成功率还是比较高的。
覆盖SEH handler没有太大版本依赖性,但是得要寻找一个适当的跳转地址。
|
|
|
[推荐]
[评论(0条)]
[返回顶部] [打印本页]
[关闭窗口] |
|
|
|
|
|
|
推荐广告 |
|
|
|
|