Wednesday, May 26, 2010

Setup of a chroot'd SFTP only server

The SSH File Transfer Protocol or SFTP is a network protocol providing file transfer and manipulation functionality over a reliable, encrypted data stream using SSH version 2. A common misconception is SFTP is simply FTP run over SSH; the truth is SFTP is a new independent protocol designed from the ground up by the IETF SECSH working group and thusly not compatible with ftp. SFTP server and its support tools are built into OpenSSH by default.
Purpose:
provide SFTP only access to users (no ssh or scp) restrict users to their home dir (chroot) no libraries or other server support files in users' home dir allow file upload and download access no executable interactive shell access keep maintenance to a minimum when upgrading OpenSSH


The easy way and the hard way

Depending on the version of OpenSSH you have installed depends on how much work you need to do to get a secure sftp server setup.
  • Use option one(1) if you have OpenBSD v4.3 (OpenBSD v4.2 -current or later). With the latest version of OpenSSH you can setup the sftp server using the ChrootDirectory command in the sshd_config file.
  • If you are using a version before the patches to OpenSSH in OpenBSD 4.2 -current then you need to following the instructions in option two(2).


Need help setting up a fast and secure OpenSSH server or assistance with the ssh client? Check out our OpenSSH configuration "how to".




OPTION 1: Install OpenBSD v4.3 (OpenBSD v4.2 -current) or higher with ChrootDirectory

First, make sure you have the ChrootDirectory option in the man page of the openssh server you are going to use. If the option is not available then you need to update your version of openssh. If you are using OpenBSD 4.2 -stable you can always download the -current CVS source tree and build openssh from there. If you need assistance setting up the cvs tree take a look at Patching OpenBSD kernel and packages "how to".
Next, add the following lines to your sshd_config file. The "recommended directives" are just good security items you may want to use. The "sftp directives" are what is needed to get the sftp server working.
The new Subsystem called "internal-sftp" was specifically made by the OpenBSD group for the purpose of chrooting sftp users. The next option will "Match" the user we will call "ftp" to be forced into the chroot at login. The order of loading the Subsystem before the ForceCommand is critical. If you reverse the order you will get errors when sshd tries to start and it will die.
##### cat /etc/ssh/sshd_config
 
## optional, but recommended directives
AllowTcpForwarding no
ClientAliveCountMax 3
ClientAliveInterval 0
Compression delayed
LoginGraceTime 60s
LogLevel DEBUG3
MaxAuthTries 6
PasswordAuthentication yes
PermitEmptyPasswords no
PermitRootLogin no
PermitTunnel no
PermitUserEnvironment no
Port 22
Protocol 2
StrictModes yes
SyslogFacility AUTH
TCPKeepAlive yes
UseDNS no
UsePrivilegeSeparation yes
X11Forwarding no

## sftp directives
# override default of no subsystems
#Subsystem      sftp    /usr/libexec/sftp-server
Subsystem       sftp    internal-sftp

Match User ftp
    ForceCommand internal-sftp
    ChrootDirectory /ftp_jail
NOTE: If you are going to allow sftp _only_ logins for the user then they DO NOT need a shell. You can add the user and set the shell as /sbin/nologin. When the user logs in with sftp their shell will be internal-sftp as set by sshd.
Next, you need to setup the directory where the user "ftp" will be chrooted. For simplicity we are going to make the directory called "/ftp_jail". For the internal-sftp server to allow logins, the directory permissions must be setup correctly. If not, the sshd server will start, but the "ftp" user will not be allowed to log in.
Make the "/ftp_jail" directory. Set the ownership as "chown root:ftp /ftp_jail" and "chmod 750 /ftp_jail". The directory will look like this:
drwxr-x--- root ftp 1000 Jan  1 10:10 /ftp_jail
This will make a read-only, chrooted directory perfect for people to come in and get stuff, but never write. By changing the permissions on the directory you can change the level of access you give to the "ftp" user. For example, you could make a directory /ftp_jail/uploads that allow people to write in. Then you can moderate what gets copied into the read-only /ftp_jail area. Remember that if a user can write in a directory then they can also delete anything in that directory.
Thats it. All done. If you have any questions please scroll to the bottom of this page.


Want more speed? Make sure to also check out the Network Speed and Performance Guide. With a little time and understanding you could easily double your firewall's throughput.






OPTION 2: Install OpenBSD 4.2 or earlier with mount options on the sftp partition

Environment:
OpenBSD v4.2 with OpenSSH v4.7
What needs to be done:
build and install openssh after applying the sftp-server patch build and install the sftpsh shell apply changes to chroot'd, sftp only users
As an added layer of security one can make a partition limiting user options. OpenBSD supplies mount options denying device files, suid calls, and execution of files with the exec bit set on a partition. Apply the following mount options "rw,nodev,nosuid,noexec,softdep" to the partition the chroot'd user's home directory will exist. Edit the /etc/fstab file and add the options to the partition sftp will chroot on. For example:
# cat /etc/fstab | grep chroot
  /dev/wd0c /chroot_dir ffs rw,nodev,nosuid,noexec,softdep 1 2


Step 2: getting the OpenSSH source files
Make the directory tree /usr/src/usr.bin/ and change to that directory. Download the latest openssh source tar file from OpenBSD and untar it. Change directory in to the ssh directory.
mkdir /usr/src/usr.bin/
  cd /usr/src/usr.bin/
  wget ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/openssh-4.6.tar.gz
  tar zxvf openssh-4.6.tar.gz
  cd ssh


Step 3: patch OpenSSH source with the sftp-server chroot patch
The only change to the openssh source is additional code to the sftp-server.c file making upgrades to OpenSSH in the future a simple task. The code will look for the string "/./" in the home directory path of the user in /etc/passwd. If the string is found the user will be chroot'd to their home directory. The following file is the patched version of the sftp-server.c file. If you have openssh v4.5 or v4.6 you can simply drop this in the source directory "/usr/src/usr.bin/ssh/" replacing the original sftp_server.c file. You can also download the patched sftp_server.c file and diff it against your own downloaded version. This way you can look at the proposed changes.
Download the patched file:sftp-server.c


Step 4: build and install OpenSSH
Before building you _may_ want to change the version variable reported by the server to the client. There is no reason the client needs to know what version of openssh we are running. To edit the publicly reported version open the version.h file and change the SSH_VERSION string.
#define SSH_VERSION     "OpenSSH_4.6" 
                 ...changed to something different...
  #define SSH_VERSION     "OpenSSH_calomel.org"
To build openssh change to /usr/src/usr.bin/ssh/ directory and execute the following to make openssh and install the binaries:
make clean && make obj && make cleandir && make depend && make && make install
Changing the version variable is optional, but highly recommended. When your machine is scanned the first piece of information a bot looks for is the version number of he ssh server. Do not give out any information that the client does not explicitly need. The ssh server and client will negotiate fine without the version number.


Step 5: suid the sftp-server
The user is going to be chroot'd into their home directory so we need to execute the sftp-server suid. Once the sftp-server is executed the binary will drop privileges to the chroot'd user. If the sftp-server process is ever compromised, permissions no higher than the chroot'd user could be obtained.
chmod +s /usr/libexec/sftp-server


Step 6: build and install the sftpsh shell
The sftpsh shell is the wrapper we will use to deny all connections other than sftp. Sftpsh is the shell the chroot'd user will use when they log in.
Download shell wrapper file: sftpsh.c
Edit sftpsh.c and take a look at the variables at the top of the script. Make sure you set SFTP_BINARY to the proper path where sftp-server is found. Also, you may want to edit the DENY_MESG to something more appropriate for your system. This is the message a remote user will see upon a failed login with ssh or scp.
Build and install sftpsh:  gcc sftpsh.c -o sftpsh;cp sftpsh /bin/sftpsh
Once sftpsh is built and installed add /bin/sftpsh to /etc/shells so you can easily apply it to your users.


Step 7: setup the "sftp only" users
To restrict a user to a the chroot'd sftp only server simply add "/./" to the end of their home directory path and change their shell to /bin/sftpsh. For example our "test" user's home directory and shell are the following according to /etc/passwd:
test:*:1001:1001:sftp test,,,:/chroot/test/./:/bin/sftpsh


Step 8: testing the server
The openssh server has been patched and the sftpsh shell has been installed. Check the sshd_config file and make sure the line with sftp-server is uncommented. Make sure to shut down sshd and restart it. Sftp to the server with the user name and password of the user you have chroot'd in /etc/passwd.
sftp user@machine
You should be able to log in without issue. Now, try to change directory up and out of the home directory. This should fail as the home directory is the chroot'd environment. You can type "?" in the cli to see what commands are allowed. Take a moment to familiarize yourself with what a user can do in the environment. Make sure you know what commands are allowed through the sftp client and whether they will cause your environment any issues. Users can be amazingly destructive even with their own files.
Now try to ssh to the machine and scp a file to/from the machine.
ssh user@machine
     and
  scp local_testfile user@machine:.
Both ssh and scp should fail and the DENY_MESG string you set in sftpsh should have been displayed and your client immediately disconnected.


Conclusions

We have built a secure, encrypted file server allowing a user to send and receive files through sftp only. Ssh and scp are denied to only chroot'd users. The server will not allow the execution of programs or running of any system binaries by the client. As an added bonus we have removed all of the active/passive port problems associated with standard ftp and ftp though ssl. Sftp will run through firewalls, uses a fully stateful connection scheme and works over most questionably setup networks.
There are many programs that will allow your users to access the sftp server. OpenSSH by the OpenBSD group supplies a CLI sftp client by default. Windows users can use the graphical WinSCP, SshSecureShell or BitKinex or check on ssh.com for example. MacOSX users can use the openssh cli or a graphical GUI called "Fugu" which works quit well.
Users wanting to use scripts with sftp should have no problems. For a password less environment they will need the use of ssh-keys. For added security it is suggested that you limit the connection rate of ssh users. With pf you can easily limit the connections to 5 connections per 30 seconds for example. You can also add an abusive user to a 000033list automatically with the same stateful tracking options. Check on the main page of calomel.org for pf.conf examples and instructions.

No comments: