78

Is there any way to configure a user on a Linux box (Centos 5.2 in this case) so that they can use scp to retrieve files, but can't actually login to the server using SSH?

1
  • I tried setting the login shell to /bin/false, but that just stops scp working altogether.
    – DrStalker
    Nov 12, 2009 at 2:55

11 Answers 11

48

DEPRECATED: Please note the following answer is out of date. rssh is no longer maintained and is no longer a secure method.

rssh shell (http://pizzashack.org/rssh/) is designed for precisely this purpose.

Since RHEL/CentOS 5.2 doesn't include a package for rssh, you might look here to obtain an RPM: http://dag.wieers.com/rpm/packages/rssh/

To use it just set it as a shell for a new user like this:

useradd -m -d /home/scpuser1 -s /usr/bin/rssh scpuser1
passwd scpuser1

..or change the shell for an existing one like this:

chsh -s /usr/bin/rssh scpuser1

..and edit /etc/rssh.conf to configure rssh shell - especially uncomment allowscp line to enable SCP access for all rssh users.

(You may also want to use chroot to keep the users contained in their homes but that's another story.)

5
  • that's awesome - I've been looking for something like this for a while, too
    – warren
    Nov 12, 2009 at 4:44
  • 6
    the idea behind rssh is nice, but iirc rssh wasn't exactly a miracle of security in programming terms. A simple google on 'rssh exploit' yields more results than I am comfortable with...
    – wzzrd
    Nov 12, 2009 at 7:48
  • 7
    scponly is more or less the same thing as well and apparently less exploits-prone : sublimation.org/scponly/wiki/index.php/Main_Page Nov 12, 2009 at 10:52
  • scponly appears to have moved to github. The sublimation link is dead. github.com/scponly/scponly/wiki
    – spazm
    Sep 13, 2013 at 22:04
  • 3
    This answer should be removed! It's really dated and may confuse people - scponly, rssh and similar tools are all dead and removed from all OS repos many years ago. rssh has unpatched vulnerability known for years.
    – ruruskyi
    Nov 19, 2020 at 13:26
44

I'm way late to this but you could use ssh keys and specify the exact command allowed in their ~/.ssh/authorized_keys file e.g.

no-port-forwarding,no-pty,command="scp source target" ssh-dss ...

You may need to use ps to on the target to set the right command settings.

PS: If you run a test scp command with "-v" you can see something like this

debug1: Sending command: scp -v -t myfile.txt

You will note that "-t" is an undocumented scp option, used by the program on the far end. This gives you the idea of what you need to put into authorized_keys.

EDIT: You can find more information (with several links) in this StackOverflow question.

Here is a working example of this, for a user named backup_user on the server side.

~backup_user/.ssh/authorized_keys content on server side (with some more security restrictions):

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="scp -v -r -d -t ~/CONTENT" ssh-rsa AAAAMYRSAKEY...

Create a link in ~backup_user/ that links to the directory where the content should be accessible.

$ ln -s /path/to/directory/with/accessible/content ~backup_user/CONTENT

Now, from client side, the following command should work :

scp -v  -r  -P 2222 -i .ssh/id_rsa_key_file path/to/data backup_user@SERVER:~/CONTENT

What this command do:

  • It displays verbose information (optionnal: you can remove the -v from both command and authorized_keys file)
  • It recursively copies the content of the path/to/data. (optionnal: you can remove -r from both command and authorized_keys file if you do not want to make a recursive copy)
  • It uses port 2222 to connect to the server (optionnal: you can remove -P 2222 from the command)
  • It uses and identity file to automate the connection (optionnal: you can remove -i .ssh/id_rsa_key_file
  • The content of path/to/data will be copied into /path/to/directory/with/accessible/content/

To make a copy of a file (or several) from the server to the client, you should create a shell script that handles this as described here

3
  • 1
    What's to stop the user scping over their authorized_keys file? Can it be restricted not to be owned by the user themselves?
    – Dan
    Oct 14, 2015 at 12:11
  • 3
    @Dan - It should be possible to set read-only permissions on the authorized_keys file, ie. chmod 400 ~/.ssh/authorized_keys. Oct 6, 2016 at 15:30
  • 3
    Also you should make ~/.bashrc (and whatever else Bash executes) and ~/.ssh/rc read-only. But if the malicious user has access to rsync or sftp, he can still remove ~/.bashrc, and upload a new one. Since it's hard to protect, I recommend against this method (command="...").
    – pts
    Dec 6, 2017 at 15:23
38

I'm a bit late to the party, however I will suggest you take a look at the ForceCommand directive of OpenSSH.

Subsystem sftp internal-sftp

Match group sftponly
         ForceCommand internal-sftp

Granted, this is SFTP and not SCP, but it reaches the same goal, more securely than with a restricted shell. Additionally, you can chroot the user if you want to.

3
  • 2
    add the chrootDirectory %h and AllowTcpForwarding no after the match section to force the sftponly users to chroot to their home. please note that the match should (must!) be the last section on the ssh config and options after that are options just for the matched users
    – higuita
    May 28, 2013 at 15:44
  • 4
    ForceCommand internal-sftp -u 0077 -d /uploaddir can farther harden it, by forcing a umask on an upload directory. In conjunction with 'ChrootDirectory` it creates a very controlled, isolated upload environment. Bonus note: the default dir and the umask must be set in the ForceCommand, not in the Subsystem directive, if you want them to work.
    – Marcin
    Jun 6, 2014 at 12:58
  • A longer article explaining this is avaiable at debian-administration.org/article/590/…
    – koppor
    Nov 15, 2015 at 18:56
9

I use MySecureShell to do this. You can configure other restrictions too.

https://github.com/mysecureshell/mysecureshell

Limits connections to SFTP/SCP only. No shell access.

2
8

I'd recommend using scponly.

It is a restricted shell that allows users to do just what it sounds like, SCP files to the server, but not actually log in. Information and source code downloads for the software are available here and the pre-compiled RPM packages are available via the EPEL YUM Repositories.

Once installed, you will need to configure each user account, which you wish to restrict access to, to use the newly installed restricted shell. You can do this manually via /etc/passwd or use the following command: usermod -s /usr/bin/scponly USERNAME

2
3

Very late to the party, but just set shell of the git user to be /usr/bin/git-shell. It's a restricted shell that doesn't allow interactive login. You can still su in to the user with 'su -s /bin/bash git' or whatever your git username is.

1
  • SFTP does not work with git-shell unfortunately.
    – tholu
    Aug 24, 2022 at 12:56
1

We use a psudo shell called scponly on our secure ftp servers for users we only want to be able to scp files but not log in.

1
  • For awareness, based on a comment on another answer here: scponly seems to be dead. Debian seems to have removed it. The code on Github is dead, too.
    – tanius
    Jan 27 at 19:24
1

I've found a nice way is to use the command="..." feature of the authorized_keys file. (Suggested to me by this page)

The command you'd run would be one that tests for arguments that start with scp (and rsync).

Here's the authorized_keys file:

# authorized_keys
command="/usr/local/bin/remote-cmd.sh" ssh-rsa.....== user@pewpew

Here's the contents of remote-cmd.sh:

#!/bin/bash
# /usr/local/bin/remote-cmd.sh
case $SSH_ORIGINAL_COMMAND in
 'scp'*)
    $SSH_ORIGINAL_COMMAND
    ;;
 'rsync'*)
    $SSH_ORIGINAL_COMMAND
    ;;
 *)
    echo "Access Denied"
    ;;
