soccer
Recon
Start off with a basic nmap scan:
|
|
|
|
Not much going on in terms of open ports and exposed services. Visiting http://soccer.htb there is a website dedicated to soccer (no surprise given the box name).
Fuzzing for directories shows http://soccer.htb/tiny/ which may be of interest.
|
|

Visiting that URL, we find a file manager:

If you google “h3k tiny file manager”, one of the top results should be a GitHub repo containing the code for the file manager present on the soccer website: https://github.com/prasathmani/tinyfilemanager. A quick trip through the documentation reveals the default credentials are admin/admin@123, which work on the soccer website.
In order to get code exec on the box , we are going to upload a webshell, and leverage that into a full reverse shell. Create shell.php with the following contents:
|
|
Upload shell.php to tiny/uploads/ in the file manager (as we don’t seem to have permission to upload to the root). Access it, and see that it works by visiting http://soccer.htb/tiny/uploads/shell.php?cmd=id. You should get the output of the id command.
Note that there seems to be a script on the box that is clearing the contents of the uploads folder on a periodic basis, so you may have to upload the shell again.
We can generate a reverse shell on https://www.revshells.com/. Im going to use python3 #2, as I find it to be reliable in these situations, and I verified that python3 is already on the box by running which python3 in the webshell.
My full reverse shell command with the URL included is:
|
|

Escalation to Player
When we get on the box, we can see there is a player user, who has the user flag in their home directory. However, as www-data, we don’t have permission to read it.
Since the webserver is nginx, its worth looking at the config to check for sensitive information, or if we missed an vhosts during initial recon. Looking in /etc/nginx/sites-available/ we see there is a config for soc-player.soccer.htb config. Add that to the host file and lets see what that new site is.
It seems to be very similar to soccer.htb, but with some added functionality. Lets create an account to see what we might be able to exploit. After creating an account and logging in, we get directed to the /check endpoint, where we can check if certain ticket numbers exist. If you put in your ticket id, found at the top of the form, you can see you get back the message “Ticket Exists”.

This smells like a boolean based SQLi. However, when looking through requests in Burpsuite and trying to capture the request used to check the ticket, you might be puzzled to find its not there. This is because the submission is being done through a websocket, listening on the port 9091 which we found in our initial nmap scan. You can find the websocket requests in the “Websockets history” subtab under the “Proxy” tab.

If we were going to try to find a SQLi manually, this would not pose an issue. However, I am lazy, and want to use sqlmap to automate this for me.
In order to use sqlmap through a websocket, we will need a intermediary server to convert the regular http requests from sqlmap to websocket requests, and vise-versa. I found a brilliant script at https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html. Full credit to the author for writing this, as I only made minor changes to adapt it to my needs.
Here is what I used:
|
|
After starting the above python script, you can run sqlmap as follows:
|
|
The * next to the number in the id parameter indicates to sqlmap that we want to test that parameter.
If the above command fails and breaks the websocket when checking for a time based SQLi, you can reset the box and leave out those tests by running the following:
|
|
technique=BEUS leaves out the time based attacks. You can read more about that here.
Dumping the database reveals players password to be PlayerOftheMatch2022, which can be used with ssh.

Escalation to root
As player, we can run linpeas to try to find any escalation paths.
After running, we see that player can run dstat as root using the doas command.

GTFObins gives us easy to follow, copy paste command to get root:
