Enable SSH shell access but disable SFTP access

Solution 1:

As others have mentioned, disabling sftp isn't anywhere near sufficient - a user with unrestricted ssh access can view any file that their account has permissions to view, can modify anything they have permission to modify, and can easily download anything they can read to their own machine. The only way to stop them from doing this is to actually restrict their access. It's also not ideal to rely on .profile to restrict users, as that's not what it's for (Edit: As Aleksi mentions in his answer, it is in fact trivial to bypass .profile; the thing about .profile is that it's for convenience, not security, so it's not intended to restrict the user. Use things designed for security, like the things below, to provide security).

There are two basic ways to do this: you could restrict them via file permissions, or force them to only execute your console app. The second way is better: Assign users who should be restricted to the console app to a group (e.g. customers); then, in sshd_config, add the following lines:

Match Group customers
ForceCommand /path/to/app

What this does is make it so that all connections from users in that group open the console app; they cannot start anything else, including the sftp server tool. This also stops them from doing anything else with the system, and unlike .profile, does so using the SSH server itself (.profile restricts them at the shell, ForceCommand also prevents doing other things that don't involve starting a shell). Also unlike .profile, this is designed as a security thing; it is specifically made to resist a malicious user evading it.

The (probably inferior) alternative would involve creating a new user to run the console app. You would then restrict the data directories to that user, set the console app owned by that user, and set u+s on the program. This is the setuid bit; it means that someone who runs the console program does so with the permissions of the program's owner. That way, the user does not themselves have access to the directories, they only get it through the program. However, you should probably just use ForceCommand, as that restricts all access to "just run this program".

Solution 2:

Edit:

In case it's not obvious, the following answer isn't intended as a secure method of preventing SFTP from being used by anyone with shell access to the server. It's just an answer that explains how to disable it from external visibility. For a discussion about user level security, see answers from @cpast and @Aleksi Torhamo. If security is your focus, this answer is not the proper one. If simple service visibiliy is your focus, then this is your answer.

We now continue to the original answer:


Comment out sftp support in sshd_config (and of course restart sshd):

#Subsystem sftp /usr/lib/openssh/sftp-server


Solution 3:

Do not attempt to do this with .profile because it provides no security whatsoever and restricts exactly nothing!

It doesn't matter what you put in .profile, since you can bypass it by simply giving a command to run on the ssh command line, like this: ssh user@host command. You can still get normal shell access by doing ssh -t user@host bash.

Disabling the sftp subsystem, like mentioned in another answer, doesn't help at all. Subsystems are essentially just aliases to commands, and you can still use sftp normally by doing sftp -s /path/to/sftp-executable user@host.

Like cpast and some commenters have said, you should use the proper mechanisms for restricting access. That is,

  • Use ForceCommand in sshd_config
  • Use passwordless login and command="..." in .ssh/authorized_keys
  • Change the user's shell to something that restricts what the user can do

Notes:

  • command="..." only applies for one key, so it doesn't restrict ssh login for the user using a password or another key
  • You might also want to restrict port forwarding etc. (port forwarding, x11 forwarding, agent forwarding and pty allocation are the ones I've heard about)
    • AllowTcpForwarding etc. in sshd_config
    • no-port-forwarding etc. in .ssh/authorized_keys
  • If you have other daemons (like FTP) running, you should verify that they don't let the user in (Some daemons make this decision based on the user's shell, so if you change that, you might want to re-check this)
  • You can change the user's shell to a script that does what you want; it's either run without arguments or like script -c 'command-the-user-wanted-to-run'
  • Both ForceCommand and command="..." run the command through the user's shell, so they don't work if the user's shell is set to eg. /bin/false or /sbin/nologin

Disclaimer: I'm no expert on the matter by any means, so while I can say that the .profile thing isn't safe, I can't promise there isn't some "gotcha" with the other methods that I don't know about. They're safe as far as I know, but I wouldn't be the first person to be wrong on the internet.