esac

I guess you'd probably still need to protect the user's authorized_keys file, but my purpose was to have a password-less key that I could use for backups, without having to create a whole new user, and have the key not give a shell (ok, easily)

5
  • 4
    This is pretty cool - but I imagine it can be subverted by issuing a command which does an scp, then run a script afterwards !
    – davidgo
    Oct 12, 2015 at 21:25
  • @davidgo prepending $SSH_ORIGINAL_COMMAND with exec might address that vulnerability, assuming scp and rsync don't themselves try to run multiple programs (in which case, this would break that)
    – Phil
    Apr 25, 2017 at 1:18
  • 1
    Also you should make ~/.ssh/authorized_keys, ~/.bashrc (and whatever else Bash executes) and ~/.ssh/rc read-only for the user. But if the malicious user has access to rsync or sftp, he can still remove ~/.bashrc, and upload a new one. Since it's hard to protect, I recommend against this method (command="...").
    – pts
    Dec 6, 2017 at 15:27
  • 1
    @pts you could make both the rc files, and the dirs that contain them be owned by someone other than the user (nobody?) and not writable by the user. But at this point you're better using something dedicated like rssh. Wow, I just realised this is my answer! It's old! Haha!
    – Phil
    Dec 7, 2017 at 3:05
  • 3
    Don't forget that scp -S ... and rsync -e ... lets the user execute arbitrary commands. So you should check the arguments in $SSH_ORIGINAL_COMMAND before executing it. More info here: exploit-db.com/exploits/24795
    – pts
    Dec 7, 2017 at 13:12
