ChinaExcel Chart图表控件是由杭州通用软件有限公司自主开发的一款的类 Excel图表控件产品,可以在 C/S和 WEB等各种环境下面应用。简单地讲,利用这个控件,我们可以实现类似微软 Excel的功能,将数据用表格的形式或者图形的形式来展现。我们知道,控件的好处在于可以作为一个单独的程序使用在不同的环境当中,尤其是网页当中。关于这方面的内容,我们不在这里讨论,我们需要关注的是这些能够使用在网页当中的控件,在安全方面往往会出现严重的问题。这里,我们就针对 ChinaExcel Chart图表控件做一个安全测试。
我们本次的测试环境为 Windows XP SP3系统,使用的浏览器为IE6。当我们在系统中安装了 ChinaExcel Chart图表控件后,它会向当前系统中注册一个 ActiveX控件,如图 1所示。
图1这张图是我们利用ComRaider程序查看当前系统中所有注册的 ActiveX控件时,找到了 ChinaExcel Chart图表控件注册的 ActiveX控件信息。从图 1中我们看出,ChinaExcel Chart图表控件注册的 ActiveX控件文件名为“CHINAE~1.OCX”,它是一个可以被浏览器自动加载的 ActiveX控件,因为图 1中显示该控件的“RegKey Safe for Script:True RegKey Safe for Init: True”即注册表中负责控件安全标识的键值都为真。 现在,我们需要查看一下 ChinaExcel Chart图表控件提供了哪些可以被我们调用的外部接口,如图 2所示。
图 2中我们看到,ChinaExcel Chart图表控件提供了丰富的外部接口,这些接口都是用来生成类似微软 Excel图表数据用的。其中,我们比较关注一个名为“ReadDataFile”的外部接口,其函数原型为:
大家一定比较疑惑,为什么我们恰恰对这个外部接口感兴趣。
“ReadDataFile”这个外部接口从名字上来看,是一个用来读取数据文件的。按照ChinaExcel Chart图表控件的帮助文档解释“ReadDataFile”读取的数据文件有着特殊的格式要求,必须将数据按照一行一个数据的方式来书写,因为这样才能使得ChinaExcelChart图表控件明确自己最后要生成的图表是什么样式。既然“ReadDataFile”是要读取数据文件的,数据文件的完整路径名称就是一个非常关键的地方,众所周知,Windows系统下的文件完整路径名长度不超过 260个字节,很多编程人员在这个细节上往往没有考虑详尽,最终将会造成严重的安全隐患。为此,我们抱着试一试的态度,准备对 ChinaExcel Chart图表控件的“ReadDataFile”外部接口做一个安全测试。
首先,我们需要写一段用来测试的网页代码,其内容如下:
代码很简单,主要就是利用 语言调用了ChinaExcelChart图表控件的“ReadDataFile”外部接口,并且制造了一个长度为1000个字节的变量 a,将其作为测试变量传递给“ReadDataFile”外部接口,目的就是看一看“ReadDataFile”外部接口在处理如此过长的文件路径名时会不会发生意想不到的错误。
保存上述网页代码为 test.htm文件,将其上传到 Web服务目录下,然后,打开浏览器,这里是 IE6,并且启动 OllyDbg程序附加到 IE的进程上,此刻,在 IE浏览器中输入 test.htm文件所在的网址,回车访问后,我们发现 OllyDbg程序监视到了一个严重的程序错误,如图3所示。
图 3中那个“2C2C2C2C不可读”的错误,我相信所有的读者都能明白是什么意思,毫无疑问,此刻“ReadDataFile”外部接口发生了严重的溢出漏洞,一个 0day被我们发现了!漏洞是发现了,但是我们更需要知道漏洞发生的原因。重新启动OllyDbg程序,运行 IE浏览器,当我们在浏览器中第一次打开 test.htm时,浏览器会弹出一个对话框,显示“打开数据文件出错”,这个时候,我们可以利用对该对话框的监视来找到“ReadDataFile”外部接口发生错误的函数,这个操作步骤很简单。首先,在 OllyDbg程序中压下 Ctrl+G组合键,输入我们要监视的函数“MessageBoxA”,该函数负责弹出对话框,点击“确定”以后, OllyDbg程序将会跳转到“MessageBoxA”函数所在的位置,在该处压 F2键下一个断点。接着,在浏览器中再次访问 test.htm文件所在网址,此刻,OllyDbg程序将会立即停止在“MessageBoxA”函数所在的位置,如图 4所示。
此刻,我们注意到图4右下侧的堆栈区域显示“返回到CHINAE~1.030D1AEC来自 CHINAE~1.030EC120”,这意味着CHINAE~1.030D1AEC这个地方是调用MessageBoxA函数的关键地区,我们在OllyDbg程序中跳转到该地址。虽然,CHINAE~1.030D1AEC这个地方调用了对话框函数,但是,这里已经发生了溢出,因为图 4的堆栈区下方已经被大量的“2C”所填充,如图 5所示。
为此,我们还需要回溯找到那个关键的函数。现在,在 OllyDbg中单步执行,直到我们来到了 030D58B7这个内存地址,如图 6所示。
这个函数才是最核心的函数,为什么这样讲,如果此刻我们从图6这个地址向上滚动 OllyDbg的显示条,我们将会看到本次漏洞发生的真正原因,如图 7所示。
上面这段代码中我们首先看到,函数利用指令“sub esp,10C”开辟了一段栈空间,这个空间的大小只有 268个字节,可是在随后的代码中,我们没有看到任何长度判断限制指令,而是看到了类似“repmovs dword ptr es:[edi], dword ptr [esi]”这样的内存拷贝指令,于是,栈空间中保存的函数返回地址被过长的数据覆盖了,漏洞由此发生了。
至此,漏洞发生的原因我们明白了,剩下的就是漏洞的利用了,这个漏洞的利用方法完全可以借助 heapspray技术来实现,代码的基本结构如下。
本文为网络安全技术研究记录,文中技术研究环境为本地搭建或经过目标主体授权测试研究,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,在挖掘、提交相关漏洞的过程中,应严格遵守相关法律法规。