Php – Stop PHP scripts being able to read files in other virtual host’s directory

apache-2.4PHP

Okay, so let's say I have two virtual hosts in my Apache config. One defines the directories and such for example.com, whilst the other is for second.org. The server root for apache is /var/www/ and the document roots for the two servers are var/www/example and var/www/second respectively. If a PHP script sat inside of var/www/example, it could read the entire system files. It could also read and execute anything inside of the /var/www/ directory. This means a script on example.com could be used to run or read a script on second.org.

I'd like to be able to lockdown each virtual host so that each PHP script can only read /var/www/virtualdomain directory. Kind of like a shared hosting server where if you attempt to run a script such as:

<?php
$dir    = '/var/www/otheruser';
$files1 = scandir($dir);
$files2 = scandir($dir, 1);
print_r($files1);
print_r($files2);
?>

Best Answer

There are generally two ways of handling this:

  • Running your PHP process as a separate user.
  • Configure PHP to keep within its document-root.

Both have its disadvantages.

Securing PHP will allow you to set a documet_root where a vhost should operate in while enabling PHP's Safe Mode feature. A slightly more dynamic configuration is to use open_basedir (which can be used without Safe Mode) but relies on a correct apache configuration. I don't think any of these configurations are a great securty feature because it does not account for external libraries and makes security dependent on the PHP implementation, not the operating system.

Running PHP as a separate user using Apache will require a third-party module or a specific configuration. Usually PHP is build as a module within Apache, so all PHP scripts run as the same user as the webserver. A module like suPHP or mod_ruid will drop a process from root specific user and continue the request. This will require running apache as root and compilation of some modules, not to mention a possible security hole. I would not recommend these setups.

You can also switch to PHP-FPM using mod_fastcgi or mod_proxy_fcgi. This will require you to setup a PHP-FPM 'pool' for every user you would like to give one or more vhosts. PHP-FPM will run as this specific user and will be set to the specific privileges on startup. You can also make specific PHP (ini) configuration settings for each PHP-FPM pool.