Beyond


┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ curl -s http://forge.htb/uploads/D5QHeBGiZSgYIDkVA2GD           
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdkg75DLB+Cd+2qjlqz6isdb/DVZusbqLoHtO/Y91DT02LE6a0dHeufEei6/j+XWk7aeM9/kZuNUcCwzAkNeYM2Nqpl8705gLsruGvsVXrGVRZOHBwqjSEg5W4TsmHV36N+kNhheo43mvoPM4MjlYzAsqX2fmtu0WSjfFot7CQdhMTZhje69WmnGycK8n/q6SvqntvNxHKBitPIQBaDmA5F+yqELcdqg7FeJeAbNNbJe1/ajjOY2Gy192BZYGkR9uAWBncNYn67bP9U5unQggoR+yBf5xZdBS3xEkCcqBNSMYCZ81Ev2cnGiZgeXJJDPbEvhRhdfNevwaYvpfT6cqtGCVo0V0LTKQtMayIazX5tzqMmIPURKJ5sBL9ksBNOxofjogT++/1c4nTmoRdEZTP5qmXMMbjBa+JI256sPL09MbEHqRHmkZsJoRahE8tUhv0SqdaHbv2Ze7RvjNiESD6fIMrq6L+euZFhQ5p2AIpdHvOUSbeaCPiG7hwVqwf8qU= user@forge

The authorized_keys file was also available inside the SSH directory I could have fetched it and figured out the exact user

Default LIST command?


An SSRF attack via the url method, pointing to a virtual host located at admin.forge.htb, which could only be access through localhost From admin.forge.htb/announcements, I learned:

  1. There was an internal FTP server running.
  2. The /upload endpoint is also present with supports to upload from ftp servers with the u parameter.
  3. That’s precisely how I managed to send a GET request to http://admin.forge.htb/upload?u=ftp://user:heightofsecurity123!@localhost:21
  4. That resulted the following unexpected output
$ curl -s http://forge.htb/uploads/zpyh0ipEENsYBY0NQqXl 
drwxr-xr-x  3 1000 1000 4096 Aug 04 2021 snap 
-rw-r-----  1    0 1000   33 Apr 12 16:32 user.txt 
  1. The output looks much like that of both ls or dir command inside the FTP session

how is this possible? My expected output was a form of errors because the web application would NOT know what to upload as the FTP connection string never specified any resource. just pointing to the FTP server itself.

So I tried connecting to the FTP server once I gained foothold. The result is shocking.

