chrootdaemon allows you to run a program and have it see a given
directory as the root (
/) directory. This effectively locks the process
into its very own filesystem ("chroot jail") isolated from the real
filesystem. In this article we will look at how to install the Apache Web server in such an environment.
Installing Apache in a chroot jail does not make Apache itself any more
secure. Rather, it serves to restrict the access of Apache and its child processes to a small subset of the filesystem. The advantage in chrooting a process is not in
preventing a breakin, but rather in containing a potential threat.
Before deciding whether you need to chroot your Web server you should consider
the advantages and disadvantages of such a setup.
If Apache is compromised, an intruder will have access only to the files
within the chroot jail.
Potentially dangerous CGI scripts do not have access to your server's filesystem.
Your Web tree is contained in one area that's easy to back up and move.
A chroot environment is more difficult to set up than a traditional install,
especially if you run external software such as Perl, PHP, MySQL, or Python.
The process is only viable if your entire Web tree can exist on a single filesystem.
Compiling and installing the Apache binary
There are no special steps needed to build the Apache binary in order to
install it in a chroot jail. The following steps apply equally to a precompiled binary (such as an RPM) or one you have compiled yourself. Starting with a working binary helps with debugging later, if necessary. Just make sure that you are using the latest patched version of the server, install Apache normally, and ensure that it is working as
Finally, make sure you configure Apache to run with its own user and
group IDs. Create a user and group with the commands:
# groupadd apache
# useradd -c "Apache Server" -d /dev/null -g apache -s /bin/false apache
These commands create the regular user
apache and the
apache group. Apache runs as
nobody by default. User
nobody may be used
by many processes, and if it is compromised an intruder will gain access to all
processes on your system running under that UID.
Creating the chroot tree
Our chroot jail is a mini-version of the Linux filesystem. I prefer to use a
seperate partition mounted as
/chroot, with Apache under a
httpd on my chroot partition.
# mkdir /chroot/httpd # mkdir /chroot/httpd/dev # mkdir /chroot/httpd/lib # mkdir /chroot/httpd/etc # mkdir -p /chroot/httpd/usr/sbin # mkdir /chroot/httpd/usr/lib # mkdir /chroot/httpd/usr/libexec # mkdir -p /chroot/httpd/var/run # mkdir -p /chroot/httpd/var/log/apache # mkdir -p /chroot/httpd/home/httpd
Now set the permissions on your directory structure:
# chown -R root /chroot/httpd # chmod -R 0755 /chroot/httpd # chmod 750 /chroot/httpd/var/log/apache/
Your exact structure may vary slightly depending upon what features of Apache
you are using and where the nescessary libraries live on your main file
Once you have created the nescessary directories you need to create the
# mknod /chroot/httpd/dev/null c 1 3 # chown root.sys /chroot/httpd/dev/null # chmod 666 /chroot/httpd/dev/null
You need the
null device and
/chroot/httpd/var/log/httpd/ because, when run in chroot jail, Apache
/chroot/httpd directory as the equivalent of
/. This means that it cannot access
/var/log on the normal filesystem.
Copying the nescessary files
Now shut down Apache, run
killall httpd, and you're ready to start
copying across the necessary files. Note that some directory names may be
different in your case depending upon how you originally installed Apache.
First, copy your configuration files:
# cp -r /etc/apache /chroot/httpd/etc/
Next, copy your Apache DocumentRoot and CGI scripts:
# cp -r /home/httpd/html /chroot/httpd/home/httpd/
# cp -r /home/httpd/cgi-bin /chroot/httpd/home/httpd/
Now copy your httpd binary (and, if you use them, the Apache
# cp /usr/sbin/httpd /chroot/usr/sbin/
# cp /usr/sbin/apache* /chroot/usr/sbin/
If you use mod_ssl you need to copy the
/etc/ssl directory and
its contents too:
# cp -a /etc/ssl /chroot/httpd/etc/
You should also copy any modules from your original install:
cp -r /usr/libexec/apache /chroot/httpd/usr/libexec/
Once you have copied Apache itself (and ssl if needed) you need to copy all of
the shared libraries Apache relies on to run. To find out which libraries you
# ldd /chroot/httpd/usr/sbin/httpd. This should give output something like:
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40017000) libm.so.6 => /lib/libm.so.6 (0x40037000) libcrypt.so.1 => /lib/libcrypt.so.1 (0x40059000) libdb.so.2 => /lib/libdb.so.2 (0x40086000) libexpat.so.0 => /usr/lib/libexpat.so.0 (0x40096000) libdl.so.2 => /lib/libdl.so.2 (0x400b6000) libc.so.6 => /lib/libc.so.6 (0x400b9000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
The exact output will depend upon how your httpd binary was built in the first
place. Copy the required files to their respective directories in your
# cp /lib/libsafe* /chroot/httpd/lib/ # cp /lib/libm* /chroot/httpd/lib/ # cp /lib/libcrypt* /chroot/httpd/lib/ # cp /lib/libdb* /chroot/httpd/lib/ # cp /usr/lib/libexpat* /chroot/httpd/usr/lib/ # cp /lib/libdl* /chroot/httpd/lib/ # cp /lib/libc* /chroot/httpd/lib/ # cp /lib/ld-* /chroot/httpd/lib/
You need certain libraries for some standard networking functionality:
# cp /lib/libnss_compat* /chroot/httpd/lib/ # cp /lib/libnss_dns* /chroot/httpd/lib/ # cp /lib/libnss_files* /chroot/httpd/lib/ # cp /lib/libnsl* /chroot/httpd/lib/
The /chroot/httpd/etc configuration files
For Apache to function properly you also need several configuration files from
/etc. First, edit the
/etc/group files. These should contain only entries for the Apache user and group you created earlier. For example:
/etc/passwd: apache:x:12347:12348:Apache Server:/dev/null:/bin/false /etc/group: apache:x:12347:
You also need several network configuration files:
# cp /etc/hosts /chroot/httpd/etc/ # cp /etc/host.conf /chroot/httpd/etc/ # cp /etc/resolv.conf /chroot/httpd/etc/ # cp /etc/nsswitch.conf /chroot/httpd/etc/
For extra security you can set the immutable bit on these configuration files.
When the immutable bit is set, root has to specifically
unset it before a file can be modified, making it much harder for an intruder to tamper with the files:
# chattr +i /chroot/httpd/etc/hosts # chattr +i /chroot/httpd/etc/host.conf # chattr +i /chroot/httpd/etc/resolv.conf # chattr +i /chroot/httpd/etc/nsswitch.conf # chattr +i /chroot/httpd/etc/passwd # chattr +i /chroot/httpd/etc/group
In order that the log files be written with the correct time, you need to check
localtime is a symlink to a file in
/usr/share/zoneinfo. To find out which file, run
ls -l /etc/localtime and copy the appropriate file to
syslogd monitors log files only in
/var/log. The chrooted httpd daemon will write its logs to
/chroot/httpd/var/log, however, so you need to tell syslogd to
monitor this directory too. To change this you need to edit the appropriate
/etc/rc.d/init.d/syslog, depending upon your distro.
daemon syslogd -m 0 to
daemon syslogd -m 0 -a /chroot/httpd/dev/log.
echo -n " /usr/sbin/syslogd" /usr/sbin/syslogd
echo -n " /usr/sbin/syslogd" /usr/sbin/syslogd -m 0 -a /chroot/httpd/dev/log
It is a good idea to create the nescessary log files and set the appendable
bit on them too.
# touch /chroot/httpd/var/log/apache/access_log # touch /chroot/httpd/var/log/apache/error_log # chmod 600 /chroot/httpd/var/log/apache/* # chattr +a /chroot/httpd/var/log/apache/*
Finally, you need to change the httpd startup script to run the chrooted
httpd. Depending on your distro, open up
/etc/rc.d/init.d/httpd and change the command that starts the
httpd daemon to read
/usr/sbin/chroot /chroot/httpd/ /usr/sbin/httpd.
Testing the server
If you have not already done so you should shut down the httpd daemon now.
Next, restart the syslog daemon:
/etc/rc.d/init.d/syslog restart accordingly).
Now start the chrooted version of Apache with
If there are no errors, check the daemon is running with the command
ps -aux | grep httpd. You should see several entries indicating a
running httpd process. Taking the process number from the output of
ps and running
ls -l /proc/PROC_NUMBER/root/ should show the structure of
/chroot/httpd rather than your server's
If something has gone wrong, you should try running your chrooted httpd with
strace. The command
# strace chroot /chroot/httpd /usr/sbin/httpd 2> httpd.strace redirects the output of
strace to a file named
httpd.strace which should give you an idea where the problem lies.
Once everything is running you can remove your original Apache install.
chroot can be used to help create a more secure environment, it is not
perfect. You still need to keep your Web server patched up to date and monitor your logs. Your
chroot environment should help to contain a potential breakin and protect your system's
main filesystem from unseen vulnerabilities in your Web server.