Nebula - level07

This is my eighth post on the Nebula series hosted by Exploit Exercises

We start off with understanding what is being asked of us:

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.
To do this level, log in as the level07 account with the password level07. Files for this level can be found in /home/flag07.

Source code


use CGI qw{param};

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

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

  print("<html><head><title>Ping results</title></head><body><pre>");

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


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


I first SSH into the box, navigate to the /home/flag07 folder:

level07@nebula:~$ cd /home/flag07/
level07@nebula:/home/flag07$ ls
index.cgi  thttpd.conf
level07@nebula:/home/flag07$ ls -lah
total 9.5K
drwxr-x--- 2 flag07 level07  102 2011-11-20 20:39 .
drwxr-xr-x 1 root   root      60 2012-08-27 07:18 ..
-rw-r--r-- 1 flag07 flag07   220 2011-05-18 02:54 .bash_logout
-rw-r--r-- 1 flag07 flag07  3.3K 2011-05-18 02:54 .bashrc
-rwxr-xr-x 1 root   root     368 2011-11-20 21:22 index.cgi
-rw-r--r-- 1 flag07 flag07   675 2011-05-18 02:54 .profile
-rw-r--r-- 1 root   root    3.7K 2011-11-20 21:22 thttpd.conf

Looks like we have 2 files owned by root, index.cgi and thttpd.conf. Per the source code, the user created their first perl program that is reachable from the webserver.

To find out where this is running, I first run netstat:

</pre></body></html>level07@nebula:/home/flag07$ netstat -antp
(No info could be read for "-p": geteuid()=1008 but you should be root.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0*               LISTEN      -               
tcp        0      0    *               LISTEN      -               
tcp        0      0 *               LISTEN      -               
tcp        0      0      ESTABLISHED -               
tcp6       0      0 :::1616                 :::*                    LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -               
tcp6       0      0 :::7007                 :::*                    LISTEN      -               

After different tests, I see that port 7007 is running our program. Per the /home/flag07 directory, we look for index.cgi and find it:

Great. We found the program. Now, looking at the code it, it will ping the parameter "Host". I test again:

Excellent. Now that we know the program works. Let's see how we can exploit this.

We see in the code that it does not validate user input. We can actually run a semicolon ";" at the end and run whatever code we want as the owner of the program.

To test, we run "whoami". Additionally, we have to URL encode our ";"

As you can see at the bottom, we have "flag07" running. Now, all we have to do is run "getflag" and complete the objective:

Excellent! This shows how user input validation is critical to development and should prevent user's from running arbitrary commands.

Thanks for reading.