user@forge:~$ curl -v 'ftp://user:heightofsecurity123!@localhost:21/'
*   Trying 127.0.0.1:21...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 21 (#0)
< 220 Forge's internal ftp server
> USER user
< 331 Please specify the password.
> PASS heightofsecurity123!
< 230 Login successful.
> PWD
< 257 "/home/user" is the current directory
* Entry path is '/home/user'
* Request has same path as previous transfer
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 229 Entering Extended Passive Mode (|||60807|)
*   Trying 127.0.0.1:60807...
* TCP_NODELAY set
* Connecting to 127.0.0.1 (127.0.0.1) port 60807
* Connected to localhost (127.0.0.1) port 21 (#0)
> TYPE A
< 200 Switching to ASCII mode.
> LIST
< 150 Here comes the directory listing.
* Maxdownload = -1
drwxr-xr-x    3 1000     1000         4096 Aug 04  2021 snap
-rw-r-----    1 0        1000           33 Apr 12 16:32 user.txt
* Remembering we are in dir ""
< 226 Directory send OK.
* Connection #0 to host localhost left intact

As soon as I connect to the internal FTP server from the target system using curl, it goes through a series of FTP commands including, LIST Those are NOT my inputs, it went through all that by itself.

The fact that this happened without any interaction from the web application confirms that this is not related to the web application. It’s likely an external influence from either a service or cronjob.

vsftpd


user@forge:~$ ps -auxwww | grep -i ftp
root         955  0.0  0.1   6808  3204 ?        ss   16:31   0:00 /usr/sbin/vsftpd /etc/vsftpd.conf

The running FTP service is vsftpd, loaded with a configuration file at /etc/vsftpd.conf

config


user@forge:~$ grep -v '^#' /etc/vsftpd.conf
listen=YES
listen_ipv6=NO
anonymous_enable=NO
local_enable=YES
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
ftpd_banner=Forge's internal ftp server
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO

The configuration file itself doesn’t have anything going on with the strange behavior I had to exclude all the lines starting with the # character to get rid of comments

So what could it be?

No more localhost


root@forge:/# service iptables restart

After compromising the system, I drop the firewall rule for port 21, and restarted the iptables service

┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ nmap -p21 $IP                                            
starting nmap 7.93 ( https://nmap.org ) at 2023-04-13 03:54 CEST
Nmap scan report for forge.htb (10.10.11.111)
Host is up (0.094s latency).
 
PORT   STATE SERVICE
21/tcp open  ftp
 
nmap done: 1 IP address (1 host up) scanned in 0.22 seconds

While the target FTP server is now accessible, I will test it directly from Kali

external


┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ curl -v 'ftp://user:heightofsecurity123!@10.10.11.111:21'
*   Trying 10.10.11.111:21...
* Connected to 10.10.11.111 (10.10.11.111) port 21 (#0)
< 220 Forge's internal ftp server
> USER user
< 331 Please specify the password.
> PASS heightofsecurity123!
< 230 Login successful.
> PWD
< 257 "/home/user" is the current directory
* Entry path is '/home/user'
* Request has same path as previous transfer
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 229 Entering Extended Passive Mode (|||10069|)
*   Trying 10.10.11.111:10069...
* Connecting to 10.10.11.111 (10.10.11.111) port 10069
* Connected to 10.10.11.111 (10.10.11.111) port 21 (#0)
> TYPE A
< 200 Switching to ASCII mode.
> LIST
< 150 Here comes the directory listing.
* Maxdownload = -1
-rwxr-xr-x    1 1000     1000      3104768 Apr 12 23:11 pspy64
drwxr-xr-x    3 1000     1000         4096 Aug 04  2021 snap
-rw-r-----    1 0        1000           33 Apr 12 16:32 user.txt
* Remembering we are in dir ""
< 226 Directory send OK.
* Connection #0 to host 10.10.11.111 left intact

It STILL does that.

BUSTED


After many trials and researches, I think I finally found out what was going on curl, by default, seems to get directory listing if the remote resource is a FTP server and not specified.

┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ wget -v 'ftp://user:heightofsecurity123!@10.10.11.111:21'
--2023-04-13 03:56:57--  ftp://user:*password*@10.10.11.111/
           => ‘.listing’
connecting to 10.10.11.111:21... connected.
Logging in as user ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD not needed.
==> PASV ... done.    ==> LIST ... done.
 
.listing                     [ <=>                               ]     786  --.-KB/s    in 0s      
 
2023-04-13 03:56:58 (110 MB/s) - ‘.listing’ saved [786]
 
Removed ‘.listing’.
Wrote HTML-ized index to ‘index.html’ [1410].

and wget does that too by saving it to the .listing file first and re-naming to index.html for better reviewing

┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ cat index.html                                           
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>index of / on 10.10.11.111:21</title>
</head>
<body>
<h1>index of / on 10.10.11.111:21</h1>
<hr>
<pre>
  2021 may 19        link        <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/.bash_history">.bash_history</a> -> /dev/null
  2020 feb 25        file        <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/.bash_logout">.bash_logout</a>  (220 bytes)
  2020 feb 25        file        <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/.bashrc">.bashrc</a>  (3771 bytes)
  2021 aug 04        directory   <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/.cache/">.cache/</a> 
  2023 apr 12 23:15  Directory   <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/.gnupg/">.gnupg/</a> 
  2020 feb 25        file        <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/.profile">.profile</a>  (807 bytes)
  2021 aug 04        directory   <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/.ssh/">.ssh/</a> 
  2023 apr 12 23:11  File        <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/pspy64">pspy64</a>  (3104768 bytes)
  2021 aug 04        directory   <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/snap/">snap/</a> 
  2023 apr 12 16:32  File        <a href="ftp://user:heightofsecurity123!@10.10.11.111:21/user.txt">user.txt</a>  (33 bytes)
</pre>
</body>
</html>

yeap.