Chrooting Apache2 With mod_chroot On Debian Lenny

Want to support HowtoForge? Become a subscriber!
 
Submitted by falko (Contact Author) (Forums) on Tue, 2010-04-13 16:03. :: Debian | Apache | Security

Chrooting Apache2 With mod_chroot On Debian Lenny

Version 1.0
Author: Falko Timme <ft [at] falkotimme [dot] com>
Follow me on Twitter
Last edited 03/31/2010

This guide explains how to set up mod_chroot with Apache2 on a Debian Lenny system. With mod_chroot, you can run Apache2 in a secure chroot environment and make your server less vulnerable to break-in attempts that try to exploit vulnerabilities in Apache2 or your installed web applications.

I do not issue any guarantee that this will work for you!

 

1 Preliminary Note

I'm assuming that you have a running Debian Lenny system with a working Apache2, e.g. as shown in this tutorial: The Perfect Server - Debian Lenny (Debian 5.0) [ISPConfig 2]. In addition to that I assume that you have one or more web sites set up within the /var/www directory (e.g. if you use ISPConfig).

 

2 Installing mod_chroot

To install mod_chroot, we simply run:

aptitude install libapache2-mod-chroot

Then we enable mod_chroot and restart Apache:

a2enmod mod_chroot
/etc/init.d/apache2 restart

 

3 Configuring Apache

I want to use the /var/www directory as the directory containing the chroot jail. Debian's Apache uses the PID file /var/run/apache2.pid; when Apache is chrooted to /var/www, /var/run/apache2.pid translates to /var/www/var/run/apache2.pid. Therefore we create that directory now:

mkdir -p /var/www/var/run
chown -R root:root /var/www/var/run

Now we must tell Apache that we want to use /var/www as our chroot directory. We open /etc/apache2/apache2.conf, and right below the PidFile line, we add a ChrootDir line:

vi /etc/apache2/apache2.conf

[...]
#
# PidFile: The file in which the server should record its process
# identification number when it starts.
# This needs to be set in /etc/apache2/envvars
#
PidFile ${APACHE_PID_FILE}
ChrootDir /var/www
[...]

Next we must tell our vhosts that the document root has changed (for example, a DocumentRoot /var/www translates now to DocumentRoot /). We can do this either by changing the DocumentRoot directive of each vhost, or more easier, by creating a symlink in the file system.


3.1 First Method: Changing The DocumentRoot

Let's assume we have a vhost with DocumentRoot /var/www. We must now open the vhost configuration of that vhost and change DocumentRoot /var/www to DocumentRoot /. Accordingly, DocumentRoot /var/www/web1/web would now translate to DocumentRoot /web1/web, and so on. If you want to use this method, you must change the DocumentRoot for every single vhost.

 

3.2 Second Method: Creating A Symlink In the File System

This method is easier, because you have to do it only once and don't have to modify any vhost configuration. We create a symlink pointing from /var/www/var/www to /var/www:

mkdir -p /var/www/var
cd /var/www/var
ln -s ../../ www


Finally, we have to stop Apache, create a symlink from /var/run/apache2.pid to /var/www/var/run/apache2.pid, and start it again:

/etc/init.d/apache2 stop

ln -s /var/www/var/run/apache2.pid /var/run/apache2.pid
/etc/init.d/apache2 start

That's it. You can now call your web pages as before, and they should be served without problems, as long as they are static HTML files or using mod_php.

If you are using CGI, e.g. Perl, suPHP, Ruby, etc., then you must copy the interpreter (e.g. /usr/bin/perl, /usr/sbin/suphp, etc.) to the chroot jail together with all libraries needed by the interpreter. You can find out about the required libraries with the ldd command, e.g.

ldd /usr/sbin/suphp

server2:/var/www/web1/log# ldd /usr/sbin/suphp
        linux-gate.so.1 =>  (0xffffe000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e34000)
        libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb7e0f000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7e03000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7cd2000)
        /lib/ld-linux.so.2 (0xb7f23000)
server2:/var/www/web1/log#

If you've copied all required files, but the page still isn't working, you should take a look at the Apache error log. Usually it tells you where the problem is. Also read http://core.segfault.pl/~hobbit/mod_chroot/caveats.html for known problems and solutions.

 

4 Links


Please do not use the comment function to ask for help! If you need help, please use our forum.
Comments will be published after administrator approval.
Submitted by max (not registered) on Thu, 2011-01-13 16:06.

Hi,
I am new to chrooting, so I apologise in advance if I ask silly questions. I have followed your tutorial, but now I can't run my phpMyAdmin. I installed it in /usr/local/phpMyAdmin and created a symbolic link to /var/www
As a consequence I am getting error 403 when I try to connect to it.
What am I doing wrong?
Max
P.S. I am running Debian GNU/Linux version 5.0.7

Submitted by Rob (not registered) on Mon, 2010-06-21 09:10.

I'm not running ISPConfig, but I do have a fairly standard setup of apache2 (2.2.9) on Debian Lenny. These instructions break it in a maddening manner.

 My ServerRoot is /etc/apache2; vhost configs are set up in the usual way under /etc/apache2/sites-available (and ./sites-enabled); the site files themselves are under /srv/www/(sitename)/public_html, etc.

 So, my vhost config files need to look like this:

<VirtualHost *:80>
    ServerName domain.com
    DocumentRoot /domain.com/public_html/
    ErrorLog /srv/www/domain.com/logs/error.log
    CustomLog /srv/www/domain.com/logs/access.log combined
    <Location />
        AuthUserFile /domain.com/.htpasswd
        AuthName "Access restricted to domain.com developers"
        AuthType Basic
        require valid-user
    </Location>
    SetEnv TMPDIR /domain.com/tmp/
    php_admin_value open_basedir /domain.com/:/usr/bin/pdftk
    php_admin_value upload_tmp_dir /domain.com/tmp/
</VirtualHost>

 

 Note the goofy mix of chroot'd and not-chroot'd directories. The chroot'd DocumentRoot will trigger warnings when apache2 is started; if you ignore those, then everything appears to work OK. However, if the ErrorLog directive uses a chroot'd path, then those warnings somehow trigger a fatal error that causes apache2 to not start at all. (This makes debugging this a real adventure.) But, once it's running, the non-chroot'd paths for both ErrorLog and CustomLog seem to work just fine.

 I've verified that the DocumentRoot, ErrorLog, CustomLog, and AuthUserFile directives all work with this setup. I'm not sure about the rest.

It's possible there's something seriously wrong with my setup, but everything's been working great for months (until now), so if there is, I don't know what it is.