Use of insecure channel - Source code
Need
Transmission of credentials and files only over encrypted connections
Context
• Usage of Kotlin 1.9+ on the JVM for building application services
• Usage of the Apache Commons Net library for FTP and SMTP connections
Description
1. Non compliant code
import org.apache.commons.net.ftp.FTP
import org.apache.commons.net.ftp.FTPClient
import java.io.File
fun uploadReport(report: File, user: String, password: String) {
// Credentials and file contents travel in clear text
val ftp = FTPClient()
ftp.connect("ftp.partner.example.com")...The `uploadReport` function below sends a file to a partner with `FTPClient` from Apache Commons Net, logging in with a user name and a password. Plain FTP sends everything in clear text: the `USER` and `PASS` commands with the credentials, and the file on the data channel. Anyone on the network path, such as a compromised router, a shared Wi-Fi network or a cloud neighbor with access to the traffic, can capture the credentials and the report, or modify the file in transit. `SMTPClient` and `TelnetClient` from the same library have the same problem, and so does an OkHttp client configured with `ConnectionSpec.CLEARTEXT`, which allows plain HTTP.
2. Steps
• Replace `FTPClient` with `FTPSClient` and call `execPBSZ(0)` and `execPROT("P")` after login, or use SFTP over SSH.
• Replace `SMTPClient` with `SMTPSClient`, or with `AuthenticatingSMTPClient` and `execTLS()` before authenticating.
• Remove `TelnetClient` and use SSH for remote shells.
• Enable host name verification with `setEndpointCheckingEnabled(true)` and keep the default trust store.
• Do not use `ConnectionSpec.CLEARTEXT` in OkHttp clients outside of local development.
3. Secure code example
import org.apache.commons.net.ftp.FTP
import org.apache.commons.net.ftp.FTPSClient
import java.io.File
fun uploadReport(report: File, user: String, password: String) {
// Implicit TLS protects the login; PROT P encrypts the data channel too
val ftps = FTPSClient(true)
ftps.setEndpointCheckingEnabled(true)...The corrected function uses `FTPSClient` with implicit TLS (`FTPSClient(true)`), so the TLS handshake happens before any FTP command and the credentials are never sent in clear text. After logging in, it sends `PBSZ 0` and `PROT P`, which switch the data channel to TLS as well; without them, FTPS protects the password but still transfers the file unencrypted. It also enables host name verification, so the client only accepts a certificate issued for the partner's server. When the partner supports it, SFTP over SSH, for example with the `sshj` library, is a simpler alternative. For email, `SMTPSClient` or `AuthenticatingSMTPClient` with `execTLS()` replaces `SMTPClient`, and Telnet should be replaced with SSH, since it has no secure variant.
References
• 332. Use of insecure channel - Source code