I've setup a web server for production use. The OS is Windows Server, and it runs Apache 2.0 and PHP 5.3 as an apache module (and MySQL too...). It is used to host several virtual hosts (Apache vhosts) belonging to different customers.
At this point PHP is running as the system user. In the future FTP access might be granted to customers, so - by default - every customer would be able to access the whole system through PHP. That is obviously unacceptable.
I understand that I can set open_basedir in PHP, yet I am not sure if it is encompassing and solid enough to be considered a solution - does it limit access on all PHP functions, such as include...? How about PHP streams?
I also know that IIS offers a solution to that problem, but I prefer to keep Apache.
What I would ideally like to set up, is a solution that would fulfill the following requirements (mainly):
- Be elegant and somehow automatic. I am manually managing the server - I want the setup of each vhost to involve the least amount of setup and configuration editing as possible.
- Allow for an exception. Most hosted websites are developed by myself, and I'd like to link all of them to a single library folder, so read-only access should be allowed to that folder although it would be outside the root of the vhost.
So, what are the options available, if any? I already did some research and it seems that most work in that field was done on Linux systems.
PHP and FTP have nothing to do with each other.
FTP is a (lousy, insecure, ancient) way of moving files from machine to machine.
PHP is a scripting language executed by your web server.
You can (and probably should) use the IIS FTP functionality to grant FTP access to your server, while denying your users access to things like the root volume (
C:\
) and your shared library directory.The other half of your security problem is PHP itself --
mod_php
isn't great at multi-tenant security, andopen_basedir
is not an all-encompassing solution (though it's better than nothing).If you want real security you pretty much need to give everyone their own Apache, in a chroot.
This is unpleasant (for you as the admin), but secure. It's also flexible since you can modify php.ini for each site.
Your next best option is PHP as a CGI.
You can call PHP's CGI interpreter as the website owner's user ID - this gives you the benefit of the operating system's file permission functionality, and avoids having to maintain separate Apache/PHP instances for each site.
The major downside is PHP has to be called as a CGI, so you lose any features that rely on PHP being a web server module.
Your third best option is
open_basedir
anddisable_functions
/disable_classes
.open_basedir
doesn't really secure anything as it only affects PHP: Your users can still upload/execute a binary to get access to other people's data.the
disable_functions
anddisable_classes
directives in php.ini let you turn off certain unsafe functions (you're on your own for a list of exploitable classes).You can cover the obvious holes this way, but you're basically the little Dutch boy with his finger in the dike. You've only got so many fingers, and there's always one more hole...
You definitely shouldn't run Apache as
Local System
(or any account with elevated privileges).Before putting this server into production ensure it's configured according to the best practices in the Apache documentation.
I have solved that problem with a combination of:
It's by no means the most secure solution but, with regular backups, it should be sufficient for hosting a handful of low-profile websites.
Update (about a year later): This setup saved me - if one can say that in this context. One of my vhosts was an outdated Wordpress installation which got infected. I could see strange temporary files being created in the PHP logs. The vhost was limited through open_basedir, which I presume contained the problem - I'm afraid all my files, and not only the files of this vhost, would have been compromised hadn't it been for that.