Chapter 9. DefaultRoot and other issues

Table of Contents
Locking users into a directory (chroot)
Finer grained control
Symlinks and chroot()

Locking users into a directory (chroot)

Preventing users from moving round the filesystem is a must for many system admistrators. Proftpd achieves this functionality using the chroot() system call. This call moves the system root directory to the specified location. Anonymous connections do this by default setting the chroot() to the directory specified in the <Anonymous> directive. For more normal users the DefaultRoot directive is required

For general open access you can use an <Anonymous> directive context block, possibly in combination with a UserPassword/AnonRequirePassword directive.

However if you wish to jail an entire group (or groups) of users, you can use the DefaultRoot directive. DefaultRoot lets you specify a root jailed directory (or '~' for the user's home directory), and an optional group-expression argument which can be used to control which groups of users the jail will be applied to. For example:

Example 9-1. Simple DefaultRoot setup

# A simple DefaultRoot setup
# limiting all users to their $HOME
DefaultRoot ~

In this example, all users who are members of group 'users', but not members of group "staff" are jailed into /u2/public. If a user does not meet the group-expression requirements, they login as per normal (not jailed, default directory is their home). You can use multiple DefaultRoot directives to create multiple jails inside the same directive context. If two DefaultRoot directives apply to the same user, ProFTPD arbitrarily chooses one (based on how the configuration file was parsed).

The chroot() system call simply moves the root (or "/") directory to a specified point within the filesystem. When implemented properly this has the effect of jailing a user into a particular branch of the filesystem directory structure. The security advantages of this approach are easily seen and it is a common method used by programmers and system administrators worldwide to enhance their local security models.

Security Implications

This approach should not be considered a high security model it has a number of flaws, not least of which is that chroot jails can be broken out of. Breaking a chroot is not a trivial task but it's nowhere near to being impossible and a competant cracker should be able to breach the security offered by chroot. This said it is still a valuable tool in the armoury of the admin.

The DefaultRoot directive is implemented using the chroot(2) system call. This moves the "/" (or root) directory to a specified point within the file system and jails the user into this sub-tree. However this is not the holy grail of security, a chroot jail can be broken, it is not a trivial matter but it's nowhere near impossible. DefaultRoot should be used as part of a general system of security not the only security measure.

A more detailed discussion on this subject and on the breaking of chroot jails has been written by Simon Burr (

This prevention method was developed by Carole Fennelly and her partner. Have a look at the August 1999 Security column of SunWorld Online for the article - see

It's worth noting that almost all FTP servers retain root privileges throughout their life, though they may revert to lower levels where possible. This is because the daemon needs to keep its root privs around when a user is logged in for things like opening sockets on ports less than 1024.

Non-root server issues

The chroot() system call will not work under a non-root ftp server process, the call requires root privileges. Without them it simply doesn't work, there doesn't appear to be any checking in the code of the uid/gid before calling chroot so using DefaultRoot in such a setup will cause the server to fail.

Required files

Some OSs require files to always exist in an environment for certain things to work. For example you need the following files available for chroot()ed work under Solaris 2.5.1:


So to actually make Proftpd work in a chrooted environment it may be necessary to create $HOME/etc/ $HOME/dev/ and similar directories and create certain files. While files are required will vary from system to system and are generally outside the scope of this guide


For systems which require the svc.conf file, tyically Digital Unix systems, it is essential that a copy of this file is placed within the chroot ($HOME/etc/svc.conf) or all attempts to authenticate will fail with error messages similar to those below.

331 Password required for test.
230 User test logged in.
ftp> dir
200 PORT command successful.
getsvc: stat of /etc/svc.conf failed
ftp> pwd
getsvc: stat failed: No such file or direc
getsvc: stat of /etc/svc.conf failed
getsvc: stat failed: No such file or direc
150 Opening ASCII mode data connection for
ftp> pwd
226 Transfer complete.
257 "/" is current directory.
ftp> dir
200 PORT command successful.
getsvc: stat of /etc/svc.conf failed

Example 9-2. Sample svc.conf file

# WARNING: This file is MANDATORY !
# Setup recommendation: As you add distributed services to database
#       entries, it is recommended that "local" is the first service.
#       For example:
#                       passwd=local,yp
# Note: White space allowed only after commas or newlines.
# File Format
# -----------
# database=service,service
# The database can be:
#       aliases
#       group
#       hosts
#       netgroup
#       networks
#       passwd
#       protocols
#       rpc
#       services
# The service can be:
#       local
#       yp
#       bind (hosts ONLY)
SECLEVEL=BSD   # for backwards compatibility ONLY