Skip to main content

Use of an insecure channel - FTP

Need

Secure transmission of customer information

Context

  • Usage of Go 1.16 for developing high-performance and efficient applications
  • Usage of gin-gonic/gin for building web applications and APIs in Go
  • Usage of ftp library for FTP file transfer operations
  • Usage of net/http for creating HTTP servers in a Node.js application

Description

Non compliant code

package main

import (
"github.com/gin-gonic/gin"
"github.com/jlaffaye/ftp"
"net/http"
)

func main() {
r := gin.Default()

r.GET("/ftp", func(c *gin.Context) {
conn, err := ftp.Dial("ftp.example.com:21")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

err = conn.Login("user", "password")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

data, err := conn.List("/")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, data)
})

r.Run()
}

The above code snippet describes a simple Gin web server that has an endpoint /ftp which connects to an FTP server, logs in with a username and password, lists the files in the root directory, and returns the list of files as a JSON response.

The vulnerability lies in the usage of the FTP protocol for transmitting data. FTP does not encrypt data and therefore any sensitive information such as usernames, passwords, and file content can be easily intercepted and read by anyone who can capture network traffic between the client and the server.

In the context of this code, the username and password used to login to the FTP server are sent in plaintext over the network. If an attacker is able to intercept this traffic, they can gain unauthorized access to the FTP server. Furthermore, the content of the files listed by the conn.List("/") command can also be intercepted and read in plaintext.

To mitigate this vulnerability, a secure protocol such as SFTP or FTPS should be used which encrypts the data transmission, preventing it from being read if intercepted.

Steps

  • Replace the use of FTP with a secure protocol such as SFTP or HTTPS.
  • Use a library or package that supports secure protocols for file transfer.
  • Ensure that the server you are connecting to supports secure protocols.
  • Update the code to establish a secure connection using the chosen secure protocol.
  • Encrypt the transmitted data to protect it from being captured in plain text.
  • Implement proper authentication mechanisms to secure access to the server.
  • Regularly update and patch the server to address any security vulnerabilities.

Compliant code

package main

import (
"github.com/gin-gonic/gin"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"net/http"
)

func main() {
r := gin.Default()

r.GET("/sftp", func(c *gin.Context) {
config := &ssh.ClientConfig{
User: "user",
Auth: []ssh.AuthMethod{
ssh.Password("password"),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}

conn, err := ssh.Dial("tcp", "sftp.example.com:22", config)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

client, err := sftp.NewClient(conn)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

files, err := client.ReadDir("/")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, files)
})

r.Run()
}

The original code was vulnerable because it used FTP, an insecure protocol that does not encrypt data during transmission. This could allow an attacker to capture credentials and confidential information in plain text.

The updated code replaces FTP with SFTP, a secure protocol that encrypts data during transmission. This prevents an attacker from capturing credentials and confidential information in plain text.

The ssh.Dial function is used to establish a secure connection to the server. The sftp.NewClient function is used to create a new SFTP client. The client.ReadDir function is used to list the files in the root directory of the server.

The ssh.ClientConfig struct is used to configure the SSH client. The User field is set to the username, and the Auth field is set to an array of ssh.AuthMethod that includes ssh.Password, which is set to the password. The HostKeyCallback field is set to ssh.InsecureIgnoreHostKey, which is a temporary measure to ignore host key checking and should be replaced with a proper host key checking mechanism in a production environment.

The c.JSON function is used to send a JSON response with the HTTP status code and the files in the root directory of the server, or an error message if an error occurred.

The server is run using the r.Run function.

References