Friday, October 25, 2013

Isolate Apache virtual hosts with suPHP

By default Apache runs all virtual hosts under the same Apache user, with no isolation between them. That makes security vulnerabilities in server-side languages such as PHP a serious threat. An attacker can compromise all websites and virtual hosts on a server as soon as he finds one site that's hosted on it that's vulnerable. To address this problem, you can deploy the Apache module suPHP, which is designed to ensure isolation between virtual hosts that support PHP.
SuPHP installs an Apache module called mod_suPHP that passes the handling of PHP scripts to the binary /usr/local/sbin/suphp, which uses the setuid flag-rwsr-xr-x. – and thereby ensures that a PHP web script runs under the user of its file owner. Thus to accomplish isolation you can create different users for each Apache virtual host and change the ownership of their web files to match that of the virtual host. Once all virtual hosts run under different users you can set strict file permissions on the web files and thus ensure that a script executed in one virtual host cannot write to or even read a file from another virtual host.

suPHP installation

Developer Sebastian Marsching provides suPHP only as a source package, licensed under the GNU GPLv2. Even though you might find suPHP as a binary installation from a third-party repository, for best compatibility and performance you should compile the software yourself. You will need the following packages:
  • apr-util-devel – APR utility library development kit
  • httpd-devel – development interfaces for the Apache HTTP server
  • gcc-c++ – C++ support to the GNU Compiler Collection
To install these in CentOS, run the command yum -y install apr-util-devel httpd-devel gcc-c++.
Download suPHP version 0.7.2 – the most recent version, released in May. Unfortunately, the officially shipped source package is not compatible with CentOS 6. Before you can compile it you need to run the following commands:
libtoolize --force                      #provides libtool support and replaces the default libtool files
aclocal                                 #creates the aclocal.m4 file by consolidating various macro files
autoheader                              #creates a template file of C ‘#define’ statements
automake --force-missing --add-missing  #generates files
autoconf                                #produces shell scripts for the automatic configuration
Manually specify the APR path with a command like ./configure --with-apr=/usr/bin/apr-1-config. After that run the usual make && make install to complete the installation.
A successful installation creates the following files:
  • /usr/lib/httpd/modules/ – the Apache module
  • /usr/local/sbin/suphp – the suPHP binary

suPHP configuration

You configure suPHP in the file /etc/suphp.conf. Here's a sample configuration file annotated with explanations of all the directives:
;Path to logfile.

;Loglevel. Info level is good for most cases but the file grows fast and should be rotated.

;User Apache is running as. By default, in CentOS this is 'apache'.

;Path all scripts have to be in. In CentOS the webroot is /var/www/html/ by default.

; Security options. suPHP will check if the executed files and folders have secure permissions.

;Check wheter script is within DOCUMENT_ROOT

;Send minor error messages to browser. Disable this unless you are debugging with a browser.

;PATH environment variable

;Umask to set, specify in octal notation. Such a umask will create new files with strict permissions 700 which allow only the owner to read/write/execute a file.

; Minimum UID. Set this to the first uid of a web user and above the uids of system users. Check the file /etc/passwd for the uids.

; Minimum GID. Similarly to uid, set this to the first gid of a web user.

;Handler for php-scripts

;Handler for CGI-scripts
The above options provide a high security level. Note the logfile option, which logs each script execution to a log file when the logging level is set to "info," and thereby gives you useful information about which users executes what scripts. Output looks like:
[Sat Oct 05 22:11:58 2013] [info] Executing "/var/www/html/" as UID 501, GID 501
[Sat Oct 05 22:12:00 2013] [info] Executing "/var/www/html/" as UID 502, GID 502
For every PHP execution suPHP reports the date and time, the full path to the executed script, and the user and group that executed it. With this information you can track each virtual host's activity.
For more options and additional information on settings, check suPHP's documentation.
Next, configure Apache to use the suPHP handler for PHP scripts. PHP settings are usually found in a separate file, such as /etc/httpd/conf.d/php.conf. Remove any previous PHP configuration and leave only the new settings:
#Load the module
LoadModule suphp_module modules/

#Add the handler
AddHandler x-httpd-php .php .php3 .php4 .php5 .phtml
suPHP_AddHandler x-httpd-php

#Enable suPHP
suPHP_Engine on

#Specify where the suphp.conf file is
suPHP_ConfigPath /etc/
Finally, create a vhost with suPHP support by editing your Apache vhost file (e.g. /etc/httpd/conf.d/ like this:

suPHP_UserGroup exampleuser exampleusergroup
DocumentRoot /var/www/html/example

The only part of the vhost unique to suPHP is suPHP_UserGroup, which must be present for each vhost. For the highest level of isolation, create a new user and group for each virtual host by using the command useradd -r exampleuser from the Linux command line. If the user you create is used only for suPHP, you can disable the user's ability to log in the system, which can help against threats like brute force attacks.
In the above vhost configuration, the directory /var/www/html/example (and all files and subdirectories under it) must belong to the user exampleuser and the group exampleusergroup. If they are not, suPHP will render an internal server error when you try to execute an incorrectly owned file.
You can automate the creation of a new virtual host and set up the proper files and folders by using a Bash script like this one:
#This script expects as first argument the domain name of the script

#Remove the dot from the domain for the user (group) creation
user=`echo $1|sed "s/\.//g"`
echo "Adding user $user"
useradd -r $user
echo "Creating vhost /etc/httpd/conf.d/$1.conf"
echo "" >> /etc/httpd/conf.d/$1.conf
echo "ServerName $1" >> /etc/httpd/conf.d/$1.conf
echo "ServerAlias www.$1" >> /etc/httpd/conf.d/$1.conf
echo "suPHP_UserGroup $user $user" >> /etc/httpd/conf.d/$1.conf
echo "DocumentRoot /var/www/html/$1" >> /etc/httpd/conf.d/$1.conf
echo "" >> /etc/httpd/conf.d/$1.conf
echo "Creating the directory /var/www/html/$1 and setting ownership"
mkdir "/var/www/html/$1"
echo "Chowning /var/www/html/$1 to $user:"
chown $user: /var/www/html/$1
echo "Checking and reloading apache"
apachectl configtest && apachectl graceful
However, you can't automate everything. Don't forget to set the correct ownership and permissions when you manually place web files into each vhost's webroot directory. The recommended file permissions are 700, which provide read/write/execute permissions only for the owner.
SuPHP is a great way to strengthen security on servers that run PHP-based websites, which is why many commercial solutions are either based on it or similar to it. However, according to the project's FAQ, suPHP is no longer actively maintained, so use it with caution.

No comments:

Post a Comment