Description
This is a hard machine from HackTheBox with the total score of 60 points. This is also my first hard machine, so expect some mistakes, and I will try to explain everything in detail.
Enumeration
From the nmap
scan, we see that the machine has 2 open ports: 22
for SSH and 80
for HTTP. Let’s add the domain to the /etc/hosts
file and visit the web server.
The website itself does not contain valuable information. Let’s run gobuster
to find hidden routes on the web server.
Web Enumeration
There are 3 subdomains: auth
, dashboard
, and report
. Let’s visit the auth
subdomain.
The login page requires username and password. I registered one and explore around, I can see that the user can report bug through a form. And the form is vulnerable to XSS.
I tried the following payload with python listener and got the cookie value of web_dev
role.
Now I can change the cookie value to web_dev
and visit the dashboard
subdomain again.
This time I can make some changes to the feedbacks from users.
If a bug requires further attention, it will be escalated to our administrators for resolution.
This is from the report notifications. Which means I can escalate my role to admin
by repeating the same process.
Note: Keep the netcat listener running, this part is quite buggy and you might need to repeat the process a few times.
Now with the admin
role, I can visited the dashboard
subdomain again and see the following page.
There are 3 options: Full report list
, Create a backup
and Create PDF report
. I tested the first 2 options but could not find any vulnerabilities. So I tried the Create PDF report
option.
I did some enumeration and found that the wkhtmltopdf
is installed on the machine. I tried to create a PDF report with the following payload. However, seems like we cannot proceed further with this method.
So I tried to enumerate the request and found that it is using Python 3.11
after some research I found this vulnerability: CVE-2023-24329. The principle is: when the entire URL starts with a blank character (or white space), urllib.parse will have parsing problems (affecting the host) Analysis of names and schemes. Any domain or protocol filtering method implemented using a block list can be bypassed by providing a URL that begins with whitespace characters. Successful exploitation of this vulnerability may lead to arbitrary file reading, command execution, or SSRF.
As showed in the image above, I can read the /etc/passwd
file. I wonder what process it is running, so I tried to read the /proc/self/cmdline
file.
With the running python3/app/code/app.py
process, I know what to do next. To exploit this running process, I need to specify the path to each file.
From the import list, I can see that there are 4 files that I can read.
From the auth.py
file, I can find the ftp credentials. with that being said, we can ftp access to the machine through the create report function.
It is showing the following files: private-8297.key
and welcome-note.txt
. I downloaded both files, I copied the private key to id_rsa
file.
Before I could ssh into the machine, I need to decrypt ssh reset phrase using ssh-keygen
.
Now it is possible to ssh into the machine using private key.
Privilege Escalation
Next step is to escalate the privilege to root, first enumerate the machine by checking for ports with netstat
.
There is a port 4444
running, let’s forward the port to our machine and check the content.
Now we can access the port 4444
on our machine to check the content.
I have check around but could not find anything that is useful. Back to the account, the current account name is dev_acc, which is a network root account, so go to the /var
directory to find information.
Seems like I am lucky this time, there are sql files and db files, for the db files, I can use sqlite3
to check the content.
From the users
table, I can see that there are 2 users: root
and adam
, with the hashed password. I tried to crack the password of root
using hashcat
but could not find the password. So I tried to crack the password of adam
and successfully found the password.
The password hash is sha256$Z7bcBO9P43gvdQWp$a67ea5f8722e69ee99258f208dc56a1d5d631f287106003595087cf42189fc43
, which format similar to Python Werkzeug SHA256 (HMAC-SHA256 (key = $salt)) *
you can find the hashcat mode here.
With the cracked password, I can now ftp
into the machine using the adam
account.
There is a directory backup
with another directory runner1
which contains following files: run-tests.sh
, runner1
, and runner1.c
. I use the get
command to download them all.
From the file run-tests.sh
, I can see that there is a authentication code, but missing the last 4 characters: UHI75GHI****
. And in the runner1.c
file, it has the authentication key hash, let’s create a Python
program to brute force the last 4 characters.
The authentication code is UHI75GHINKOP
.
From the last file runner1
I found that the file mainly executes the ansible-playbook command. This involves another component Ansible , which is an open source automation engine that can automatically execute configuration, configuration management, application deployment and other processes. It includes the following functions :Global Definitions, Authentication, Listing Playbooks, Running a Playbook, Installing a Role and Main Program Logic
The Listing Playbooks function will scan the PLAYBOOK_LOCATION directory for files ending with .yml and list them.
Running a Playbook gets the name of the playbook file, constructs a command line to use ansible-playbook, and uses that function to execute the command system
The Main Program Logic function processes command line parameters and determines the operation mode. The main operation requests are: list, run and install. These points will be mentioned later.
Ansible Exploitation
Let’s find any file related to playbook
:
You can see here that there is another runner2 file, but only users in the sys_adm group can access it. Continue with file enumeration.
Fortunately, the login credentials of the lopez user were found in the /var/log/suricata folder. Suricata is an open source network detection tool that can capture the login information.
Check the successful login section, find the login credentials of user lopez as lopez/Lopezz1992%123 , and use it to log in to ssh.
Lopez can run the runner2
file and is in the sys-adm
group. Let’s check the content of the runner2
file.
I forgot to take the screenshot of this part, but the location of the file is /opt/runner2/
.
Checked the permissions of runner2 and find that they are all root, which means that as long as you find the use method of runner2, you can get the root permissions.
Now we will use IDA to analyze the runner2
file. IDA is a disassembler and debugger that can be used to analyze binary files. The main functions of IDA are: disassembly, debugging, and decompilation. The disassembly function is to convert the binary code into assembly code, and the debugging function is to debug the program. The decompilation function is to convert the assembly code into a high-level language code.
After analysis, it is known that the parameters it receives are .json files, and need to contain role_file and auth_code. Combined with the runner1 file, the final utilization method can be concluded as:
Let’s try the list action first.
However, when I tried to run the run
action, it does not work.
As mentioned earlier, running a Playbook will use system to execute shell commands, so there may be command injection vulnerabilities.
I found that the parameters are: %s -i %s %s%s . The vulnerability is that if the attacker can control any part of the entered string, he can make a file containing shell metacharacters or control characters (,,,, etc.) name or path. When executing the constructed command, the shell will interpret these metacharacters, allowing arbitrary commands to be executed, but we do not have write permissions under /opt/playbook.
Fortunately, there is another exploit in the installRole
function:
Now we can create a fake .tar.gz and modify its name to execute any command. It should be noted that /usr/bin/ansible-galaxy will verify whether it is a valid compressed file, so it must be generated using a template. Here is the template
Now we just need to execute the json
file with sudo
permission.
Conclusion
This machine is challenging for me, especially the privilege escalation part, even harder when the machine is buggy, I have to reset and repeat the process multiple times. But overall, I learned a lot from this machine, especially the ansible
exploitation part. I hope you enjoy reading this write-up and learned something new. Thank you for reading.