Here are several techniques for creating a secure shared web server.
Update 2010-03-14 – Revised opinion about APC and eAccellerator, which possibly do use memory-mapped files, also added detail about mpm_worker not working with mod_apparmor.
PHP open_basedir ini setting
PHP provides this setting in order to limit the access of functions which use PHP’s fopen to a specified directory. PHP extensions may not always use this, instead using the standard fopen, which wont be protected. Shell functions, such as exec, will also be unable to restrict external programs, so should be disabled.
If you are using mod_php, you will need to use php_admin_value rather than php_value, as .htaccess files can override php_value or php.ini settings:
<vhost *:80> ... php_admin_value open_basedir /path/to/project </vhost>
This technique involves the use of setuid, which allows the super-user to change to any other user. The way suEXEC does this is providing a program with the user sticky bit set. With the right configuration, Apache will call this, passing in a script to execute, and the user and group id for which to run from.
Suexec will check a few conditions against it’s compiled settings, such as the base directory from which scripts are allowed to run from, and directory permissions. If these pass, it will execute the script.
Using suExec in CGI mode, or when using suPHP, you will get the same disadvantages of using CGI normally, and so would not be suitable for a server.
suEXEC can also initialise a program supporting FastCGI, allowing better utilisation of resources. The FastCGI server can then be connected to from Apache. It does not have the benefit of Apache’s process pooling, and you may not be able to modify the FastCGI pool once running.
For more information check out this blog post on setting it up.
mpm_itk is an Apache process model based on mpm_prefork, which instead runs its master process as root, giving it the ability to fork and setuid Apache itself. This gives many advantages over the above techniques, allowing use of any Apache modules and process pooling.
It however has a tradeoff. Firstly, the connection is established by a process running as super-user. This, the module’s creator mentions, would be a problem if there was a mod_ssl security hole.
Secondly, since processes using setuid cannot return to super-user, the only realistic possibility is to terminate the fork. From a performance viewpoint of forking and terminating, this isn’t a big deal, however there is no way to persist modified shared memory between requests, as forks copy-on-write. Memory-mapped file support should still work, as well as regular file caching.
To use, install the mpm-itk, and add the configuration to your vhost:
<vhost *:80> ... AssignUserID myproject-apache myproject-apache </vhost>
For more information checkout the mpm-itk project page.
This is an Apache module which comes with AppArmor. AppArmor is a kernel-level access control module, which allows processes to run under different configurations (called hats). mod_apparmor can change the hat a vhost is running under, giving kernel-level access control to all calls to files to all Apache modules.
This, unlike mpm-itk, isn’t restricted to a request fork and terminate processing model, so should work on more Apache2 mpms.
Mpm_worker, however will have problems with changing hats per process, as multiple requests to different vhosts share the same hat, so mod_apparmor shouldn’t be used. This doesn’t stop you from just using AppArmor by itself to provide a global policy.
<vhost *:80> ... AAHatName MY_HAT_NAME </vhost>
See the following link for more information on using mod_apparmor and configuring hats for it: 5.2. Configuring Apache for mod_apparmor
As mentioned, mod_apparmor needs AppArmor to be compiled into the kernel, which may rule out some Linux distributions. Distributions like Ubuntu have AppArmor integrated into their kernel, so if compiling your kernel is not an option, you could switch distribution.
mod_apparmor may be the best option for a secure shared web server, as it would seem the most secure whilst allowing shared cache modules to work correctly, which give languages like PHP a huge boost in performance.