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:

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/mod_suphp.so – 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:

[global]
;Path to logfile.
logfile=/var/log/suphp/suphp.log
;Loglevel. Info level is good for most cases but the file grows fast and should be rotated.
loglevel=info
;User Apache is running as. By default, in CentOS this is 'apache'.
webserver_user=apache
;Path all scripts have to be in. In CentOS the webroot is /var/www/html/ by default.
docroot=/var/www/html/
; Security options. suPHP will check if the executed files and folders have secure permissions.
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser. Disable this unless you are debugging with a browser.
errors_to_browser=false
;PATH environment variable
env_path=/bin:/usr/bin
;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.
umask=0077
; 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.
min_uid=200
; Minimum GID. Similarly to uid, set this to the first gid of a web user.
min_gid=200
[handlers]
;Handler for php-scripts
x-httpd-php="php:/usr/bin/php-cgi"
;Handler for CGI-scripts
x-suphp-cgi="execute:!self"

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:

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:

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:

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.