FTP#
FTP (File Transfer Protocol, RFC 959) is the original file
transfer protocol from 1971, predates TCP/IP itself. Plaintext, two
connections per session (control + data), and a NAT-hostile design
that’s kept network engineers up at night for decades. For new work
the operator should reach for SFTP (SSH-tunneled), HTTPS, or
rsync over SSH. For legacy systems, embedded devices, anonymous
software mirrors, and CTF boxes, FTP is still everywhere, which is
why operators still need to read it. The protocol quirks, ftp /
lftp / curl clients, vsftpd / proftpd servers, FTPS
(TLS-wrapped FTP), and what makes FTP fundamentally insecure.
Ports:
Port |
Use |
|---|---|
21/TCP |
Control channel, commands and responses. |
20/TCP |
Active-mode data channel (server-initiated). |
ephemeral |
Passive-mode data channel (client picks server side). |
990/TCP |
Implicit FTPS (TLS at connect; deprecated). |
989/TCP |
Implicit FTPS data. |
Active vs passive mode#
The old design that breaks NATs and firewalls. The control channel (client → server:21) is normal; the data channel direction depends on mode:
Mode |
How the data channel opens |
|---|---|
Active |
Client tells server “connect back to my IP:port” via
|
Passive |
Client says |
sequenceDiagram
participant C as Client
participant S as Server port 21
Note over C,S: Passive mode (PASV), the modern norm
C->>S: TCP connect to port 21
S-->>C: 220 banner
C->>S: USER alice
S-->>C: 331 password please
C->>S: PASS p@ss
S-->>C: 230 logged in
C->>S: PASV
S-->>C: 227 reply with IP and port (10,0,0,5,200,15)
C->>S: TCP connect to data channel 10.0.0.5 port 51215
C->>S: RETR file.bin
S-->>C: 150 sending, data flows on data channel
S-->>C: 226 transfer complete
Common response codes#
Code |
Meaning |
|---|---|
|
Service ready (banner) |
|
User logged in |
|
Username OK, password required |
|
Not logged in (auth failed / required) |
|
Opening data connection |
|
Closing data connection (transfer OK) |
|
Can’t open data connection (firewall? port range?) |
|
File unavailable (busy) |
|
File / permission error |
Clients#
Tool |
Use |
|---|---|
|
Original interactive client; keeps a session. |
|
Operator’s choice; scriptable, mirror, segmented downloads, FTPS, SFTP, FXP. |
|
Quick one-shot get / put with TLS support. |
|
Recursive fetch ( |
|
Friendly interactive; auto-resume. |
|
GUI; FTP / FTPS / SFTP. |
# one-shot fetch (anonymous)
$ curl -O ftp://ftp.gnu.org/gnu/wget/wget-1.21.tar.gz
# authenticated put
$ curl -T report.pdf -u alice:pwd ftp://files.example.com/incoming/
# interactive session
$ ftp -inv ftp.example.com
ftp> user alice
ftp> bin # binary mode
ftp> passive on
ftp> cd /pub
ftp> ls
ftp> get file.bin
ftp> mput *.txt
ftp> bye
# lftp: scriptable, recursive
$ lftp -u alice,'pwd' -e '
set ftp:passive-mode on
cd /backup
mirror -R /var/backups /backup/host01
quit
' files.example.com
FTPS (FTP over TLS)#
Two flavours, with the usual TLS bolted-on confusion:
Flavour |
Notes |
|---|---|
Explicit |
Plain FTP on port 21; client issues |
Implicit |
TLS from byte one on port 990. Deprecated by RFC 2228 but still found on appliances. |
# explicit FTPS via curl
$ curl --ftp-ssl -u alice:pwd ftp://files.example.com/path/file
# explicit FTPS via lftp
$ lftp -u alice,pwd -e 'set ftp:ssl-force true; ls; quit' files.example.com
Note: don’t confuse FTPS with SFTP. SFTP is a different protocol, the file transfer subsystem of SSH on port 22, no relation to FTP. Use SFTP whenever possible.
Servers#
Server |
Notes |
|---|---|
|
“Very Secure FTPd”; default on many
distros; |
|
Apache-style modular config;
|
|
Light, command-line configured. |
|
Mostly Windows. |
Minimum-viable vsftpd config:
# /etc/vsftpd.conf
listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
chroot_local_user=YES
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
# FTPS (explicit)
ssl_enable=YES
rsa_cert_file=/etc/ssl/certs/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.key
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1_2=YES
Open ports 21 + the passive range on the host firewall.
Pentest / audit#
# find listeners
$ nmap -p 21 --open 10.0.0.0/24
# banner, anon login, syst, bounce-attack vector
$ nmap -p 21 --script ftp-anon,ftp-syst,ftp-bounce,ftp-vuln-cve2010-4221 host
# anonymous probe by hand
$ curl -v ftp://host/ # lists / on anon-enabled servers
# password spray
$ hydra -L users.txt -P passwords.txt ftp://host
$ medusa -h host -U users.txt -P pass.txt -M ftp
Why FTP is broken#
Plaintext credentials and data, a single passive sniff sees USER, PASS, and the file. Use FTPS, SFTP, or HTTPS instead.
NAT / firewall hostility, two channels per session; passive port range must be punched through the firewall.
FTP bounce (RFC 2577), the
PORTcommand historically let an attacker have a server connect anywhere on the attacker’s behalf; modern servers refuse this, but the legacy Nmap-bflag still works on weird gear.Anonymous read often == anonymous write,
vsftpd’sanon_upload_enableplus a writable/incoming/plus default config has been a recurring data-leak pattern.No good auth, no MFA, no key auth, no SSO. SFTP solves all of this.
Modern operator default: ban port 21 inbound; offer SFTP (or HTTPS upload, or rsync over SSH) instead.
See also#
SSH, SFTP, the secure replacement.
SSL/TLS, TLS for FTPS.
0X42 - Networks, finding FTP listeners.
man vsftpd.conf,man lftp,man curl(FTP options).RFC 959 (FTP), RFC 2228 (security extensions), RFC 4217 (FTP over TLS).