File Transfer with SSH, Tee, and Base64
Computer servers deployed in a secure environment may allow SSH sessions but forbid SCP, SFTP, and execution of remote commands without a login shell. Such restricted access is typically enforced with SSH gateways and firewalls. An SSH gateway provides controlled access to the remote system. A firewall can ensure that only an SSH gateway can connect to the remote system. Thus, users can be forced to connect to the remote system only via the SSH gateway which can now control what is allowed and what isn't.
Even if SCP, SFTP, port forwarding, and remote command execution without a login shell are forbidden, as long as we get a login shell on our terminal and we can print data on the terminal, we are already able to transfer data from the remote system to our local system. The data is in the terminal. It is now only a matter of figuring out how to copy that data to a file.
Note: Various readers of this post notice that SCP or SFTP is not allowed and immediately begin suggesting me a solution similar to one of the following ones:
ssh HOST cat file > file
ssh HOST tar cf - file | tar xf -
Note that these solutions and other similar solutions are not going to work because the SSH gateway described in the previous two paragraphs forbids remote command execution without a login shell. It also blocks port forwarding, so any solution involving port forwarding is not going to work either.
Assuming that both the remote and local systems are Unix-like, the following steps show one way to accomplish copying a file from the remote system to our local system:
Connect to the remote system with
sshand pipe the output to
teeto write the entire session to a text file on the local system.
ssh HOST | tee ssh.txt
This type of pipeline works as intended even while connecting to a remote system via a jumphost or an SSH gateway.
In the remote system, create a 10 MB file to serve as an example payload to be transferred.
head -c 10485760 /dev/urandom > /tmp/payload
You probably already have a meaningful payload that you want to copy, so in that case, you would skip this step.
Compute checksum on the file. This will be used later to verify that the entire file is transferred correctly.
Print Base64 representation of the file.
Depending on the Internet bandwidth, this can take a few seconds to a few minutes to complete.
End the SSH session.
On the local system, extract the Base64 encoded payload and decode it. Assuming the shell prompt on the remote system ends with the dollar sign (i.e.,
$), the following command does this.
sed '1,/$ base64/d;/$ exit/,$d' ssh.txt | base64 --decode > payload
Extract the checksum computed on the original file.
grep -A 1 sha1sum ssh.txt
Compute checksum on the decoded payload.
Ensure that the checksum in this step matches the checksum in the previous step.
The steps above assume the use of the
sha1sum command to
compute checksum. If this command is unavailable, use
shasum, or something else that serves
this purpose well. If you are worried about collision attacks, you
-a 256, etc. instead.