Hello! Today let's pawn the HTB machine Sau. This is again rated Easy and it was truly easy. User own was little tricky mainly because I had to tweak the curl request a lot but root own was truly a piece of cake. So, without further ado let's start hacking!
Enumeration
First thing I did was run an nmap scan on the target to get information about the services running on the machine.
┌──(kali㉿kali)-[~]└─$nmap-sV-sC-Pn10.10.11.224StartingNmap7.94 ( https://nmap.org ) at 2023-07-15 10:33 EDTNmapscanreportfor10.10.11.224Hostisup (0.16s latency).Notshown:997closedtcpports (conn-refused)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH8.2p1Ubuntu4ubuntu0.7 (Ubuntu Linux; protocol2.0)|ssh-hostkey:|3072aa:88:67:d7:13:3d:08:3a:8a:ce:9d:c4:dd:f3:e1:ed (RSA)|256ec:2e:b1:05:87:2a:0c:7d:b1:49:87:64:95:dc:8a:21 (ECDSA)|_256b3:0c:47:fb:a2:f2:12:cc:ce:0b:58:82:0e:50:43:36 (ED25519)80/tcpfilteredhttp55555/tcpopenunknown|fingerprint-strings:|FourOhFourRequest:|HTTP/1.0400BadRequest|Content-Type:text/plain; charset=utf-8|X-Content-Type-Options:nosniff|Date:Sat,15Jul202314:34:29GMT|Content-Length:75|invalidbasketname; thenamedoesnotmatchpattern:^[wd-_\.]{1,250}$| GenericLines, Help, Kerberos, LDAPSearchReq, LPDString, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie:
|HTTP/1.1400BadRequest|Content-Type:text/plain; charset=utf-8|Connection:close|Request|GetRequest:|HTTP/1.0302Found|Content-Type:text/html; charset=utf-8|Location:/web|Date:Sat,15Jul202314:34:00GMT|Content-Length:27| href="/web">Found</a>.|HTTPOptions:|HTTP/1.0200OK|Allow:GET,OPTIONS|Date:Sat,15Jul202314:34:00GMT|_Content-Length:01 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-Port55555-TCP:V=7.94%I=7%D=7/15%Time=64B2AE55%P=x86_64-pc-linux-gnu%r(GSF:etRequest,A2,"HTTP/1\.0\x20302\x20Found\r\nContent-Type:\x20text/html;\SF:x20charset=utf-8\r\nLocation:\x20/web\r\nDate:\x20Sat,\x2015\x20Jul\x20SF:2023\x2014:34:00\x20GMT\r\nContent-Length:\x2027\r\n\r\n<a\x20href=\" w="" sf:eb\"="">Found</a>\.\n\n")%r(GenericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Re
SF:quest\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\xSF:20close\r\n\r\n400\x20Bad\x20Request")%r(HTTPOptions,60,"HTTP/1\.0\x202SF:00\x20OK\r\nAllow:\x20GET,\x20OPTIONS\r\nDate:\x20Sat,\x2015\x20Jul\x20SF:2023\x2014:34:00\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequestSF:,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;SF:\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request"SF:)%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20texSF:t/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20SF:Request")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConSF:tent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\SF:r\n400\x20Bad\x20Request")%r(TerminalServerCookie,67,"HTTP/1\.1\x20400\SF:x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nCSF:onnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(TLSSessionReq,67,"SF:HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20cSF:harset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(KSF:erberos,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20textSF:/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20RSF:equest")%r(FourOhFourRequest,EA,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nSF:Content-Type:\x20text/plain;\x20charset=utf-8\r\nX-Content-Type-OptionsSF::\x20nosniff\r\nDate:\x20Sat,\x2015\x20Jul\x202023\x2014:34:29\x20GMT\rSF:\nContent-Length:\x2075\r\n\r\ninvalid\x20basket\x20name;\x20the\x20namSF:e\x20does\x20not\x20match\x20pattern:\x20\^\[\\w\\d\\-_\\\.\]{1,250}\$\SF:n")%r(LPDString,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:SF:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20SF:Bad\x20Request")%r(LDAPSearchReq,67,"HTTP/1\.1\x20400\x20Bad\x20RequestSF:\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20cloSF:se\r\n\r\n400\x20Bad\x20Request");ServiceInfo:OS:Linux; CPE:cpe:/o:linux:linux_kernelServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.Nmapdone:1IPaddress (1 hostup) scanned in 115.75 seconds</a\x20href=\">
Nmap shows 3 open tcp ports. One is SSH, one is port 80 mostly used for web servers and one is port 55555. Port 55555 is a webpage. But, nmap returns three different HTTP codes, code 404, 302 and 200. 200 OK is the one I would like to focus on. 200 OK is for a subdirectory /web. So, let's visit port 55555 and subdirectory /web.
Interesting! The service running on this port is request-baskets. According to official github "Request Baskets is a web service to collect arbitrary HTTP requests and inspect them via RESTful API or simple web UI." Even the machine icon on htb has a picture of a basket. Very sneaky Sau ;)
Anyways, I create a basket on port 55555 and try to understand what is going on here.
I create a basket named "test". The website gives me a prompt with a token. This token might be useful so I copy this token for future reference. Now the basket is created and we can send requests. So, I try to send a GET request to the basket link.
And, sure enough we get to see the request on the web page. (You can notice the discrepancy in the dates of nmap scan and the GET request, that's because I lost all my screenshots and had to create them again -_-)
Initial Foothold
So, the requests work. Now, if we can send requests like this to the basket, it might be possible to inject some commands. I explore the icons on the top right and find a forwarding feature.
What does this forwarding do? I research a little and et voila! There's a vulnerability in the Request baskets service. A Server-Side Request Forgery (SSRF) via the component /api/baskets/{name}. We can access network resources and sensitive information via the crafted API request.
We can send this information as a curl request, but I will craft it in the web page itself. I tweaked the payload a bit and enabled both Proxy Response and Expand Forward Path.
Then, I try visiting http://10.10.11.224:80/test but with no luck. This was a little time consuming for me because I had to try lot of requests. Finally, I got a response out of sheer luck on http://10.10.11.224:55555/test. A new service is running here, Maltrail.
Getting User Shell
Now, I did a little research on Maltrail and turns out Maltrail has a vulnerability of unauthorised command injection. Here, we can run commands without needing authentication. The exploit code is:
The exploit code only works for /login directory. Right now, we are redirecting all our requests to /test. So, we need to change that to /login for the exploit to work.
Now, let's tweak the exploit a little. I will insert a bash script as a command to get a reverse shell. First create a bash.sh file on your host machine.
Let's run the exploit now. I disabled the Expand Forward Path on my basket configuration so the URL http://10.10.11.224:55555/test redirects straight to http://127.0.0.1:80/login.
What this will do is first retrieve the bash.sh file from host machine with curl, and then run the command as bash script. Look at your netcat listener and [hacker voice] I'm in.
┌──(kali㉿kali)-[~]└─$nc-lvnp4444listeningon [any] 4444 ...connectto [10.10.14.30] from (UNKNOWN) [10.10.11.224] 51704bash:cannotsetterminalprocessgroup (914): Inappropriate ioctl for devicebash:nojobcontrolinthisshellpuma@sau:/opt/maltrail$whoamiwhoamipuma
The user flag can be found at /home/puma/user.txt.
Privilege Escalation
As this is an easy box, I run the sudo -l command to check if there are any misconfigurations.
We can run the /usr/bin/systemctl status trail.service command without password. I visited GTFOBins and found a less vulnerability on sudo services. But first, I spawn a TTY with python3 -c 'import pty;pty.spawn("/bin/bash")'.