Print View

Chrooting Apache and PHP
Created: 06/01/2005


General Information

Chrooting has been around for a long time now.  Chrooting makes a program believe that the root of the file system is higher up in the hierarchy.  For example, if I wanted to create a chroot in /chroot/httpd, a program executed from within the chroot would believe that "/chroot/httpd" was actually "/".  There in lies the beauty as the program can't reach any files outside "/chroot/httpd".  Security of the server as a whole is increased due to the fact that the system binaries are off limits.  In addition, chroots usually only have the bare minimum files inside, so exploits have a harder time breaking in.

Chroots can be broken out of.  On FreeBSD, jail can also be used.  Jail does the same as chroot, but on top of what chroot does, jail restricts what a process can do.  One of the benefits of OpenBSD is the fact that apache comes chrooted by default, which is nice.  But, that's not going to stop NetBSD or FreeBSD from doing this also.

So, why chroot instead of jail?  Jailing processes is actually a simple task.  Basically I want to help you out with 2 areas in this article.  The first is to get apache and php chrooted while working with a chrooted mysql.  And the second, I hope you can figure out from this how to chroot your own processes.  Once you figure out how to setup chroot trees, configuring jails should not be a challenge for you at all.

Installation

Lets start off by installing apache with mod_ssl and create our SSL certificates.
#
#
#
#
cd /usr/ports/www/apache13-modssl
make
make certificate TYPE=custom
make install
Next we set a variable of where we wish to place it.  To help avoid unnecessary typing, it's recommended that you have your chroot directory on its own disklabel.  This way you can place further restrictions in the /etc/fstab file.
# TGT=/chroot/httpd

Configuration

Now we need to prepare our directory structure for the chroot.
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
cd $TGT
mkdir dev
mkdir etc
mkdir tmp
mkdir -p var/run
mkdir -p usr/lib
mkdir usr/libexec
mkdir -p usr/local/www/
mkdir usr/local/lib
mkdir -p usr/local/etc/apache
mkdir -p usr/local/libexec/apache
mkdir -p usr/local/www/data
mkdir usr/local/www/vhosts
mkdir usr/local/sbin
mkdir -p usr/X11R6/lib
mkdir var/log
Next, there are a few devices we need in our dev directory in which apache needs.  We will use the mknod for this task.
#
#
#
#
#
#
#
#
#
mknod $TGT/dev/null c 2 2
chown root:sys $TGT/dev/null
chmod 666 $TGT/dev/null
mknod $TGT/dev/random c 2 3
chown root:wheel $TGT/dev/random
chmod 755 $TGT/dev/random
cd $TGT/dev
ln -s random urandom
vi /etc/rc.conf
Add the following line in so we can get some logging going on.
syslogd_flags="-l /chroot/httpd/dev/log" # Or Where your target resides
Now there are a few methods we can use to figure out what files we need for our chroot: ldd, truss, and strings are amongst the most commonly used.  I'll go over ldd and strings here.
# ldd /usr/local/sbin/httpd
/usr/local/sbin/httpd:
libcrypt.so.2 => /usr/lib/libcrypt.so.2 (0x280c6000)
libmm.so.13 => /usr/local/lib/libmm.so.13 (0x280df000)
libc.so.5 => /usr/lib/libc.so.5 (0x280e3000)

# strings /usr/local/sbin/httpd | grep lib
/usr/libexec/ld-elf.so.1
libcrypt.so.2
libmm.so.13
libc.so.5
Those commands will display the required libraries.  Next, we need to copy those required libraries over to our chroot.
#
#
#
#
#
#
#
#
#
#
#
install -C /usr/local/sbin/httpd $TGT/usr/local/sbin
install -C /var/run/ld-elf.so.hints $TGT/var/run/
install -C /usr/lib/libcrypt.so.2 $TGT/usr/lib/
install -C /usr/lib/libc.so.5 $TGT/usr/lib/
install -C /usr/libexec/ld-elf.so.1 $TGT/usr/libexec/
install -C /usr/local/lib/libexpat.so.4 $TGT/usr/local/lib/
install -C /usr/local/lib/libmm.so.13 $TGT/usr/local/lib/
cp /etc/hosts $TGT/etc/
cp /etc/resolv.conf $TGT/etc/
cp /etc/group $TGT/etc/
cp /etc/master.passwd $TGT/etc/passwords
Remove everything inside the group and passwords file except for the user/group www and nobody/nogroup
#
#
#
#
#
#
vi $TGT/etc/group
vi $TGT/etc/passwords
cd $TGT/etc
pwd_mkdb -p -d $TGT/etc passwords
rm -f $TGT/etc/master.passwd
cp -Rvp /usr/local/etc/apache/* $TGT/usr/local/etc/apache/
Now, before we get into too much else, go ahead and install php and any other apache modules, which you require or need.

Once that's done let's get those modules inside the chroot tree.
# cp -Rvp /usr/local/libexec/apache/* $TGT/usr/local/libexec/apache/
Now php can be a pain depending upon what options you gave it to install.  So we're going to determine what libraries php needs just like we did with apache.
# ldd /usr/local/libexec/apache/libphp4.so
/usr/local/libexec/apache/libphp4.so:
libcrypto.so.3 => /usr/local/lib/libcrypto.so.3 (0x2833d000)
libssl.so.3 => /usr/local/lib/libssl.so.3 (0x28441000)
libcrypt.so.2 => /usr/lib/libcrypt.so.2 (0x28472000)
libc-client4.so.8 => /usr/local/lib/libc-client4.so.8 (0x2848b000)
libzzip.so.10 => /usr/local/lib/libzzip.so.10 (0x28542000)
Those are just a few.  I'm sure your list is much longer.  So we need to ensure these libraries are inside our chroot tree.
#
#
#
#
#
install -C /usr/local/lib/libcrypto.so.3 $TGT/usr/local/lib/
install -C /usr/local/lib/libssl.so.3 $TGT/usr/local/lib/
install -C /usr/lib/libcrypt.so.2 $TGT/usr/lib/
install -C /usr/local/lib/libc-client4.so.8 $TGT/usr/local/lib/
install -C /usr/local/lib/libzzip.so.10 $TGT/usr/local/lib/
And so on...Or, if you wish to take the lazy-man's approach, you could run this:
#
#
#
#
#
#
ldd /usr/local/libexec/apache/libphp4.so | awk {' print $3 '} | \
grep '/usr/lib' | xargs -J % install -C % $TGT/usr/lib/
ldd /usr/local/libexec/apache/libphp4.so | awk {' print $3 '} | \
grep '/usr/local/lib' | xargs -J % install -C % $TGT/usr/local/lib/
ldd /usr/local/libexec/apache/libphp4.so | awk {' print $3 '} | \
grep '/usr/X11R6' | xargs -J % install -C % $TGT/usr/X11R6/lib/
Now, just to show you how great of a tool xargs is, let's use it to run the same thing on all the apache modules.  (I would like to thank http://daemonnews.org for teaching me that this wonderful command existed.)
#
#
#
#
#
#
ldd /usr/local/libexec/apache/* | grep '=>' | awk {' print $3 '} | \
grep '/usr/lib' | xargs -J % install -C % $TGT/usr/lib/
ldd /usr/local/libexec/apache/* | grep '=>' | awk {' print $3 '} | \
grep '/usr/local/lib' | xargs -J % install -C % $TGT/usr/local/lib/
ldd /usr/local/libexec/apache/* | grep '=>' | awk {' print $3 '} | \
grep '/usr/X11R6/lib' | xargs -J % install -C % $TGT/usr/X11R6/lib/
Now let's try to fire it up.
# chroot $TGT /usr/local/sbin/httpd
Well, that seems to have worked.  Now we need to integrate mysql into this.  This is really simple.
#
#
cp /etc/my.cnf $TGT/etc/
ln /chroot/mysql/tmp/mysql.sock $TGT/tmp/mysql.sock
It should be working now.  Just edit your configurations to your desire and enjoy.  Don't forget to edit your startup scripts for apache.

Author: Leigh Renfrow
soup4you2 at mac dot com



3 Comments

Posted by sporkit on August 06, 2005 at 5:47:09 pm EEST

i was able to chroot apache as and php in my jail at /usr/chroot_apache but unfortunatly ran into this problem at that last step.

sporkitBSD# ln /tmp/mysql.sock /usr/chroot_apache/tmp
ln: /usr/chroot_apache/tmp/mysql.sock: Cross-device link

also i compilied the port for mysql41 but never found a my.cnf.  i search the entire system too.  the mysql server is working however with out it.

and one last thing.  occationally when im copying files over after trying to actually start the jail it'll say i have a dependancy on a certain file.  even if move it over to the correct place with the same permissions it still complains.


Posted by sporkit on August 06, 2005 at 5:47:09 pm EEST

to get this working i recompiled the mysql

./configure --prefix=/usr/mysql41  --with-unix-socket-path=/usr/chroot_apache/tmp/mysql.sock

if you dont set the correct permissions for the database directory it wont work either.

# chown -R mysql data
# chgrp -R mysql .

most importantly mysql will give you vauge errors about mysql.sock if it cant write to your new temp dir.

chmod 755 /usr/chroot_apache/tmp


Posted by star on October 22, 2006 at 7:36:24 am EEST

I'm geting this one error :

avec# [/][7:25am] # chroot /chroot/httpd/ /usr/local/sbin/httpd
fopen: Operation not supported
httpd: could not open document config file /dev/null

I've cheked all files twice, everything seems to be normal. Also it's it normal for php4 :

avec# [/][7:25am] # pkg_info | grep "php4"
php4-4.4.4_1        PHP Scripting Language (Apache Module and CLI)
php4-bz2-4.4.4_1    The bz2 shared extension for php
php4-ctype-4.4.4_1  The ctype shared extension for php
php4-extensions-1.0 A "meta-port" to install PHP extensions
php4-gd-4.4.4_1     The gd shared extension for php
php4-mbstring-4.4.4_1 The mbstring shared extension for php
php4-mcrypt-4.4.4_1 The mcrypt shared extension for php
php4-mysql-4.4.4_1  The mysql shared extension for php
php4-overload-4.4.4_1 The overload shared extension for php
php4-pcre-4.4.4_1   The pcre shared extension for php
php4-posix-4.4.4_1  The posix shared extension for php
php4-session-4.4.4_1 The session shared extension for php
php4-sockets-4.4.4_1 The sockets shared extension for php
php4-tokenizer-4.4.4_1 The tokenizer shared extension for php
php4-xml-4.4.4_1    The xml shared extension for php
php4-zlib-4.4.4_1   The zlib shared extension for php
avec# [/][7:28am] #

avec# [/][7:25am] # ldd /usr/local/libexec/apache/libphp4.so
/usr/local/libexec/apache/libphp4.so:
        libcrypto.so.4 => /lib/libcrypto.so.4 (0x2826b000)
        libssl.so.4 => /usr/lib/libssl.so.4 (0x2835d000)
        libcrypt.so.3 => /lib/libcrypt.so.3 (0x2838b000)
        libm.so.4 => /lib/libm.so.4 (0x283a3000)
avec# [/][7:29am] #

all modules for php works fine on non-chrooted apache.


Copyright 2003 - 2010 BSD Guides.  All rights reserved.

About | Terms of Use | Privacy | Contact