Home Hackthebox - Forge
Post
Cancel

Hackthebox - Forge

This box was solved over multiple days and redeployed multiple times. IP’s used in commands may change throughout the article.

Forge is an easy Linux box hosting a picture gallery application. The application allows us to upload new images from an URL. A scan of virtual hosts gives us the admin.forge.htb subdomain which is only reachable from the box itself. The main application can be abused request pages from admin.forge.htb . The subdomain is hosting the same website, but a newer version. It has an announcement which contains FTP credentials. This newer version also allows to specify a FTP URL for uploading images. With this FTP connection we can download the private SSH key of the user. To escalate our privileges we abuse a python script we are allowed to run as root. When the script encounters an error we get an interactive PDB shell. This allows us to execute any python code as root.

Enumeration

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ sudo nmap -sC -sV -oA nmap/forge 10.129.177.192
Starting Nmap 7.92 ( https://nmap.org ) at 2022-01-02 07:11 EST
Nmap scan report for 10.129.177.192
Host is up (0.037s latency).
Not shown: 997 closed tcp ports (reset)
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-title: Did not follow redirect to http://forge.htb
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: Host: 10.129.177.192; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.42 seconds

HTTP - 80

The main page is a redirect to forge.htb. It is hosting an image gallery webpage: There also is a way to upload new images from an URL: After running some gobuster scans I found the admin.forge.htb subdomain (really a virtual host):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
gobuster vhost -u http://forge.htb/ -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -r
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:          http://forge.htb/
[+] Method:       GET
[+] Threads:      10
[+] Wordlist:     /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent:   gobuster/3.1.0
[+] Timeout:      10s
===============================================================
2022/01/10 15:05:25 Starting gobuster in VHOST enumeration mode
===============================================================
Found: admin.forge.htb (Status: 200) [Size: 27]

===============================================================
2022/01/10 15:05:57 Finished
===============================================================

However, the virtual host is only accessible from localhost:

Let’s try to abuse the main application to access the admin page.

After trying some different filter evasion strategies, I found that just making the host uppercase let’s us access the admin site. We can now view the admin page by going to the given url: We can repeat this process for any page on the admin subdomain. Let’s have a look at the anouncements: It gives us FTP credentials and shows us how to access the FTP through the admin site (I couldn’t access the FTP from my machine). We can test the connection by providing

1
http://ADMIN.FORGE.HTB/upload?u=ftp://user:heightofsecurity123!@FORGE.HTB/

as a url on the main page.

The result looks strangely like a home directory. This lead me to try retrieving the .ssh directory and downloading the user’s private ssh key: We can now SSH into the box as user and get user.txt.

PE

To escalate our privilegs I had a look at sudo -l. It tells us we can execute a python script as root.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/env python3
import socket
import random
import subprocess
import pdb

port = 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()

If we find a way to crash the program it will give us a python pdb shell (line 39 of the script). Line 27 gives us a way to crash the program. It will try to convert our input into an integer. If we provide anything that isn’t a number, the pdb shell will be activated. This pdb shell allows us to executy arbitrary commands as root through the system module.

Recap

This box was all about filter bypasses and SSRF (Server Side Request Forgery). We were able to bypass the filter in the main application to send requests to a restricted virtual host. Using the SSRF vulnerabiltiy we were able to get access to the FTP server which was mapped to the user’s home directory. We extracted his private key and abused a pdb shell inside a python script which we could run as root.

Overall a fun box that made me think about novel ways to bypass filters.

This post is licensed under CC BY 4.0 by the author.