A while back, when I was doing some research for a talk on server-side security for PHP, I looked into various “secure” methods for setting up a server for multiple users. Despite my search, I couldn’t find a simple and effective solution for managing a server with a large (and untrusted) user base (as is the case with many virtual hosting companies). Sure, there’s PHP’s
safe_mode, but its “safety” is misleading at best. There’s also
open_basedir, which helps a little, but it’s not quite enough. I also looked at jailing Apache (both the hard way and the easier way), but even then, all user directories have to be in the root jail, and any user can still read the readable and write to the writable files of another user in the jail.
For my research, I also looked at and tested mod_security, the goal of which is to secure applications from the Apache Web server, and the Hardened PHP Project’s Hardening Patch, which secures PHP applications from the language engine. Both of these are excellent tools and should be assessed by anyone seeking to “harden” their server configuration.
Still, I wanted to find something that would split off Apache so that each user’s site was running as that user instead of the general Apache user that could read and execute all user files. This global user serving and processing all pages is where the root of the problem lies. Yet, if Apache could serve each site as the owner of the site, then the owner’s file permissions could essentially be set to 700 (instead of being world/group readable for the Apache user) and Apache would still serve the pages since it’s running as the privileged user. Even better, run Apache with this configuration, and place it and the system users in a jail; no one would then be able to access any system files or the files of other users.
No matter how many people I asked, I couldn’t find an easy answer for how to do this.
Around that time, someone suggested I look into Metux MPM for Apache, but, from what I understand, Metux uses threading, and running PHP in a threaded environment is not recommended, so the solution needed to be non-threaded.
Finally, via a comment on Christopher Kunz’s blog, I’ve found something that, at least, sounds like what I’m looking for. It’s the Peruser MPM by Telena Internet Services, and it seems that it was created with PHP in mind.
Here’s what the site says about Peruser:
The fundamental concept […] is to run each apache child process as its own user and group, each handling its own set of virtual hosts. Peruser […] can also chroot() apache processes. The result is a sane and secure web server environment for your users, without kludges like PHP’s safe_mode. […] I created Peruser, which provides multiple processes for each unique user/group/chroot.
The site warns against using it in production, and it warns that it breaks mod_ssl and renders Apache not as scalable, but it sounds like a step in the right direction. I’m putting it on my radar to test soon.