1

Change the login shell of the user to something restrictive, which lets the user run only scp, sftp-server and rsync only, and it also checks that unsafe arguments are not allowed (e.g. scp -S ... and rsync -e ... are unsafe, see here: http://exploit-db.com/exploits/24795). Example for such restrictive login shell:

You may want to run one of these in a chroot or in another restricted environment (e.g. nsjail on Linux), to disable network access and for easier (whitelisted) control of which directories can be read and/or written.

I don't recommend using command="..." in ~/.ssh/authorized_keys, because without careful additional protection (such as chmod -R u-w ~ for the user) a malicious user can upload a new version of ~/.ssh/authorized_keys, ~/.ssh/rc or ~/.bashrc, and thus can include and execute arbitrary commands.

0

Combining Phils script with some configuration in the SSH server seems to be having the desired effect. In our case, we have a group sftponly. As the name suggests - users in this group can only be used for file access over SSH. No user files (~/.ssh/authorized_keys or ~/.bashrc) modifications necessary.

Append this to /etc/ssh/sshd_config:

Match group sftponly
    X11Forwarding no
    AllowTcpForwarding no
    AllowAgentForwarding no
    ForceCommand /usr/local/bin/remote-file-access-only.sh

Create /usr/local/bin/remote-file-access-only.sh:

#!/bin/bash

# allow scp, sftp and rsync only
case $SSH_ORIGINAL_COMMAND in
 'scp'* | 'rsync'* | '/usr/libexec/openssh/sftp-server'*)
    $SSH_ORIGINAL_COMMAND
    ;;
 *)
    echo "Access Denied"
    ;;
esac

Restart sshd and make the script executable.

And there you go, for users in this group we can do scp, sftp and rsync but won't get a shell over SSH.

-1

Its not the most graceful solution, but you could throw something like this into the users .bashrc

if [ "$TERM"  != "dumb" ]; then
  exit
fi

I've found that SCP users get a TERM of 'dumb', and others will typically get vt100.

I imagine the user could probably scp over a new .bashrc, which makes this not the best solution, but for a quick and dirty solution, this will work

3
  • 2
    I strongly recommend against this proposed solution, it's too easy for a malicious user to circumvent (e.g. by uploading another ~/.bashrc). It's also flaky in the sense that maybe newer versions of OpenSSH would set the TERM variable differently, or some sshd config settings may affect TERM.
    – pts
    Dec 6, 2017 at 15:29
  • 3
    Ehhh... ssh -o SetEnv TERM=dumb yourserver bash ??
    – ulidtko
    Jul 2, 2019 at 18:45
  • Even just plain ssh yourserver ls -la bypasses this.
    – erco
    Oct 19, 2022 at 17:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .