Setting up chroot in Apache2 with PHP-FPM

 chroot != security, but still chroots are one of the security measures commonly used on servers as a first-line defense.

Imagine an attacker manages to perform some sort of injection and gains write access to your web root, what damage can they do and to what extent? A question many server admins may find interesting…

If a PHP chroot is in place the attacker is confined to the website root, i.e. /var/www/example.com, he can’t go anywhere outside of it; therefore by implementing a chroot you are limiting the damage to the specific website that was first attacked.

Now that I have explained what a chroot is and why it’s important, let me explain how to set one up:

Note: We are using Apache 2.4.25 on Debian Linux, PHP-FPM is installed and configured to be used with Apache

Let’s start by creating some directories in the chroot folder:

Important! The webroot is at /var/www/example.com/public_html

mkdir -p /var/www/example.com/etc/ssl

mkdir -p /var/www/example.com/var/run

mkdir -p /var/www/example.com/usr/share

mkdir /var/www/example.com/dev

Then, we need to bind mount them to the real directories; You may be asking why. PHP will run in the chroot and will see that folder as if it were the real system root, therefore we need to make some files available inside our chroot. (mainly DNS resolution, timezones, SSL CAs)

to do this we use an init script:

nano /etc/init.d/php5-fpm-chroot-setup

#!/bin/bash

CHROOT=/var/www/example.com

DIRS=”/var/run/nscd /usr/share/zoneinfo /etc/ssl/certs”

case “$1” in

  start)

        $0 stop 2>/dev/null

        for d in $DIRS; do

                mkdir -p “${CHROOT}${d}”

                mount –bind -o ro “${d}” “${CHROOT}${d}”

        done

        ;;

  stop)

        for d in $DIRS; do

                umount “${CHROOT}${d}”

        done

        ;;

  *)

        echo “Usage: $N {start|stop}” >&2

        exit 1

        ;;

esac

exit 0

DNS resolution: nscd

Timezones: zoneinfo (Used by wordpress)

CA Certs: ssl/certs (Used by curl for example)

We now need to fix entropy issues as /dev/[u]random Linux devices as not accessible from inside the chroot:

mknod -m 0666 /var/www/example.com/dev/null c 1 3

mknod -m 0666 /var/www/example.com/dev/random c 1 8

mknod -m 0444 /var/www/example.com/dev/urandom c 1 9

The only step left is setting up a new php-fpm pool, go to /etc/php5/fpm/pool.d copy the existing config and uncomment the chroot option:

chroot = /var/www/example.com

The end.

%d bloggers like this: