Skip to main content

FTP

FTP is one of the oldest services you’ll meet on an engagement, and one of the most generous when misconfigured. Anonymous logins, world-readable files, writable web roots, and chatty banners make it a reliable first foothold.
Protocol: TCP · Port: 21 (data on 20)

FTP vs TFTP

FTP (File Transfer Protocol) transfers files between a client and server over TCP port 21, with user authentication and a full set of commands. TFTP (Trivial File Transfer Protocol) is the stripped-down cousin. It runs over UDP, has no authentication, no password-protected login, and no directory listing. In practice it only operates on globally readable/writable files, so it should only ever appear on local, protected networks — and when you find it exposed, that’s already a finding. A few core TFTP commands:
CommandPurpose
connectSet the remote host (and optionally port) for transfers
getPull a file from the remote host to the local host
putPush a local file onto the remote host
statusShow current status — transfer mode, connection, timeout
verboseToggle extra information during transfers
quitExit tftp
Remember: unlike FTP, TFTP can’t list directories — you have to already know the filename you want.

Default Configuration

One of the most common FTP servers on Linux is vsFTPd, configured in /etc/vsftpd.conf. It’s only one of many FTP servers, but it’s the one you’ll see most often. Key settings in a default vsftpd.conf:
# /etc/vsftpd.conf
listen=NO                        # run standalone or from inetd
listen_ipv6=YES                  # listen on IPv6
anonymous_enable=NO              # allow anonymous access?
local_enable=YES                 # allow local users to log in?
dirmessage_enable=YES            # show messages when entering directories
use_localtime=YES
xferlog_enable=YES               # log uploads/downloads
connect_from_port_20=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd          # PAM service name
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO
There’s also /etc/ftpusers, which denies specific users access to FTP even if they exist on the system. For example, listing guest, john, and kevin there blocks those accounts from logging in:
# /etc/ftpusers
guest
john
kevin

Dangerous Settings

The setting that matters most to an attacker is anonymous access. In vsftpd.conf, the anonymous-related options look like this:
SettingEffect
anonymous_enable=YESAllow anonymous login
anon_upload_enable=YESLet anonymous users upload files
anon_mkdir_write_enable=YESLet anonymous users create directories
no_anon_password=YESDon’t even ask anonymous for a password
anon_root=/home/username/ftpRoot directory for anonymous sessions
write_enable=YESAllow write commands: STOR, DELE, RNFR, RNTO, MKD, RMD, APPE, SITE
anonymous_enable=YES combined with write_enable=YES or anon_upload_enable=YES is the dangerous pairing — it means anyone can not only read files but drop their own. On an FTP server tied to a web root, that’s a path to a web shell.
When you connect, the server greets you with response code 220 and a banner — which often discloses the service description and even its version. Even when you can’t download anything, just listing the directory contents can hand you names and intel for another angle of attack.

Footprinting the Service

Anonymous Login

The first thing to try is logging in as anonymous (any password, often blank):
ftp 10.129.14.136
Connected to 10.129.14.136.
220 "Welcome to the HTB FTP service."
Name (10.129.14.136:user): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
ftp> ls
200 PORT command successful.
150 Here comes the directory listing.
drwxr-xr-x    2 0        125          4096 Jun 25  2024 pub
226 Directory send OK.

Get an Overview with status

To see how the server is configured at a glance, use status:
ftp> status
Connected to 10.129.14.136.
No proxy connection.
Connecting using address family: any.
Mode: stream; Type: binary; Form: non-print; Structure: file
Verbose: on; Bell: off; Prompting: on; Globbing: on
Store unique: off; Receive unique: off
Case: off; CR stripping: on

Reveal More with debug and trace

Turning on debug and trace makes the server show you more of what’s happening under the hood — useful for understanding its behavior:
ftp> debug
Debugging on (debug=1).
ftp> trace
Packet tracing on.
ftp> ls
---> PORT 10,10,14,4,228,12
200 PORT command successful.
---> LIST
150 Here comes the directory listing.

Spotting hide_ids and ls_recurse_enable

If hide_ids=YES is set, the UID/GID of files is overwritten (shown as ftp or 0), making it harder to tell what rights files were written with. Conversely, if ls_recurse_enable=YES is set — common on vsFTPd for convenience — you can list the entire directory tree in one shot:
ftp> ls -R
.:
drwxr-xr-x    3 0   0   4096 Jun 25  2024 pub

./pub:
drwxr-xr-x    2 0   0   4096 Jun 25  2024 backup

./pub/backup:
-rw-r--r--    1 0   0    582 Jun 25  2024 config.bak

Download Everything

When the server has a large folder structure, you can mirror the whole thing at once with wget. Be aware this is noisy — nobody legitimately downloads an entire FTP server in one go:
wget -m --no-passive ftp://anonymous:anonymous@10.129.14.136
wget creates a directory named after the target’s IP and stores everything there for offline inspection.

Test Upload Access

Check whether you can upload — especially valuable when the FTP server is tied to a web server, since developers often sync files between them. Upload access there can mean dropping a web shell and getting code execution:
ftp> put shell.php
local: shell.php remote: shell.php
200 PORT command successful.
150 Ok to send data.
226 Transfer complete.
Upload access to an FTP server connected to a web root is one of the cleanest paths to a reverse shell. Drop a web shell, browse to it, and you’ve turned a file server into command execution.

Scanning FTP

Network scanners make footprinting easier and can find FTP even on non-standard ports. Nmap’s NSE scripts are the standard approach. First, the FTP-related NSE scripts live in /usr/share/nmap/scripts/ and can be found with:
find / -type f -name "ftp*" 2>/dev/null | grep scripts
Run the default FTP scripts with version detection:
nmap -sV -p21 -sC -A 10.129.14.136
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxr-xr-x    2 0   125   4096 Jun 25  2024 pub
| ftp-syst:
|   STAT:
| FTP server status:
|      Connected to ::ffff:10.10.14.4
|      Logged in as ftp
|      TYPE: ASCII
|_     vsFTPd 3.0.3 - secure, fast, stable
To watch what the NSE scripts are doing at the network level, add --script-trace. It shows the commands Nmap sends, the ports used, and the server’s responses — including the banner returned to one of the parallel NSE connections:
nmap -sV -p21 -sC -A 10.129.14.136 --script-trace

Interact Manually with netcat / telnet

You can also talk to the server directly:
nc -nv 10.129.14.136 21
telnet 10.129.14.136 21

TLS/SSL FTP with openssl

If the server runs with TLS/SSL (FTPS), you need a client that speaks it. openssl works and has the bonus of showing you the SSL certificate, which can itself contain useful information:
openssl s_client -connect 10.129.14.136:21 -starttls ftp
CONNECTED(00000003)
---
Certificate chain
 0 s:CN = ftp.inlanefreight.htb
   i:CN = ftp.inlanefreight.htb
---
220 Welcome to the secure HTB FTP service.

Quick Reference

CommandPurpose
ftp <ip>anonymousAttempt anonymous login
ftp> statusOverview of server settings
ftp> debug / traceReveal protocol-level detail
ftp> ls -RRecursive listing (if enabled)
wget -m --no-passive ftp://anonymous:anonymous@<ip>Mirror the whole server
ftp> put <file>Test upload access
nmap -sV -sC -p21 <ip>NSE enumeration
openssl s_client -connect <ip>:21 -starttls ftpConnect to FTPS, view cert
The footprinting flow: anonymous login → status for config → recursive listing → download everything → test upload → fall back to nmap/openssl for banner and version intel.
Next: SMB — shares, null sessions, and pulling files off Windows file servers.