Chroot
environment for Apache
The chroot
utility is often used to jail a daemon in a restricted
tree. You can use it to insulate services from one another, so that security
issues in a software package do not jeoparize the whole server. When using the
makejail
script, setting up and updating the chrooted tree is much
easier.
This document is copyright 2002 Alexandre Ratti. It has been dual-licensed and
released under the GPL version 2 (GNU Public License) the GNU-FDL 1.2 (GNU Free
Documentation Licence) and is included in this manual with his explicit
permission. (from the original
document
)
This procedure was tested on Debian GNU/Linux 3.0 (Woody) with
makejail
0.0.4-1 (in Debian/testing).
root
and create a new jail directory:
$ mkdir -p /var/chroot/apache
chrapach
.
$ adduser --home /var/chroot/apache --shell /bin/false \ --no-create-home --system --group chrapach
FIXME: is a new user needed? (Apache already runs as the apache user)
/etc/apache/httpd.conf
configuration file , set the Group
and User options to chrapach. Restart Apache and make
sure the server is working correctly. Now, stop the Apache daemon.
makejail
(available in Debian/testing for now). You
should also wget
et lynx
as they are will be used by
makejail
to test the chrooted server: apt-get install
makejail wget lynx
/etc/makejail
directory:
# cp/usr/share/doc/makejail/examples/apache.py /etc/makejail/
/etc/makejail/apache.py
. You need to change the
chroot, users and groups options. To run this
version of makejail
, you can also added a packages
option. See the makejail
documentation
. A sample is shown here:
chroot="/var/chroot/apache" testCommandsInsideJail=["/usr/sbin/apachectl start"] processNames=["apache"] testCommandsOutsideJail=["wget -r --spider http://localhost/", "lynx --source https://localhost/"] preserve=["/var/www", "/var/log/apache", "/dev/log"] users=["chrapach"] groups=["chrapach"] packages=["apache", "apache-common"] userFiles=["/etc/password", "/etc/shadow"] groupFiles=["/etc/group", "/etc/gshadow"] forceCopy=["/etc/hosts", "/etc/mime.types"]
FIXME: some options do not seem to work properly. For instance,
/etc/shadow
and/etc/gshadow
are not copied, whereas
/etc/password
and /etc/group
are fully copied instead
of being filtered.
/etc/password
and /etc/group
were fully copied,
type:
$ grep chrapach /etc/passwd > /var/chroot/apache/etc/passwd $ grep chrapach /etc/group > /var/chroot/apache/etc/group
to replace them with filtered copies.
makejail
's
configuration file).
# cp -Rp /var/www /var/chroot/apache/var # cp -Rp /var/log/apache/*.log /var/chroot/apache/var/log/apache
/var/chroot/apache/dev/log
socket. In
/etc/init.d/sysklogd
, replace: SYSLOGD=""
with SYSLOGD=" -a /var/chroot/apache/dev/log" and
restart the daemon (/etc/init.d/sysklogd restart).
/etc/init.d/apache
). You might
need to make some changes to the default startup script for it to run properly
with a chrooted tree. Such as:
/proc
filesystem within the
jail.
#! /bin/bash # # apache Start the apache HTTP server. # CHRDIR=/var/chroot/apache NAME=apache PATH=/bin:/usr/bin:/sbin:/usr/sbin DAEMON=/usr/sbin/apache SUEXEC=/usr/lib/apache/suexec PIDFILE=/var/run/$NAME.pid CONF=/etc/apache/httpd.conf APACHECTL=/usr/sbin/apachectl trap "" 1 export LANG=C export PATH test -f $DAEMON || exit 0 test -f $APACHECTL || exit 0 # ensure we don't leak environment vars into apachectl APACHECTL="env -i LANG=${LANG} PATH=${PATH} chroot $CHRDIR $APACHECTL" if egrep -q -i "^[[:space:]]*ServerType[[:space:]]+inet" $CONF then exit 0 fi case "$1" in start) echo -n "Starting web server: $NAME" mount -t proc proc /var/chroot/apache/proc start-stop-daemon --start --pidfile $PIDFILE --exec $DAEMON \ --chroot $CHRDIR ;; stop) echo -n "Stopping web server: $NAME" start-stop-daemon --stop --pidfile "$CHRDIR/$PIDFILE" --oknodo umount /var/chroot/apache/proc ;; reload) echo -n "Reloading $NAME configuration" start-stop-daemon --stop --pidfile "$CHRDIR/$PIDFILE" \ --signal USR1 --startas $DAEMON --chroot $CHRDIR ;; reload-modules) echo -n "Reloading $NAME modules" start-stop-daemon --stop --pidfile "$CHRDIR/$PIDFILE" --oknodo \ --retry 30 start-stop-daemon --start --pidfile $PIDFILE \ --exec $DAEMON --chroot $CHRDIR ;; restart) $0 reload-modules exit $? ;; force-reload) $0 reload-modules exit $? ;; *) echo "Usage: /etc/init.d/$NAME {start|stop|reload|reload-modules|force-reload|restart}" exit 1 ;; esac if [ $? == 0 ]; then echo . exit 0 else echo failed exit 1 fi
FIXME: should the first Apache process be run as another user than root (i.e. add --chuid chrapach:chrapach)? Cons: chrapach will need write access to the logs, which is awkward.
/etc/logrotate.d/apache
/var/log/apache/*.log with
/var/chroot/apache/var/log/apache/*.log
/etc/init.d/apache start
) and check what is it
reported in the jail log
(/var/chroot/apache/var/log/apache/error.log
). If your setup is
more complex, (eg. if you also use PHP and MySQL), files will probably be
missing. if some files are not copied automatically by makejail
,
you can list them in the forceCopy (to copy files directly) or
packages (to copy full packages and their dependencies) option the
/etc/makejail/apache.py
configuration file.
root 180 0.0 1.1 2936 1436 ? S 04:03 0:00 /usr/sbin/apache chrapach 189 0.0 1.1 2960 1456 ? S 04:03 0:00 /usr/sbin/apache chrapach 190 0.0 1.1 2960 1456 ? S 04:03 0:00 /usr/sbin/apache chrapach 191 0.0 1.1 2960 1456 ? S 04:03 0:00 /usr/sbin/apache chrapach 192 0.0 1.1 2960 1456 ? S 04:03 0:00 /usr/sbin/apache chrapach 193 0.0 1.1 2960 1456 ? S 04:03 0:00 /usr/sbin/apache
/proc
filesystem: ls -la
/proc/process_number/root/. where process is one of
the PID numbers listed above (2nd column; 189 for instance). The ntries for a
restricted tree should be listed:
drwxr-sr-x 10 root staff 240 Dec 2 16:06 . drwxrwsr-x 4 root staff 72 Dec 2 08:07 .. drwxr-xr-x 2 root root 144 Dec 2 16:05 bin drwxr-xr-x 2 root root 120 Dec 3 04:03 dev drwxr-xr-x 5 root root 408 Dec 3 04:03 etc drwxr-xr-x 2 root root 800 Dec 2 16:06 lib dr-xr-xr-x 43 root root 0 Dec 3 05:03 proc drwxr-xr-x 2 root root 48 Dec 2 16:06 sbin drwxr-xr-x 6 root root 144 Dec 2 16:04 usr drwxr-xr-x 7 root root 168 Dec 2 16:06 var
To automate this test, you can type:ls -la /proc/`cat /var/chroot/apache/var/run/apache.pid`/root/.
FIXME: Add other tests that can be run to make sure the jail is closed?
The reason I like this is because setting up the jail is not very difficult and the server can be updated in just two lines:
apt-get update && apt-get install apache makejail /etc/makejail/apache.py
If you are looking for more information you can consider these sources of information in which the information presented is based:
makejail homepage
,
this program was written by Alain Tesio)
Chrooting
daemons and system processes HOWTO
by Jonathan, Network Dweebs,
21/10/2002
Apache
in a chroot jail
in Securing and Optimizing Linux written
by Gerhard Mourani, 2000
Securing Debian Manual
2.99 5 marzo 2004Wed, 3 Mar 2004 09:18:54 +0100jfs@computer.org