> For the complete documentation index, see [llms.txt](https://sayonara.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sayonara.gitbook.io/writeups/hackthebox/machines/soccer.md).

# Soccer

## <mark style="color:red;">Intro</mark>

In this article I’m going to be tackling `Soccer` machine, an easy difficulty Linux machine on `hackthebox.com`

soccer is an easy difficuly machine, this machine uses `Tiny File Manager` with default credentials giving access to a vulnerable version of Tiny File Manager which leads to a reverse shell to the target system using a weak upload functionality. enumerating the machine `(nginx config files)` reveals a hidden subdomain that is vulnerable to a `Boolean Based SQLI` that we will exploit using `SQLMAP` to dump `SSH Credentials` for the user `player`, this user can run `dstat` with root privileges which is an alternative to sudo, by leveraging a `dstat python plugin` we can execute code on the machine with root privileges and escalate privileges to become root.

<div align="left"><figure><img src="/files/Lm2KdyoxkksVZiLkHKNq" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">Scanning Using Nmap :</mark>&#x20;

<div align="left"><figure><img src="/files/Bpudf2Du9GfrPpBxc5aN" alt=""><figcaption></figcaption></figure></div>

* **`-sC`:** It is an Nmap option that enables the use of default scripts for service and version detection.
* **`-sV`:** It is an Nmap option that enables version detection against open ports.
* **`-oA nmap/soccer`:** It is an Nmap option to specify the output filename. In this case, it will save the output in three formats: normal, XML, and grepable. The files will be named "soccer.nmap," "soccer.xml," and "soccer.gnmap" respectively. The output files will be stored in the "nmap" directory.
* **`10.10.11.194`:** It is the IP address of the target host that you want to scan.

### <mark style="color:blue;">HTTP port 80 :</mark>&#x20;

let's visit the website open on port 80 but when we type  at the search bar [http://10.10.11.194:80\&#x20](https://sayonara.gitbook.io/writeups/hackthebox/machines/http:/10.10.11.194:80\&#x20);

<div align="left"><figure><img src="/files/ZMH97CoIPG6HUKIFewEj" alt=""><figcaption></figcaption></figure></div>

but all request are forwareded to <http://soccer.htb> and since soccer.htb is not known we will get server not found error so what we need is to assign the ip address 10.10.11.194 to soccer.htb name in the /etc/hosts file

<div align="left"><figure><img src="/files/6JWCXR8hEWtYghFy7Kzc" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/jpIwqnJQhnnc7egtUDuB" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/zyn4pQQOV7r9nA4AwvmN" alt=""><figcaption></figcaption></figure></div>

### <mark style="color:blue;">Web Server port 9091 :</mark>

<div align="left"><figure><img src="/files/5KCEn7rNIvorGqGxQnb9" alt=""><figcaption></figcaption></figure></div>

based on the response to the "GetRequest" sent to port 9091/tcp, it appears that the server is running a web server and if we search for the html tag resulting for an Error \<pre>Cannot GET\</pre> we will find that this web server is Nodejs

<div align="left"><figure><img src="/files/jDWuy8fD3RyyCOX6y52j" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">Directory Enumeration using Gobuster :</mark>&#x20;

<div align="left"><figure><img src="/files/3act7VahIhhmaaLqICQM" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/xYPHTOrRCsmUUNY0PrUq" alt=""><figcaption></figcaption></figure></div>

### <mark style="color:blue;">Default Credentials :</mark>&#x20;

[**https://exploit-notes.hdks.org/exploit/web/tiny-file-manager-pentesting/**](https://exploit-notes.hdks.org/exploit/web/tiny-file-manager-pentesting/)

<div align="left"><figure><img src="/files/efAVugIwvqfvRcqRBMPu" alt=""><figcaption></figcaption></figure></div>

let's log in using default admin credentials `admin : admin@123` and we are logged in&#x20;

&#x20;

<div align="left"><figure><img src="/files/WpLAS0HGWUNc9ISGTGuS" alt=""><figcaption></figcaption></figure></div>

at the right bottom we can notice that the Tiny File Manager Version is 2.4.3

now let's search for an upload functionality so we can uplaod a reverse shell

go to tiny

<div align="left"><figure><img src="/files/Bq7iKuIYRf8fif4GtQrt" alt=""><figcaption></figcaption></figure></div>

and then uploads

<div align="left"><figure><img src="/files/EYavlTxcI5J27zCVgZiF" alt=""><figcaption></figcaption></figure></div>

and then upload

<div align="left"><figure><img src="/files/pK5QElBc7czsJo07cSYE" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/InXbPIO7EPSuINpn8Don" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">Uploading Pentest Monkey Php Reverse Shell :</mark>

download the reverse shell script

link **:** [**https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php**](https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php)

copy the content of the reverse shell script and copy it to a file called shell.php and then update values of **“$ip”** and **“$port”** in the above script to our local ip and port for listener which will start. Then upload the script to the arbitrary folder in the Tiny File Manager dashboard.

<div align="left"><figure><img src="/files/FFeKejBRfBv5Axz7bzt3" alt=""><figcaption></figcaption></figure></div>

and now upload the reverse shell script&#x20;

<div align="left"><figure><img src="/files/pzIz6uAQiUSJ7MwVRDig" alt=""><figcaption></figcaption></figure></div>

and now the <mark style="color:blue;">shell.php</mark> file is uploaded into <mark style="color:purple;">**/var/www/html/tiny/uploads**</mark> so to execute that file we have to go to <mark style="color:purple;">**<http://soccer.htb/tiny/uploads/shell.php>**</mark>

but before that we have to setup a listener so we capture the reverse tcp connection made when executing the reverse shell script

<div align="left"><figure><img src="/files/vwgqUg5Wj8wA3by1b3dJ" alt=""><figcaption></figcaption></figure></div>

now let's execute the script by visiting <mark style="color:purple;">**<http://soccer.htb/tiny/uploads/shell.php>**</mark>

<div align="left"><figure><img src="/files/kFCk1y39B2gbAO7WQvRN" alt=""><figcaption></figcaption></figure></div>

and Boom we've a shell into the machine as <mark style="color:blue;">**www-data**</mark> user

<div align="left"><figure><img src="/files/4tAx5hGweSYtEABCE31B" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">Upgrading the shell :</mark>&#x20;

<div align="left"><figure><img src="/files/1ZOrfTNUdtT9fQJUbwBH" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">Enumerating the 9091 service based on processes :</mark>&#x20;

now controlling the machine with the privileges of www-data user let's take a look at all the listening network sockets along with their associated processes and PID (process id) number using <mark style="color:blue;">**`ss -lntp`**</mark>&#x20;

<div align="left"><figure><img src="/files/hwCiRhxhwKgyHKqGGpiI" alt=""><figcaption></figcaption></figure></div>

The <mark style="color:blue;">**`ps -ef --forest`**</mark> command is used to display a process listing in a tree-like format, showing the hierarchical relationship between processes but no information related to the 9091 service

<div align="left"><figure><img src="/files/1DNDAGt1n3MDH5Ex0eRT" alt=""><figcaption></figcaption></figure></div>

and this is because of the <mark style="color:blue;">**hidepid=2**</mark> option is is used to restrict access to process information in the `/proc` filesystem. When `hidepid=2` is set, only the process owner and privileged users (typically root) can access the process information directories under `/proc`. Other users will not be able to see the directories or contents of processes they do not own.

* **`hidepid=0`:** No restriction; all users can access all process information.
* **`hidepid=1`:** Restricted access; users can access only their own process information.
* **`hidepid=2`:** Strong access restriction; only the process owner and privileged users can access the process information

<div align="left"><figure><img src="/files/x0mEqzYt9NkGhUwzGSX8" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">Enumerating nginx configuration files for potential subdomains :</mark> &#x20;

```python
cd /etc/nginx/sites-enabled
cat soc-player.htb
```

<div align="left"><figure><img src="/files/fPs9zndKWN3Tf4MZBceG" alt=""><figcaption></figcaption></figure></div>

now let's add this subdomain to the /etc/host file so we can navigate to it

<div align="left"><figure><img src="/files/f0QcTE4p3ZWq48jwTOEq" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/1u4zdplsFOeMBbc3y0K0" alt=""><figcaption></figcaption></figure></div>

this subdomain page is similar to the landing page the diffrence is that there is added functionnality in this subdomain like the signup and login functionnalities

trying to login with default credentials or sql injection didn't work for me so what we'll do is create an acount using signup page

<div align="left"><figure><img src="/files/e7Q95cy6jwnk1FTjR1l3" alt=""><figcaption></figcaption></figure></div>

after logging in using those credentials we will be redirected to the <mark style="color:blue;">**`/check`**</mark> endpoint where it checks whether a ticket id exists or no&#x20;

<div align="left"><figure><img src="/files/lk2quTsY4knkgCFGFVnK" alt=""><figcaption></figcaption></figure></div>

press `CTRL + U` to see the source code and you will find the javascript script that implements the check functionality

```markup
<script>
        var ws = new WebSocket("ws://soc-player.soccer.htb:9091");
        window.onload = function () {
        
        var btn = document.getElementById('btn');
        var input = document.getElementById('id');
        
        ws.onopen = function (e) {
            console.log('connected to the server')
        }
        input.addEventListener('keypress', (e) => {
            keyOne(e)
        });
        
        function keyOne(e) {
            e.stopPropagation();
            if (e.keyCode === 13) {
                e.preventDefault();
                sendText();
            }
        }
        
        function sendText() {
            var msg = input.value;
            if (msg.length > 0) {
                ws.send(JSON.stringify({
                    "id": msg
                }))
            }
            else append("????????")
        }
        }
        
        ws.onmessage = function (e) {
        append(e.data)
        }
        
        function append(msg) {
        let p = document.querySelector("p");
        // let randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
        // p.style.color = randomColor;
        p.textContent = msg
        }
    </script>
```

this script establishes a WebSocket connection with a nodejs server on port 9091 and listens for key presses, sends messages over the WebSocket connection when the "Enter" key is pressed, receives messages from the server, and updates the HTML content (Ticket Exists or not) on the page with the received message

## <mark style="color:red;">**Blind Boolean SQLI**</mark> <mark style="color:red;">:</mark>&#x20;

<div align="left"><figure><img src="/files/Aq5oBc3uabbDBLrwcI7L" alt=""><figcaption></figcaption></figure></div>

to intercept the web socket message using burp we have to open the network tab on the developper tool `CTRL + SHIFT + i` and then press Enter&#x20;

make sure that the websocket proxy options are enabled

<div align="left"><figure><img src="/files/1Xd5gHgxCrbVI3X0Y21g" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/5ugITUYIgmoRu2dmZyGE" alt=""><figcaption></figcaption></figure></div>

now if we go back to burp we will see that the websocket message is intercepted now

<div align="left"><figure><img src="/files/wqnoDP4s6x7XazbvMrSf" alt=""><figcaption></figcaption></figure></div>

send it to repeater

<div align="left"><figure><img src="/files/04y58LTh1JqNYPAqScWp" alt=""><figcaption></figcaption></figure></div>

now let's copy the request to a file to use sqlmap to automate the boolean sqli

<div align="left"><figure><img src="/files/0p20dXCNKCkPWCsKgVjl" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/obtcoXiztRSWd844ufFS" alt=""><figcaption></figcaption></figure></div>

The <mark style="color:purple;">**"ws\://"**</mark> URI scheme is used to specify the WebSocket protocol and the WebSocket server's address and port. For example the URI <mark style="color:purple;">**"ws\://soc-player.soccer.htb:9091"**</mark> indicates that a WebSocket connection is being established with the server at **"soc-player.soccer.htb"** on port **9091**.

### <mark style="color:blue;">WebSocket Testing and Debugging :</mark>&#x20;

testing if <mark style="color:purple;">**soc-player.soccer.htb:9091**</mark> is a valid socket name and it's

<div align="left"><figure><img src="/files/3OtLvsLwfUAB55OL7Z83" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/rO7oTYJwNawyn1F6IJPz" alt=""><figcaption></figcaption></figure></div>

* **-u :** this flag specifies the target URL as `ws://soc-player.soccer.htb:9091`, which is a WebSocket URL
* **--data {"id":"\*"} :** The `--data` option in `sqlmap` is used to specify the data payload to be sent as part of an HTTP POST request and the \* specifies where to inject SQLI payloads
* **--dbs :** This option is used to instruct the tool to enumerate the available databases on the target server during the SQL injection testing process&#x20;
* **--threads :** This option is used to specify the number of concurrent threads to be used during the SQL injection testing process. Each thread represents a separate request made by `sqlmap` to the target server.
* **--risk :** This option sets the risk level of the SQL injection tests. The risk level determines how aggressively `sqlmap` performs the tests. It accepts an integer value from 1 to 3.
* **--level :** This option sets the level of tests to perform in terms of techniques and payloads used by `sqlmap`. It also accepts an integer value from 1 to 5.&#x20;
* **--batch :** This option instructs `sqlmap` to run in non-interactive mode, which means it will not prompt for user input during the testing process, it will automatically make decisions based on its default or configured options and proceed with the SQL injection detection and exploitation process without user intervention.
* **--technique=B :** This option is used to specify the technique to be used for exploiting SQL injection vulnerabilities. The `--technique=B` parameter you provided indicates the use of the "Boolean-based blind" technique.&#x20;

<div align="left"><figure><img src="/files/jGika3Zvxyd7GX7KcLcm" alt=""><figcaption></figcaption></figure></div>

now let's dump the columns (username and password columns) of soccer\_db database&#x20;

<div align="left"><figure><img src="/files/J60ubvXl3uCktBXtbBN3" alt=""><figcaption></figcaption></figure></div>

* **-D :** This option is used to specify the target database name to be selected during the SQL injection testing process
* **--dump :** option is used to extract and dump the contents of database tables

<div align="left"><figure><img src="/files/TZF2GHnM9iBerJi5ONe0" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">SSH into the BOX using the dumped creds :</mark>&#x20;

The database is dumped successfully, revealing the credentials `player:PlayerOftheMatch2022` , which we can use to SSH into the box.

<div align="left"><figure><img src="/files/qK4DwHQTUntxOokD8dFt" alt=""><figcaption></figcaption></figure></div>

### <mark style="color:orange;">User Flag :</mark>&#x20;

<div align="left"><figure><img src="/files/YF2KGSERcAZckJhoNHEN" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:red;">Privilege Escalation :</mark>&#x20;

to search for SUID bit set run this command

```python
find / -perm -u=s -type f 2>/dev/null
```

and the more interesting one here is the doas binary which is an alternative to sudo

<div align="left"><figure><img src="/files/XL119KGCdyV4eROqlLOu" alt=""><figcaption></figcaption></figure></div>

to  search for the doas confuguration file run this command

```python
find / -type f -name "doas.conf" 2>/dev/null
```

`doas.conf` file is the configuration file for the `doas` (do as) command, which is an alternative to `sudo`. It allows users to run specific commands with the privileges of another user, typically the root user, after authentication

ased on the content you provided (`permit nopass player as root cmd /usr/bin/dstat`), the `doas.conf` file configuration allows the user `player` to execute the `/usr/bin/dstat` command as the `root` user without requiring a password

This means that the user `player` can run the `dstat` command with root privileges by simply executing `doas /usr/bin/dstat` without being prompted for a password.

<div align="left"><figure><img src="/files/EwuziLAtrDcMElgAtTuA" alt=""><figcaption></figcaption></figure></div>

dstat gives the possibility of using Python plugins for the tool and since wecan run it as root we can leverage a privilege escalation by running a python plugin that elevates our privileges

### <mark style="color:red;">1. Creating New dstat Plugin :</mark> &#x20;

first off, find and locate the `dstat` directory

```python
find / -type d -name dstat 2>/dev/null
```

<div align="left"><figure><img src="/files/1E3uwwHYkRxr7LiB9gHr" alt=""><figcaption></figcaption></figure></div>

we have to pick the one we have write permissions on and `/usr/local/share/dstat` is the one we will work on&#x20;

<div align="left"><figure><img src="/files/NRkWTuCn7TPUBfIFYVwC" alt=""><figcaption></figcaption></figure></div>

Create a plugin called `dstat_exploit.py` under `/usr/local/share/dstat/`

<div align="left"><figure><img src="/files/hv2iQplbDWqMRgRIFFQT" alt=""><figcaption></figcaption></figure></div>

```python
import os

os.system('chmod +s /usr/bin/bash')
```

dstat recognizes plugins under `/usr/local/share/dstat/`.\
Check if the above exploit plugin has been added by executing the following command.

```python
#in general
dstat --list

#in our case
doas /usr/bin/dstat --list
```

<div align="left"><figure><img src="/files/JW8DmURxrIQkaY7f84da" alt=""><figcaption></figcaption></figure></div>

### <mark style="color:red;">2. Execute dstat With The Malicious Plugin :</mark>  <a href="#id-2.-execute-dstat-with-the-malicious-plugin" id="id-2.-execute-dstat-with-the-malicious-plugin"></a>

Now execute `dstat` with `—exploit` flag (the flag name is determined by the suffix of the file name e.g. `dstat_<plugin-name>.py` ).

```python
doas /usr/bin/dstat --exploit
```

and Boom our Python Plugin have been executed

<div align="left"><figure><img src="/files/VYR8GJM1CKDhreY9GuP4" alt=""><figcaption></figcaption></figure></div>

since we have set the permissions to run /usr/bin/bash in the python plugin now let's execute it

```python
bash -p
```

<div align="left"><figure><img src="/files/TfBxyZqEWAjSTAKK6po6" alt=""><figcaption></figcaption></figure></div>

### <mark style="color:orange;">Root Flag :</mark>&#x20;

<div align="left"><figure><img src="/files/QXm9BW9wqMMfG1uA0Uru" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/DxoVORHyVxT5h42vH7ho" alt=""><figcaption></figcaption></figure></div>

hope you found this walkthrough easy to understand and follow

Greeting From [<mark style="color:red;">Sayonara</mark>](https://github.com/ismail-arame)
