We start off with understanding what is being asked of us:
Level07
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
#!/usr/bin/perl 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"; } print("</pre></body></html>"); } # check if Host set. if not, display normal page, etc ping(param("Host"));
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 level07@nebula:/home/flag07$
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 127.0.0.1:50001 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:10007 0.0.0.0:* LISTEN - tcp 0 0 192.168.56.103:22 192.168.56.1:47544 ESTABLISHED - tcp6 0 0 :::1616 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 :::7007 :::* LISTEN - level07@nebula:/home/flag07$
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.
-geoda