Copying files between computers is a common task, and there are a lot of protocols designed to do just that. But not all protocols are created equally. Many people use the popular OpenSSH scp command to transfer files, but few understand the risks surrounding it.
This blog post will attempt to explain what the SCP and SFTP protocols are, how they work, and why SFTP should be used wherever possible.
scp is widely known and used to copy files over the Secure Shell (SSH) protocol. It’s a tad bit confusing that it shares a name with the protocol it implements, the Secure Copy Protocol (SCP). SCP was designed to be a more secure version of the BSD Remote Copy Protocol (RCP), which supported file copying to and from remote machines. The problem with RCP is the protocol is unencrypted. RCP was designed in 1983 when network protocols generally didn’t use any cryptography. A malicious adversary could take advantage of this and either read or modify sensitive file contents as they are being transferred. SCP solves this problem by operating on top of SSH. SSH provides authenticity, confidentiality, and integrity, which SCP takes advantage of.
What happens when you send a file to a remote machine over SCP? Say you want to copy a file
source to a machine
server and write it to
destination. You would run:
scp simply invokes the
ssh command to open an SSH session and run a remote
scp has two undocumented flags
-f (“to” and “from”) that put it into server mode. In this case,
scp -t destination would be run remotely. This will cause the remote
scp process to create or truncate the file
destination, and write the received contents of the file
source over the established SSH connection to
Downloading a remote file is handled in much the same way. If the goal is to download the remote file
source from the machine
server and write it to
destination you would run:
scp will invoke the
ssh command to open an SSH session and run a remote
scp command. But this time,
scp -f source will be run instead. This will cause the remote
scp process to read and send the contents of the file
source to the local
scp process, which will be written to the file
Seems simple enough right? At it’s core, SCP really is a simple protocol, relying on SSH to pass file paths via command-line arguments.
SCP implementations have been subject to a fair share of vulnerabilities over the years, as does almost any piece of software that is widely used for a long time. To err is to be human, and writing completely secure software is an impossible endeavor, no matter how high the code quality and thorough the security practices. What is important is to:
If software is written to trust a minimal amount, verifying and validating everything reasonably possible, then the likelihood that vulnerabilities will be discovered is lowered significantly. If the power and privileges given to software is minimized, then when a vulnerability is inevitably discovered and exploited, the impact will be greatly lessened.
Historical vulnerabilities in SCP implementations show that neither of these two axioms hold. RCP’s outdated and insecure design that SCP inherits prevents it from sufficiently limiting the likelihood and impact of potential vulnerabilities.
In 2019 Harry Sintonen, a security researcher at F-Secure published an advisory containing multiple vulnerabilities to a few popular SCP clients.
Sintonen described the impact of the vulnerabilities as such:
In other words, if a user initiated a file to be downloaded from an SCP server, a malicious server could add or modify files in the directory the user specified as the output (or target) directory. Output from the local SCP client could be spoofed making detection of additional file downloads very difficult. This could allow a malicious SCP server to add a local user, overwrite allowed SSH keys, or truncate log files, depending on what the user specified as the target directory.
Sintonen’s first piece of advice regarding mitigation of these vulnerabilities for OpenSSH
In 2020 a security researcher named Chinmay Pandya discovered an interesting bug: passing a specifically crafted payload as the target file or directory to OpenSSH
scp will result in command execution. For example, the following
scp command will copy
/destination, but will also execute
echo Hello from scp:
This is not as terrible a vulnerability as it may seem at first blush, as the ability to use SCP necessitates the ability to log onto a machine with SSH. If you can do that, executing arbitrary commands is as simple as creating an SSH session. Some people configure OpenSSH to only allow execution of
scp in an attempt to restrict users to only copying files. This is indeed a vulnerability in that case, as a user could easily bypass this restriction and execute whatever they want.
This vulnerability put OpenSSH in a tough spot; ideally they would patch this vulnerability, as security is of upmost importance to them. But they also didn’t want to potentially break the way existing users use
scp, as some have come to rely on this specific behavior. Their response was:
The scp command is a historical protocol (called rcp) which relies upon that style of argument passing and encounters expansion problems. It has proven very difficult to add "security" to the scp model. All attempts to "detect" and "prevent" anomalous argument transfers stand a great chance of breaking existing workflows. Yes, we recognize it the situation sucks. But we don't want to break the easy patterns people use scp for, until there is a commonplace replacement.
Before we continue I’d like to clear up any potential confusion with the name of SSH File Transfer Protocol (SFTP). It would make logical sense that SFTP is just a more secure File Transfer Protocol (FTP), though that is incorrect. SFTP and FTP are not at all related. Some confuse SFTP with the Simple File Transfer Protocol due to the acronyms being the same. However, Simple File Transfer Protocol is unrelated to SFTP. It is an abandoned protocol that never gained widespread adoption. SFTP is a unique protocol that is not tied to or built off of another protocol. Yes, SFTP has SSH in the name, but it can actually be used alongside other network protocols, such as inside a Transport Layer Security (TLS) connection.
SFTP was originally a proprietary protocol owned by SSH Communications Security, designed in 1997. Over the next few years, the Internet Engineering Task Force (IETF) would start to design SSHv2. The same group decided to start work on standardizing a more modern protocol for secure file transfer, which would become the SFTP protocol we know and love today. They never finished however, creating over a dozen successive drafts in the process, but that didn’t stop numerous projects from implementing and using SFTP anyway. OpenSSH added server-side support for SFTP in version 2.3.0, and client-side support in 2.5.0.
In 2020, an OpenSSH contributor by the name of Jakub Jelen decided to add SFTP support to the
scp command, making it easier than ever to use SFTP. After CVE-2020-15778 was reported and OpenSSH declared
scp deprecated, Jelen wanted to make it easier for users to migrate to SFTP. At the time, OpenSSH shipped with an SFTP client, but it was not very easy to use nor compatible with
scp. Jelen decided to add SFTP support to
scp, allowing users to continuing to use
scp with the same syntax they were used to while also benefitting from the security afforded by SFTP. Originally, the
-s flag optionally enabled the use of SFTP, but in OpenSSH version 9.0.0 SFTP became the default protocol.
SFTP operates using a more traditional client-server model than SCP: a client make requests and a server handles it and sends back a response. Clients connect over an existing SSH session, like SCP. Unlike SCP, SFTP isn’t limited to just file transfers. Available SFTP requests closely mirror those of typical file operations. Files and directories can be read, written to, created, deleted, have permissions changed, and more. This enables SFTP to be much more than just a file transfer protocol.
After creating a SSH session, clients then specify that they want to start a SFTP connection by making a SSH subsystem request. SSH subsystems are a way to abstract executing commands or handling protocols. If the SSH server supports the
sftp subsystem, the SSH server starts an SFTP server to handle the SFTP connection.
Clients then negotiate with the server what version of SFTP to use and what extensions to support. Clients send what version of SFTP they are using, and servers responds with what version will be used. This is either the client’s supported version or the server’s, whichever is lower. If clients support any SFTP extensions, or functionality not present in standard SFTP implementations, they will include those extension names in the version negotiation. Servers respond with any client extensions that are also supported, letting both sides know what, if any, extensions can be used.
Clients then send requests to preform file operations. Requests for standard file operations are available, as well as request types supported by available client and server extensions. Once clients are finished making requests, the SFTP connection can be terminated simply by ending the SSH session that is being used to wrap it.
Additionally, extensions can be used to provide functionality when working with remote files. Without having to change the specification of the protocol for everyone, users can develop and add extensions to support additional file operations. What’s great about SFTP extensions is that they are optional, and are only used if both the client and server both support them. This gives SFTP great flexibility and allow for clients and servers of varying age and capabilities to continue to just work.
Auditing SFTP can be very easy due to how clients have to make separate requests for every file operation they want to preform. Some SFTP server implementations emit log entries for every client request that is handled, giving administrators valuable insight into what remote file operations users are performing.
At Remoteler, we’ve added support for SFTP starting with Remoteler 11.0. As an example, lets see what SFTP requests
scp makes when using SFTP. We’ll transfer a file using
scp to a Remoteler Node and view the audit logs to see what events are generated:
We’re passing the
-s flag to force usage of SFTP, as prior to OpenSSH 9.0 SCP is still used by default. The
-p flag is passed to preserve file times and permissions. Logging into our Remoteler Cluster and viewing the audit log will reveal what SFTP requests
scp used to copy
We can verify that the attributes were indeed preserved by expanding the details of the
The access and modification times were preserved, as well as the file permissions. The original permissions of
0644, but they are shown above to be set to
420. This is because Linux file permissions are in octal (or base 8), while SFTP sends file permissions in decimal (or base 10). Converting
0644 from octal to decimal results in
420, demonstrating that file permissions were indeed preserved as well as file times.
SFTP’s more modern request-response design gives SFTP clients and servers many opportunities to vet what the other is doing is both allowed and correct. Clients and servers can more easily hold the other accountable and fail when something is wrong more easily compared to SCP. Also, no file execution is required at all which eliminates whole classes of vulnerabilities from SFTP. SFTP was designed from the ground up with security in mind, while SCP is just an insecure protocol from the ’80s given a subtle facelift.
SCP has served us well for many years, but the time has come to put it to rest. SFTP is superior in almost every way, and should be preferred to securely transfer files. With the recent changes in OpenSSH
scp, you may not even realize that SFTP is being used as a secure default without the need for any manual intervention on your part. Many IDEs such as JetBrains have also started to use SFTP as a default for file transfers, and it’s becoming more and more common to see SFTP used in place of SCP. If you’re still using SCP, it’s time to start using SFTP instead.