In what way isn't SFTP based on SSH?
On bash in general
Bash's design with respect to startup files is rather peculiar. Bash loads .bashrc
in two unrelated circumstances:
- When it's an interactive shell, except when it's a login shell (and except when it's invoked as
sh
). This is why.bash_profile
typically loads.bashrc
. When bash is not interactive nor a login shell nor invoked as
sh
but given a command to execute with-c
andSHLVL
is unset or less or equal to 1, and one of the following is true:- If standard input is a socket. In practice, this mostly happens when bash is invoked by
rshd
, i.e. when runningrsh remotehost.example.com somecommand
. If activated at compile time (which is the case on some distributions, such as Debian and derivatives), if one of the environment variables
SSH_CLIENT
orSSH2_CLIENT
is defined. In practice, this means that bash is invoked bysshd
, i.e.ssh remotehost.example.com somecommand
.
If you don't know how bash was compiled, you can find out whether this option was set by checking whether the binary contains the stringSSH_CLIENT
:strings /bin/bash | grep SSH_CLIENT
- If standard input is a socket. In practice, this mostly happens when bash is invoked by
On SSH in general
When you execute a command through the SSH protocol, the command is passed over the wire as a string. The string is executed by the remote shell. When you run ssh example.com somecommand
, if the remote user's login shell is /bin/bash
, the SSH server runs /bin/bash -c somecommand
. There is no way to bypass the login shell. This permits restricted login shells, for example to allow only file copying and not general command execution.
There is one exception: the SSH protocol allows the client to request a specific subsystem. If the client requests the sftp
subsystem, then by default the OpenSSH server invokes the program /usr/lib/openssh/sftp-server
(the location may vary) via the user's login shell. But it can also be configured to run an internal SFTP server through the line
Subsystem sftp internal-sftp
in the sshd_config
file. In the case of the internal SFTP server, and only in this case, the user's login shell is bypassed.
For this challenge
In the case of OverTheWire Bandit 18, .bashrc
contains
…
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
…
echo 'Byebye !'
exit 0
So you can solve this level by doing anything that causes bash not to be interactive.
As you discovered, SFTP works.
Butssh [email protected] cat readme
would also work.
As wouldecho 'cat readme' | ssh [email protected]
.
And pressing Ctrl+C at the right time during an interactive login would also work: it would interrupt bash, so the.bashrc
would not be completely executed. Bash takes macroscopic time to start up, so while this doesn't work reliably, it can be done in practice.
The .bashrc
is only executed when you start a shell.
The SSH server can be configured not to start a shell for the SFTP protocol by providing the command Subsystem internal-sftp
in the server's sshd_config
file.
Conjecture: it's likely that this is how the OverTheWire Bandit wargame is actually configured rather than an adjustment to .bashrc
because otherwise the same restriction for ssh
would also block the sftp
server command.
sftp uses the same credentials, but does not run an interactive shell on the remote machine.
An administrator can prevent an sftp user from running ssh, e.g., as described in How to restrict users to SFTP only instead of SSH