Securing FTP with TLS
updated by
- rfc-8996 — Deprecating TLS 1.0 and TLS 1.1
Extracted elements (30)
FTP-TLS upgrades an existing plaintext FTP session in place on the standard port 21, rather than using a separate dedicated port. This is analogous to STARTTLS in SMTP (RFC 3207) and HTTP upgrade in RFC 2817, and avoids requiring firewall policy changes for a new port.
Only two PROT levels—'C' (Clear) and 'P' (Private)—are defined for FTP-TLS because TLS negotiation inherently encompasses and exceeds the distinctions between the 'S' (Safe/integrity-only) and 'E' (Confidential/privacy-only) levels; a single TLS session provides both integrity and confidentiality simultaneously.
The CCC command exists to accommodate NAT and firewall devices that must inspect the FTP control connection to adjust their behavior (e.g., for PORT/PASV address rewriting). Authentication and PROT negotiation happen under TLS protection, after which CCC drops TLS from the control channel while maintaining data connection protection.
PBSZ 0 is not strictly valid per the grammar in RFC 2228 Section 8.1, which specifies decimal integers from 1 to (2^32)-1. However, using '0' to mean a streaming (unbuffered) protocol is unambiguous in context and is required by this specification for FTP-TLS.
Server-to-server (proxy or third-party) data transfers are explicitly excluded from TLS protection under this specification, because neither server can simultaneously act as the TLS client while also acting as an FTP server in the firewall-friendly model.
The '334' response defined in RFC 2228 implies an ADAT exchange will follow, which does not occur with TLS. The correct server response to an accepted 'AUTH TLS' command is '234', not '334'.
TLS does not support the notion of TCP Urgent data, which FTP historically used to signal ABOR and STAT commands during data transfers via the Telnet IP/DM mechanism and SIGURG. Implementations MUST route these commands through the TLS session instead.
A client MUST allow a user to override the timing of the AUTH, PBSZ, and PROT commands to suit a specific server. Clients SHOULD NOT insist on sending AUTH as the first command, nor insist on issuing PBSZ/PROT directly after AUTH.
A client that wishes to secure an FTP session SHOULD send the AUTH command with the parameter 'TLS'. The client then behaves according to its policies based on the server response and the result of TLS negotiation; a client that receives an AUTH rejection MAY continue the session unprotected.
Even though TLS negotiation may provide authentication information, the USER command MUST still be issued by the client. It is a server implementation decision which credentials to accept and what consistency checks to make between the client certificate and the USER parameter.
Following an AUTH command, all transfer parameters MUST be reset, including (but not limited to) user identity, default data ports, TYPE, STRU, MODE, and current working directory—almost as if a REIN command was issued.
For data connections in the standard and firewall-friendly modes, the FTP client MUST be the TLS client and the FTP server MUST be the TLS server, regardless of which side initiates the TCP connection via connect() or accept().
If a server supports the FEAT command, it MUST advertise the AUTH, PBSZ, and PROT commands in the FEAT reply, and the AUTH reply should identify 'TLS' as a valid parameter.
The initial state of the data connection MUST be 'Clear' (no TLS protection), consistent with the behavior indicated by RFC 2228.
The PBSZ command MUST still be issued before PROT, but MUST have a parameter of '0' to indicate that no buffering is taking place and the data connection should not be encapsulated, as FTP-TLS operates as a streaming protection mechanism.
The PROT command MUST be preceded by a PBSZ command, and a PBSZ command MUST be preceded by a successful TLS negotiation. Once accepted, data connections MUST use the negotiated PROT security level until another PROT command is accepted, a REIN is issued, or AUTH is re-negotiated.
To request TLS protection in accordance with this document, the client MUST use the AUTH parameter 'TLS'. To maintain backward compatibility, the server SHOULD accept 'TLS-C' as a synonym; these parameters are case-insensitive.
When the REIN command is processed, the TLS session(s) MUST be cleared and the control and data connections revert to unprotected communications. The reply to REIN MUST be sent in a protected session prior to the session(s) being cleared. A server MUST NOT mandate the use of cached TLS sessions after REIN.
When TLS is in use, the server SHOULD NOT rely on SIGURG to process input on the control channel during data transfers. The client MUST send all data, including Telnet commands (used for ABOR and STAT), across the TLS session.
Reply code '521' ('data connection cannot be opened with this PROT setting') is used when a data transfer command (STOR, RETR, NLST, LIST, STOU, APPE) is rejected due to an incorrect PROT level. Reply code '522' indicates that TLS negotiation on the data connection failed or was unacceptable after the '150' was already issued.
The AUTH TLS command (parameter 'TLS') initiates TLS negotiation on the FTP control connection. The server responds with '234' to indicate it will honor the request; '334' is incorrect for this exchange as no ADAT command follows.
The CCC (Clear Command Channel) command reverts the control connection from TLS back to plaintext. On receipt, the server sends '200', shuts down the TLS session, and continues in plaintext. After CCC, the server MUST NOT accept further PBSZ or PROT commands; all subsequent data transfers use the previously negotiated PROT setting.
The PROT command sets the data connection security level. For FTP-TLS only 'C' (Clear: no TLS) and 'P' (Private: TLS with integrity and confidentiality) are used; 'S' (Safe) and 'E' (Confidential) are not applicable because TLS encompasses both.
The server SHOULD check the PROT status only at the data-transfer command (STOR, RETR, NLST, LIST, STOU, APPE) that initiates the connection, not at PORT or PASV time. The server may also insist that the data connection use a previously cached TLS session.
Port stealing remains a problem when client certificates are not used; strong client authentication on the data connection is required to prevent unauthorized connections from retrieving or submitting files. Without any strong authentication (e.g., anonymous DH), port stealing is unmitigated.
The CCC command introduces significant security risks described in RFC 2228. Servers SHOULD refuse to process CCC on sessions without client authentication (TLS client cert or USER/PASS), to prevent anonymous clients from issuing repeated AUTH TLS followed by CCC to exhaust server resources.
The certificate used for server (or client) authentication of data connections SHOULD be the same certificate used for the corresponding control connection. If different certificates are used, an alternative cross-checking mechanism must be provided to bind the identities of the two connections.
TLS bounce attacks are mitigated because the FTP server acts as TLS server in data connections, so only services configured as TLS clients could be targeted—a counter-intuitive configuration. Additionally, mismatched authentication credentials between data and control connections allow servers to detect and drop illegitimate connections.
Using anonymous Diffie-Hellman (no server certificate) eliminates server identity authentication and provides little protection against man-in-the-middle attacks. Without client certificates, a malicious client can still hijack a data connection (port stealing).
TLS negotiation failure on the control connection has three possible states: (1) complete failure—connection reverts to unprotected, server issues unprotected '421' or client issues unprotected QUIT; (2) successful negotiation but unacceptable parameters—connection stays protected, issue protected '421' or protected QUIT; (3) failure during handshake—connection is in unknown state, both sides SHOULD simply drop the connection.