Prevent PHP/Apache from access files above site directory

2.1k views Asked by At

I'm configuring a multidomain web server using Apache virtual hosts and suEXEC (Centos 6.5, Apache 2.2.5 and PHP 5.3.3).

I want to prevent PHP to access folders/files above the website directory. I will explain step by step what are my settings and at last what's the problem.

This is the folder structure that I'm using:

/var/www/domain.com/public_html/

Inside /var/www/ I've got this:

drwxr-xr-x  2 root    root   4.0K Aug 13 13:30 cgi-bin/
drwxrwxr-x  4 apache  apache 4.0K Jan 28 09:16 site1.com/
drwxrwxr-x  4 apache  apache 4.0K Jan 28 08:44 site2.com/
drwxr-xr-x  4 apache  apache 4.0K Jan 30 11:08 site3.com/

and inside /var/www/site1.com/:

drwxr-xr-x 2 apache apache 4.0K Jan 30 10:16 logs/
drwxr-xr-x 3 user1  user1  4.0K Jan 30 11:08 public_html/

The virtual host definition for site1.com inside httpd.conf is:

<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot /var/www/site1.com/public_html
    ServerName www.site1.com
    ServerAlias site1.com
    ErrorLog /var/www/site1.com/logs/error_log
    CustomLog /var/www/site1.com/logs/access_log common

    php_flag log_errors on
    php_flag display_errors on
    php_value error_log /var/www/site1.com/logs/php_errors.log

    <Directory "/var/www/site1.com/public_html">
        Options FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>

    SuexecUserGroup user1 user1
    AddHandler application/x-httpd-php .php
    Action     application/x-httpd-php /cgi-bin/php-cgi

    ScriptAlias /cgi-bin/ /var/www/site1.com/public_html/cgi-bin/
    <Directory "/var/www/site1.com/public_html/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

But, I wrote and executed this php script (www.site1.com/test.php)

<?php
system("id");
print "<pre>";
system("ls /var/www");
print "</pre>";
?>

and I get:

uid=503(user1) gid=503(user1) groups=503(user1)

site1.com
site2.com
site3.com

That means that PHP can access any folder in my server (including /etc /var /usr, etc)

I'd like to prevent Apache/PHP to access all folders above /var/www/site1.com

How should I configure Apache?

I've done an extensive google research about this issue, but I couldn't find the solution.

Thanks a lot.

1

There are 1 answers

1
Jack_Hu On

Running on production, you should really be using something like:

disable_functions=exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

in your php.ini file. Allowing things like system or exec represents a real security flaw.

You also want to use something like:

php_admin_value open_basedir /var/www/site1.com/

In your Apache vHost conf, to prevent PHP from overstepping its desired boundaries...

As it stands, I could upload a PHP file as user1 to /var/www/site1.com/public_html/attacker.php, that contains:

<?php
chmod("/var/www/site2.com", 777);
?>

Then, open up my browser and navigate to http://site1.com/attacker.php. Apache would pass this off to PHP quite happily, run it, and as Apache owns /var/www/site2.com is quite capable of changing the permissions.

Bam!

user1 can now access /var/www/site2.com/, as well as anyone else with a user account on that machine. It could then hijack the site, creating new files to host bitcoin mining operations, sell Viagra, etc., etc.

Note: Even if you trust your users not to do anything malicious, there's no guarantee that a third party can't gain access to their account and do something like this. Best way to deal with it is to contain a compromised account, so it can't do too much damage to the system at large.

For more info, check out: