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:
-
The code imports the necessary modules:
express
for creating the server,fs
for file system operations, andssh2-sftp-client
for establishing an SFTP connection. -
An instance of the
express
application is created. -
An instance of the
ssh2-sftp-client
is created to establish an SFTP connection. -
The code defines a route handler for the
/download
endpoint usingapp.get()
. This endpoint expects a query parameterfile
to specify the file to be downloaded. -
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. -
After a successful connection, the code retrieves the requested file using
client.get()
. The file is streamed directly to the response objectres
usingstream.pipe(res)
. -
In case of any errors during the connection or file retrieval, the code sends a 500 status response with an error message.
-
Finally, the SFTP connection is closed using
client.end()
in thefinally
block to ensure proper cleanup. -
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.