SFTP Chroot Jail in CentOS Linux

Introduction

Secure FTP uses openssh and was engineered by the IETF between 2001 and 2007. It has the potential to replace the insecure and older File Transfer Protocol (FTP). Another alternative to FTP and SFTP is WebDAV, which uses HTTP/TCP pipelining technology and hence does considerably speed up file transfers. However if you wanted WebDAV to be secure you would have to go through the hassles of creating a working SSL connection. This article will focus on implementing a SFTP Chroot Jail for SFTP usage. It has been last updated in October 2013 to incorporate some of the suggestions by the readers in the comments.

SFTP should work out of the box if SSH is already running on your server. Just connect from your client machine with

sftp user@hostname.tld

The SFTP connection itself is getting tunneled over SSH. However the user you are using to log in will have access to your entire root file system as well as being able to login via SSH and administer a whole different kind of damage if he wanted to. So what we want to achieve is to not only prohibit the user from using SSH to login, we also want to restrict him or her from having access to certain areas of our file system. We will jail him to his home directory or to a particular Web site directory. In order to jail the user, we will have to chroot him, which means as much as changing his root.

Installation of OpenSSH 5.6

To achieve a simple chroot jail, software-wise you need openSSH 5 or greater.

At the time of this blog post (Nov 2010), CentOS 5.5 still shipped with the one-year old openSSH 4.6. In order to get openSSH 5 on oour system, we best compile a RPM package from the latest openSSH 5.6 sources and install it on CentOS. This is how you can achieve that:

## Command line Fu explained First the yum package manager installs the **GNU compiler** together with important tools like `make`. Then yum installs the **openssl** development packages and **rpm-build**. Then you should choose a **repository location**; we chose the RWTH Aachen. You also fetch the **GPG signature** and import it to your local gpg databse in order to verify the package. The rest comes down to **building** the **rpm package**; without GUI support like X11 or GNOME, since a graphical user interface isn't usually needed on a server. 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` *(use backticks around uname -i)*. The latter changes directory to the correct build version of your kernel. I must credit some of these steps to BinBlog. ## Verify Installation We better check if it worked: `rpm -qa | grep ssh` .. which should print out: `openssh-clients-5.6p1-1`
`openssh-5.6p1-1`
`openssh-server-5.6p1-1`
These have been the pre-requisites for installing a chroot jail with SFTP. In the following section we will have a loot at how to configure SFTP users and prepare your directory structure. # Structure of SFTP Chroot ## Creating Groups First, we setup two new groups on your Linux system. `fullssh` and `sftponly`. The group `fullssh` is going to have full access to the Linux filesystem, as its name gives away. Just add your main user to the `fullssh` supplementary group. The other group called `sftponly` is designed for the **SFTP user**, let's call him *pete*. Pete is going to be jailed to a particular directory and will also be restricted from using SSH. `groupadd sftponly`
`useradd pete`
`usermod -aG sftponly pete`
In above snippet you could also omit the `-a` switch, which I put there to ensure our user is **appended** to a supplementary/secondary group instead of having the user or the group get created from scratch. You can **verify** that permissions are setup accordingly by issuing a `groups pete`. ## Configure sshd_config Now edit the file `/etc/ssh/sshd_config`. Comment out the default entry for the SFTP service and set up the **chroot directory** of choice. In this example I used /var/www/html, the root of Web sites on most servers. In this context it would be great to re-read your ssh config file without restarting the whole server or you will be kicked out of the running session. A typical `HUPKILL` won't do the trick. You have to find out the Process ID (PID) of your **root sshd dameon process** with `ps aux | grep sshd` and then re-read sshd_config accordingly with `kill -HUP 1234`, where 1234 is the PID of the root process. ## Directory Structure and Permissions We now proceed to setup the directories and the permissions of the directory structure. This has to be done with great care. `mkdir -p /var/www/html/petes-website`
`chmod 755 /var/www/html/petes-website`
`chown root:sftponly /var/www/html/petes-website`
`chown -R pete:sftponly /var/www/html/petes-website` First, you create the directory `petes-website` with the `-p` switch. The switch will take care of creating all necessary parent folders, just in case you don't have a `/var/www/html` directory already.

Then you set the directory permission bits to 755. Why not set permissions of the chroot directory to the safer 750 bits? While this might provide better security in most Web server scenarios, this locked my Web server out from accessing the directory and when I tried to access my Web site through a Browser it produced a HTTP 403 Forbidden status code.

With the first of the two chown lines above you change the owners of the directory /var/www/html/petes-website to root user-wise and to sftponly group-wise. We made the user pete a member of the sftponly group earlier. The second chown line gives ownership recursively to all files in the directory petes-website to the user pete.

Verify Setup

The permissions have to be setup in the following manner to make the SFTP login chain work:

$ls -lishad /var/www/html/petes-website
drwxr-xr-x 3 root sftponly 4.0K Nov 9 /var/www/html

$ls -lisha /var/www/html/petes-website
drwxr-xr-x 8 pete sftponly 12.4K Nov 9 /var/www/html/petes-website/index.html
drwxr-xr-x 8 pete sftponly 25.0K Nov 9 /var/www/html/petes-website/about-pete.html
drwxr-xr-x 8 pete sftponly 15.1K Nov 9 /var/www/html/petes-website/contact.html

Now if you login via SFTP with the user pete, SSH will handle the login process until the user pete is authenticated. The user is then jail rooted to the petes-website directory from above example.

When the user pete tries to login to your server via SSH the ForceCommand internal-sftp directive inside sshd_config will restrict pete from login via SSH and you should see:

ssh pete@petes-website.org
This service allows sftp connections only.
Connection to petes-website.org closed.

Full Chroot

Consequently, ommiting the ForceCommand internal-sftp directive in the sshd_config file will allow members of the sftponly group to access your system via SSH. You will have to setup at least a rudimentary chroot environment by providing necessary programs and libraries like bash, to name the most important one. This is described at HowtoForge.

By using the internal-sftp directive we made sure that we don't need a fully chroot environment with scripted access to tools or symlinks - therefore it should be rather difficult for an attacker to escape the jail. However you should be aware that there exists a chroot exploit since 1999. That is why the Solaris and Linux community stopped to consider a chroot jail being completely secure approach. However it is possible to harden a shell chroot environment.

I hope you enjoyed this article. I would appreciate your thoughts on the topic of server security in the comments or a blacklink from your blog or forum.

comments powered by Disqus