Skip to main content

Use of an insecure channel - FTP

Need

Secure transmission of customer information

Context

  • Usage of Python 3 for writing and executing Python scripts
  • Usage of ftplib for FTP file transfer operations

Description

Non compliant code

from ftplib import FTP

def send_file_over_ftp(filename):
ftp = FTP('ftp.example.com')
ftp.login(user='username', passwd='password')
ftp.storbinary('STOR '+filename, open(filename, 'rb'))
ftp.quit()

In this piece of code, we are using the FTP (File Transfer Protocol) to send a file over the network. The FTP class from the ftplib module in Python is used to establish a connection to the FTP server, login with the provided username and password, and send a file to the server.

Here's a breakdown of the functions used:

  • FTP('ftp.example.com'): This establishes a connection to the FTP server at 'ftp.example.com'.
  • ftp.login(user='username', passwd='password'): This logs into the FTP server with the provided username and password.
  • ftp.storbinary('STOR '+filename, open(filename, 'rb')): This sends a file to the server. The 'STOR' command is used to start the upload process, and the file is opened in binary mode for reading.
  • ftp.quit(): This closes the connection to the FTP server.

The vulnerability here lies in the fact that FTP does not use encryption, and so the data being sent (including the login credentials) can be easily intercepted and read in plain text. This can lead to unauthorized access to the FTP server, data breaches, and other security issues.

Steps

  • Replace FTP with a secure protocol like SFTP or FTPS which provide secure file transfer.
  • Use libraries that support these secure protocols.
  • Ensure that the server you are connecting to also supports the secure protocol.
  • Update the login credentials to use secure methods provided by the new protocol.
  • Ensure that the file transfer is done over the secure channel.

Compliant code

from ftplib import FTP_TLS

def send_file_over_ftp(filename):
ftps = FTP_TLS('ftp.example.com')
ftps.login(user='username', passwd='password')
ftps.prot_p() # Switch to secure data connection
with open(filename, 'rb') as file:
ftps.storbinary('STOR '+filename, file)
ftps.quit()

The updated code uses the FTP_TLS class from the ftplib module, which is a FTP subclass which adds SSL/TLS support to FTP as described in RFC-4217.

Here's a breakdown of the changes:

  1. from ftplib import FTP_TLS: This imports the FTP_TLS class from the ftplib module. FTP_TLS is a subclass of FTP that adds support for the FTPS protocol (FTP over SSL/TLS).

  2. ftps = FTP_TLS('ftp.example.com'): This creates a new FTP_TLS object. This object represents a connection to an FTP server over SSL/TLS.

  3. ftps.login(user='username', passwd='password'): This logs into the FTP server using the provided username and password. The communication during the login process is encrypted using SSL/TLS.

  4. ftps.prot_p(): This switches the data connection to be protected by SSL/TLS. This means that any data sent over this connection (including the file being uploaded) will be encrypted.

  5. with open(filename, 'rb') as file:: This opens the file in binary mode for reading. The 'with' statement ensures that the file is properly closed after it is no longer needed.

  6. ftps.storbinary('STOR '+filename, file): This uploads the file to the FTP server. The file data is sent over the secure data connection, so it is encrypted.

  7. ftps.quit(): This closes the connection to the FTP server.

By using FTP_TLS instead of FTP, the code ensures that both the login credentials and the file data are encrypted when they are sent over the network. This prevents them from being intercepted in transit.

References