SFTP with chroot jail on CentOS
Posted by Stephan Kristyn on November 10th, 2010 / 23 Comments
SFTP which uses openssh was engineered by the IETF 2001-2007. It has the potential to replace the insecure and legacy FTP. Another alternative would be WebDAV. It seems like a great alternative to SFTP since it uses HTTP/TCP pipelining and should considerably speed up file transfers. However if you want WebDAV to be secure you would have go through the pain of creating a valid SSL connection.
SFTP should work out of the box if ssh is running on your server. Just connect from your client machine with
sftp [email protected]
The connection itself is tunneled over SSH now. However the user will have access to your entire file system and even worse if anyone gained these credentials, he could login via ssh to your server.
Since we don’t want that, we will have to chroot (jail root) the sftp user and forbid him to use ssh itself. For this you will need openSSH 5 or greater. At the time of this blog post, CentOS 5.5 still ships with the year old openSSH 4.6. Therefore we will have to make a rpm package with the latest openSSH 5.6 sources and install it on our CentOS.
rpm -qa | grep ssh yum -y install gcc automake autoconf libtool make openssl-devel pam-devel rpm-build wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz.asc wget -O- http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/DJM-GPG-KEY.asc | gpg --import gpg openssh-5.6p1.tar.gz.asc tar zxvf openssh-5.6p1.tar.gz cp openssh-5.6p1/contrib/redhat/openssh.spec /usr/src/redhat/SPECS/ cp openssh-5.6p1.tar.gz /usr/src/redhat/SOURCES/ cd /usr/src/redhat/SPECS/ perl -i.bak -pe 's/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/' openssh.spec rpmbuild -bb openssh.spec cd /usr/src/redhat/RPMS/`uname -i` uname -i ls -l rpm -Uvh openssh*rpm /etc/init.d/sshd restart
Alright what does all this command lines do? First yum installs the gnu compiler with important tools like make, then yum installs openssl development packages and rpm-build. Then I choose a repository from Aachen, Germany, which is nearest from my server’s location. We also get the gpg signature and import it to our local gpg databse then we check it. The rest is building the rpm package; without GUI support like X11 or gnome, because it’s not really usable on a server. I must credit some of these steps to someone else on the interwebs: http://binblog.info/2009/02/27/packaging-openssh-on-centos/
I found perl -i.bak -pe ‘s/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/’ openssh.spec to be very elegant and I liked also cd /usr/src/redhat/RPMS/`uname -i` very cool. The latter changes directory to the correct build version of your kernel.
Did I mention you should be root to do this?
I do it in one go, absolute hardcore.
rpm -qa | grep ssh && yum -y install gcc automake autoconf libtool make openssl-devel pam-devel rpm-build && wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz && wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz.asc && wget -O- http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/DJM-GPG-KEY.asc | gpg --import && gpg openssh-5.6p1.tar.gz.asc && tar zxvf openssh-5.6p1.tar.gz && cp openssh-5.6p1/contrib/redhat/openssh.spec /usr/src/redhat/SPECS/ && cp openssh-5.6p1.tar.gz /usr/src/redhat/SOURCES/ && cd /usr/src/redhat/SPECS/ && perl -i.bak -pe 's/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/' openssh.spec && rpmbuild -bb openssh.spec && cd /usr/src/redhat/RPMS/`uname -i` && uname -i && ls -l && rpm -Uvh openssh*rpm
Better check if it worked.
rpm -qa | grep ssh openssh-clients-5.6p1-1 openssh-5.6p1-1 openssh-server-5.6p1-1
This were the pre-requisites for using chroot with SFTP. I will show how to setup SFTP and prepare your directory structure.
First, setup two new groups. One group fullssh is going to have full access to the Linux filesystem. Just add your main user to the fullssh supplementary group. The other group is called sftponly for our SFTP users that will be jailed to a particular directory.
groupadd sftponly useradd pete usermod -aG sftponly pete
In above snippet one could also use useradd -G sftponly pete, but in case the user pete exists already the -a switch ensures he is added to the supplemental group sftponly instead of deleting existing supplemental groups.
Now go into /etc/ssh/sshd_config and comment out the default entry for the sftp service.
#Subsystem sftp /usr/lib64/misc/sftp-server Subsystem sftp internal-sftp AllowGroups fullssh sftponly Match Group sftponly ChrootDirectory /var/www/html ForceCommand internal-sftp X11Forwarding no AllowTcpForwarding no
Now let’s set permissions on the directory structure. This has to be done with great care.
chown root:sftponly /var/www/html chmod 755 /var/www/html mkdir -p /var/www/html/yourDomain chown pete:sftponly /var/www/html/yourDomain
Some tutorials on the web suggest setting permissions to 750, but as it turns out this will lock out apache and produces a HTTP 403 Forbidden when accessing your website. We don’t want that.
With chown you change the owners of the directory to root user-wise and to sftponly group-wise. The user pete should be a member of that group by now. You can check that with groups pete.
Creating the directory with the -p shouldn’t be necessary in above example, but I included it nonetheless. The switch would take care of creating all necessary parent folders.
This is how the permissions must look like in order to make the ssh / sftp login chain to work.
ls -lishad /var/www/html inode 4.0K drwxr-xr-x 3 root sftponly 4.0K Nov 9 10:27 /var/www/html ls -lishad /var/www/html/yourDomain inode 4.0K drwxr-xr-x 8 joe sftponly 4.0K Nov 9 11:33 /var/www/html/yourDomain
Now if you login, ssh has root permissions and handles the login process until the user pete is authenticated. The user is then jail chrooted to the yourDomain directory, at least in my understanding. With SFTP we don’t need a proper chroot environment with access to /dev or any hardlinks – therefore it should be rather difficult for an attacker to escape the jail. There exists an exploit  since 1999. That is why Solaris and Linux stopped to consider chroot a secure solution. However it is possible to harden  a shell chroot environment.
I hope you enjoyed this article. I would appreciate any thoughts on the topic of server security in the comments below.
 chroot HowTo