Skip to main content

Use of an insecure channel - FTP

Need

Secure transmission of customer information

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and APIs
  • Usage of fs for file system operations
  • Usage of FTP for transferring files over a network

Description

Non compliant code

import express from 'express';
import fs from 'fs';
import ftp from 'ftp';

const app = express();
const client = new ftp();

app.get('/download', (req, res) => {
const file = req.query.file;

client.connect({
host: 'ftp.example.com',
user: 'username',
password: 'password'
});

client.get(file, (err, stream) => {
if (err) {
res.status(500).send('Error occurred while downloading the file');
} else {
stream.pipe(res);
}
});
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The vulnerability in this code is the use of an insecure channel, specifically FTP, to transmit customer information. The code uses the 'ftp' module to connect to an FTP server and download a file based on the user's request.

However, FTP does not provide encryption, which means that the credentials and confidential information being transmitted can be captured by an attacker in plain text. This leaves the user's credentials vulnerable to interception and potential misuse.

To fix this vulnerability, the application should be deployed over an encrypted communication channel, such as SFTP (SSH File Transfer Protocol) or HTTPS. These protocols provide secure encryption for data transmission, ensuring that sensitive information remains confidential and protected from unauthorized access.

Steps

  • Replace the 'ftp' module with a module that supports secure file transfer, such as 'ssh2-sftp-client'.
  • Install the 'ssh2-sftp-client' module using npm or yarn.
  • Import the 'ssh2-sftp-client' module in your code.
  • Create a new instance of the 'ssh2-sftp-client' class.
  • Update the connection details to use SFTP instead of FTP.
  • Use the 'connect' method to establish a secure connection to the SFTP server.
  • Replace the 'get' method with the 'get' method provided by the 'ssh2-sftp-client' module.
  • Update the error handling and response code accordingly.
  • Start the Express server and test the file download functionality.

Compliant code

import express from 'express';
import fs from 'fs';
import { Client } from 'ssh2-sftp-client';

const app = express();
const client = new Client();

app.get('/download', async (req, res) => {
const file = req.query.file;

try {
await client.connect({
host: 'ftp.example.com',
port: 22, // SFTP port
username: 'username',
password: 'password'
});

const stream = await client.get(file);
stream.pipe(res);
} catch (err) {
res.status(500).send('Error occurred while downloading the file');
} finally {
client.end();
}
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The fixed code addresses the vulnerability by using a secure communication channel (SFTP) instead of the insecure FTP channel. Here's an explanation of the changes made:

  1. The code imports the necessary modules: express for creating the server, fs for file system operations, and ssh2-sftp-client for establishing an SFTP connection.

  2. An instance of the express application is created.

  3. An instance of the ssh2-sftp-client is created to establish an SFTP connection.

  4. The code defines a route handler for the /download endpoint using app.get(). This endpoint expects a query parameter file to specify the file to be downloaded.

  5. Inside the route handler, the code connects to the SFTP server using client.connect(). It provides the host, port (22 for SFTP), username, and password for authentication.

  6. After a successful connection, the code retrieves the requested file using client.get(). The file is streamed directly to the response object res using stream.pipe(res).

  7. In case of any errors during the connection or file retrieval, the code sends a 500 status response with an error message.

  8. Finally, the SFTP connection is closed using client.end() in the finally block to ensure proper cleanup.

  9. The server starts listening on port 3000 using app.listen().

By using SFTP instead of FTP, the code ensures that customer information and credentials are transmitted securely over an encrypted channel, mitigating the risk of interception and unauthorized access.

References