HacktheBox: Soccer Writeup

Veshraj Ghimire
PenTester Nepal
Published in
6 min readJun 10, 2023

Hey everyone, I wanted to share my experience doing the HackTheBox machine “Soccer”, which is rated as an “easy” machine. During my exploration, I discovered some new techniques and approaches, and I thought it would be helpful to share a walkthrough with you all. I’m very grateful to Kiran Ghimire for providing such a challenging and engaging environment to learn.

By the time of this writeup, the machine should have been retired. Still you can find it below:

Initial Recon

Let’s start with a basic Nmap scan. This allows us to see what ports are open and what services are running on those ports:

After running the Nmap scan, we can find that three ports are open: 22, 80, and 9091.

Let’s start with the port 80, where we can see it’s redirecting us to soccer.htb .In order to resolve the host, we need to add it to our /etc/hostsfile:

When we visit the host using our web browser, we see a single page with the Nginx web server running. There doesn’t seem to be anything interesting on the page.

Let’s fuzz for some interesting stuffs with FFUF:

While fuzzing, we can find a directory called /tiny that contains a web application called Tiny File Manager.

To try to gain access to the Tiny File Manager application, we can try for default credentials of tiny File Manager. After a bit of google, we can find that admin:admin@123 works. This gives us access to the application’s dashboard, which we can use to upload and manage files on the server.

So, We’re in!!

/isn’t writeable but /tiny/uploads is.
So, we can upload our php reverse shell to get a shell.

After successfully uploading our PHP reverse shell to the /tiny/uploads directory, we are able to establish a remote shell on the server. However, we can see that the shell was running as the www-data user, which had limited privileges. To be able to access the flag, we needed to escalate our privileges to gain greater control over the machine.

Let’s make the shell stable and do some enumeration. We knew that there are two users who can login with ssh (root&player) user.txt is on player’s home directory which we can’t read yet.

Privilege Escalation I (user)

As we had observed during our initial reconnaissance, the web server on the target machine was running Nginx. To see if we could find any additional information, we can start to explore some of the Nginx configuration files on the server.

Through this process, we can find that there is another subdomain running on the machine at “localhost:3000”. To access this subdomain, we have to add the hostname “soc-player.soccer.htb” to our “/etc/hosts” file (same as before)

Let’s try FUZZing this subdomain too.

Cool, this host seems to have more functionality than previous one.

After registering and logging in, we can notice a feature on endpoint /check which basically checks if the ticket exists.

Which looks to be vulnerable to SQL injection. This simple payload made the server sleep for 5 seconds.

The server was using Websocket which we knew from initial nmap scan too:

It took me few minutes to find following blog with good explanation and script to exploit this blind SQLi:

Let’s make our exploit ready and make the sqlmap do our job:

It takes some time to dump the database but at last we can get our credentials on accounts table of soccer_db with email and password on it.

Let’s try to ssh on the server with the credentials we got:

Here, we got our user flag.

Privilege Escalation II (root)

After few more enumeration, we got the unusual binary doas with special permission:

doas (“dedicated openbsd application subexecutor”) is a program to execute commands as another user.

Digging more, we can know that whenever the user player executes the command /usr/bin/dstat, the command can be executed with root privileges without requiring a password.

dstat is a tool that is used to retrieve information or statistics form components of the system such as network connections, IO devices, or CPU, etc.

dstat — list gives us the available operations within dstat:

Unfortunately the directory at /usr/share/dstat is unwritable but we can know the file formats from it (dstat_operation.py):

Since, we can write on /usr/local/share/dstat, it’s also included on dstat’s operations:

Now, since we know that, we can execute command as root. we can create a simple python file to execute the code as root user and run it:

The SUID bit was set! Now we just need to run /bin/bash -p to allow us to keep the elevated permissions as root from the SUID.

Pwned!!

Analyzing Vulnerable Code snippet:

So this was the code responsible for Blind SQL injection via Web socket:

var id = JSON.parse(data).id is parsing the incoming message from a websocket client and extracting the id field from the JSON object.

The vulnerability lies in the fact that the id value is being concatenated directly into the SQL query string without any proper sanitization or validation. This means that an attacker can potentially inject malicious SQL code as the id value, causing the query to execute unintended commands on the database.

In the vulnerable code, the SQL query is constructed using string concatenation with the id value as follows:

const query = `Select id,username,password  FROM accounts where id = ${id}`;

An attacker can craft a payload to manipulate the id value to execute unintended SQL commands.

To prevent these types of vulnerabilities, it’s recommended to use parameterized queries or prepared statements, which separate the query logic from the data input, and validate/sanitize the input to ensure it’s safe to use in the query.

Thanks for making it till the end, that’s all folks.
You can connect with me on Twitter if you wish to.

--

--