[Hack The Box] Forge— Walkthrough

Gerard De Las Armas
6 min readJan 22, 2022

Summary

Forge is a simple box that does not involve any guesswork. It is an introduction to Server-Side Request Forgery (SSRF). The main website allowed access to the admin website via SSRF which led to sensitive information disclosure. The admin website allowed access to FTP which led to another sensitive information disclosure and an SSH access to the box.

To get root, I directed execution to the Python Debugger and worked my way to get a shell.

Foothold

Nmap

I started off Nmap, as usual, to discover available services in the machine.

nmap -sC -sV -vvv -oA nmap/forge-default 10.10.11.111
nmap -p- -oA nmap/forge-all 10.10.11.111
nmap -sU -vvv -oA nmap/forge-udp 10.10.11.111

Only two services are available — 22/tcp/ssh and 80/tcp/http. Nmap also showed 21/tcp/ftp as filtered which was a telltale sign that FTP is running but the box won’t accept connections from external network.

forge.htb

Checking port 80/tcp/http in my browser, I was redirected to http://forge.htb right off the bat so I had to add that in my /etc/hosts.

127.0.0.1            localhost10.10.11.111         forge.htb

The forge.htb website was a simple website that allowed users to upload an image via local file or from URL. When I uploaded an image, the website returned a URL with unique alphanumeric as a path parameter and when I clicked the URL, the website redirected me to the image I uploaded.

When I uploaded a file that is NOT an image, the website cannot display it.

However, in BurpSuite, I was able to see the content of the file I uploaded.

gobuster

I fired up gobuster to check for any hidden directories.

gobuster dir -u http://forge.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 20 -o forge.htb.gobuster.txt

However, gobuster did not find any useful directories that can help me.

wfuzz

Then I fired up wfuzz to check for any possible subdomain of forge.htb.

wfuzz -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt — hw 26 -H “Host: FUZZ.forge.htb” http://forge.htb

And found one — admin.forge.htb.

admin.forge.htb

I added admin.forge.htb to my /etc/hosts.

127.0.0.1            localhost10.10.11.111         forge.htb
10.10.11.111 admin.forge.htb

The admin.forge.htb only allowed localhost to access it.

Server-Side Request Forgery

I figured if I can send an HTTP request to admin.forge.htb, that will be great and then I remembered that in forge.htb, I can type in a URL when I upload an image and I can get the result in BurpSuite. So I tried to type in http://admin.forge.htb in the URL in hopes to get the content of admin.forge.htb in BurpSuite but forge.htb said the URL contained a blacklist.

Apparently there was a [simple] blacklisting going on here. To circumvent this, I used the redirector.py from HackTricks.

redirector.py

The redirector.py redirects the HTTP traffic to any HTTP URL I desire. My IP address was not blacklisted so I ran redirector.py in my local machine and have it redirected to http://admin.forge.htb.

python3 redirector.py 8000 http://admin.forge.htb

Then I typed in my IP address and port of redirector in the upload URL and checked BurpSuite.

I was able to see the HTML page of admin.forge.htb in BurpSuite.

Sensitive Information Disclosure

I took note of /announcements and /upload. To check what is in /announcements, all I have to do is to change the URL parameter of the redirector.py, upload an image by URL again in forge.htb and check the response in BurpSuite.

python3 redirector.py 8000 http://admin.forge.htb/announcements

There were a few things to note and they were already in a list — (a) FTP credentials with a username aptly named user, (b) /upload of admin.forge.htb supports ftp among others, and (c) /upload of admin.forge.htb supports the GET parameter u as in URL.

Server-Side Request Forgery — anotha one

The next logical step is to chain another SSRF — to FTP this time. Again, change the URL parameter of the redirector.py, upload an image by URL again in forge.htb and check the response in BurpSuite.

python3 redirector.py 8000 'http://admin.forge.htb/upload?u=ftp://user:heightofsecurity123!@10.10.11.111'

BurpSuite showed me this:

Okaaayyy, I saw user.txt. I figured this directory is the home directory of user due to the fact that user.txt is there.

Sensitive Information Disclosure — anotha one

So if this is the home directory of user, maybe I can search for credentials, such as SSH private keys — and I did.

python3 redirector.py 8000 'http://admin.forge.htb/upload?u=ftp://user:heightofsecurity123!@10.10.11.111/.ssh/id_rsa'

And just as I’ve thought

User

SSH

It was just a matter of logging in via SSH.

Check for permissions

As I typed sudo -l, I discovered I can run a Python script /opt/remote-manage.py as root without supplying a password.

The contents of /opt/remote-manage.py:

/opt/remote-manage.py

This Python script opens a random port from 1025 to 65535 on localhost interface. To interact with it, I had to forward the port via SSH after running it. To do that while in SSH, type

[Enter]
~C # The prompt will change to ssh>
-L [RANDOM_GENERATED_PORT]:[REMOTE_HOST]:[REMOTE_PORT]

Luckily tmux was available in the box so I was able to open multiple window panes in one SSH session.

Root

Examining the Python Script

The /opt/remote-manage.py seemed like a straightforward Python script but I didn’t recognize any easy and usual exploitation such as (a) hijacking the system command execution because the script did not use any user input when executing system command and (b) hijacking binaries and/or Python libraries because I was not allowed to set my own environment variables such as PATH and PYTHONPATH.

I looked up a statement found inside the Exception clause — pdb.post_mortem(e.__traceback__) — to see what it does and found out that pdb is Python Debugger and the post_mortem function allows the examination of the exception that took place. I had to trigger an exception to interact with the Python Debugger and I was able to do that in one of two ways: (a) enter one or more letter when I was asked “What do you wanna do:” — this will trigger a ValueError because the script expects an integer number or (b) issue a SIGINT by pressing CTRL+C —this will trigger a KeyboardInterrupt exception in Python.

To get to a Python interpreter from the Python Debugger, I issued the command

!import code; code.interact(local=vars())

From here on out, it was a piece of cake. All I had to do is to spawn a shell.

import os
os.system('/bin/bash')

And get root.txt

Conclusion

This box is a good introductory box for beginners without needing any guesswork when completing it. It teaches basic SSRF attacks and bypass & how to chain them to get more access. The Python script is a nice addition to the box because it presents a different way of exploiting Python scripts. Overall, I enjoyed completing Forge.

--

--