HackTheBox – Forge

Welcome to another HackTheBox blog entry, this time I’m gonna show the steps to resolve the Forge challenge, categorized as medium level of difficulty. The user is solved chaining vulnerabilities in the web server, then the privilege escalation involves a Python functionality which is executed as root with SUDO.

Initial enumeration

We start with a port scan with Nmap, we see the ports 80 and 22 opened:

Additionally, the results returned the port 21 filtered, which means that something could be listening but not reachable. Normally the filtered state is received because the server has returned RST reponse to the initial SYN sent by Nmap. We could verify this fact trying to access the FTP service, the timeout is obtained.

Web app enumeration

As usual, we skip any action to SSH and start directly with the HTTP service, since it is normally the entry point of the HackTheBox machines. The web server is redirecting us to “forge.htb” as you can see in the following image, where a 302 is received and the Location in the response header is pointing to “forge.htb”:

After adding the hostname to the /etc/hosts file, we can access the web application and it looked like this.

The web application is pretty simple, the only interesting functionality is a file uploader in /upload:

It has two ways of working, uploading the file from the attacker’s machine and upload the file from URL. This last method usually can be abused to access internal services, which are not reachable from outside. This vulnerability is officially named SSRF (Server Side Request Forgery).

If we access to the uploaded file, remarked in red, we can see that the file is successfully downloaded from the HTTP server.

Okay, it seems interesting. If we were able to download internal files (for example using “file:///etc/passwd”) we could for example read something like the private key of any user to access by SSH. The first problem we faced is a blacklist in the hostname:

That is not a big deal, since the server has a known IP 10.10.11.111 and it is not blacklisted. The second problem is another blacklist in the scheme:

Unfortunately, the only two enabled schemes are “http” and “https” according to the server’s response. Therefore, there is not much else to do here and we proceed with other type of web enumeration. The first one is to scan the directories, for instance we could use Gobuster:

Nothing new, the second check is the subdomain enumeration, we use Wfuzz to easily check other domains:

Reaching the administrator panel

Bingo, the subdomain “admin” to the rescue ! After adding it to the /etc/hosts file we access the URL “http://admin.forge.htb” and in the following image you can see that the server’s response indicates that there is any whitelist of IP to access the web application only from localhost.



This came immediately to my mind the SSRF vulnerability we found, which basically is useful to this situations. We can access the content of the “admin.forge.htb” web page using the Upload functionality. However, the new hostname is also blacklisted:

So… At this moment, some lateral thinking is required. We need to access the contents of the “http://admin.forge.htb” from localhost and this will be only possible through the SSRF in the “http://forge.htb/upload” page.

Since we can force the “forge.htb” to request to an attacker-controlled web server any resource, we can also control the response that our server will return to the “forge.htb” web application. One possibility is to return a 302 response code and indicate a location with the “Location” in the server’s response header. This would redirect the request to another page, which could be “admin.forge.htb”.

To achieve this redirection, a custom server could be implemented in Python. For example, the following code will redirect the client’s request to the URL indicated in the arguments (source):

We launch the web server in the port 80 and indicate the “http://admin.forge.htb” to be the final URL. Then, we abuse the SSRF to access our deployed web server and successfully downloaded the content of the admin web page.

Obtaining SSH session

The administration portal has a endpoint in /announcements, let’s see the contents of this page:

In the announcements page are the credentials to access the internal FTP server and it also explains that there is another Upload endpoint in the Administrator’s panel which allows schemes like “ftp” or “ftps”.

Now we might be theoretically able to access the contents of the FTP server through the SSRF, configuring the redirecting server to the “ftp://10.10.11.111” with the found credentials and the following request is enough:

Fortunately, the FTP server is pointing to the user’s home, so we should be able to access the private key in “ftp://10.10.11.111/.ssh/id_rsa”:

Alright ! using this private key we obtain a SSH session:

Privilege escalation

Checking if the user is able to execute commands with SUDO, we saw the following output.

The contents of the script is in the following image:

The first thing that should catch our attention is the fact that the programs have been executed with “subprocess” without the full path. This error is very common and could lead an attacker to a Path Hijacking attack that allowed us to obtain the root access in the Previse challenge.

However, in this case this will not be possible because the permissions have been securely configured in the “sudoers” file according the the “sudo -l” output.

From the documentation:

  • env_reset: If set, sudo will run the command in a minimal environment containing the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables. Additionally, If the secure_path option is set, its value will be used for the PATH environment variable.

Although the Path Hijacking is not possible, a deeper analysis of the code revealed an interesting library “pdb” and the “post_mortem” method in the exception block of the script. From the official documentation:

It seems like some kind of debug process is raised when we execute this method. We want to understand what is the meaning of this function so we use a Python interpreter in our local machine to see how it looks.

Okay we see an intesting (Pdb) prompt that indicates some kind of command interpreter. As we want to get command execution using this piece of code, let’s see if we can execute python commands.

So we only need to put all the pieces together to obtain a Bash session with Root permissions. Analyzing the code it is straightforward to reach the error and obtain the shell.

Posted on