I'm using suexec to ensure that PHP scripts (and other CGI/FastCGI apps) are run as the account holder associated with the relevant virtual host. This allows for securing each users' scripts from reading/writing by other users.
However, it occurs to me that this opens up a different security hole. Previously, the web server ran as an unprivileged user, with read-only access to user's files (unless the user changed the file permissions for some reason). Now, the web server can also write to user's files.
So while I've prevented different users taking advantage of each other's scripts, I've made it so that in the event that some application has a remote code injection vulnerability, it now has not only read access but also write access to all that user's scripts and website.
How can I deal with this?
One idea I've had is to create a second user account for each user account in the system, so that each user has their own user account, and all their scripts are run under another user account. But that seems cumbersome.
Running PHP under the web server's permissions isn't isn't necessarily better or worse than using SuPHP. It's just different. The first model separates the owner from the web server, while the second model separates the owner (and his PHP code) from all the other users on the machine.
Using suPHP doesn't necessarily increase your overall security, it just redirects it. Instead of trying to prevent break-ins, you're isolating the sites from eachother. The justification is that, particularly in a shared-hosting environment, the former security model just wasn't working out: users constantly blew holes in their security by setting world-write permissions on everything so that the web application would work, and then a security compromise on one account would quickly metastasize to all the others on the server.
So, instead, it's common now to use tools like suPHP in large shared-hosting environments to remove the barrier between the user and his PHP application, and instead erect a barrier between a user and his neighbors.
So, in this case, you don't provide security, you provide separation. Unfortunately, suPHP requires that files be owned by the user you intend to run as, so creating a separate FTP user would be... a mess. You'd constantly have to
chown
files back and forth between the suPHP user and the FTP user.Instead, you need to pick a role: either you secure a site, or you secure a server. If you want to secure the site, then you need to separate the webserver from the content owner. That's a somewhat complex relationship to maintain correctly, so it's not recommended for shared hosting environments. If, instead, you want to protect the server from its users, then use suPHP to separate the user (and his code) from the others on the server. In this case the user is responsible for his own security. Good luck, user! Technically it is possible to have a secure PHP application--in theory, at least.
First of all, if the owner of a file doesn't need to have write access, don't give it to them. You can do this by setting the first number of the UNIX permissions. This means that only root will have write access to their files. This will be very annoying when they will need to upgrade files but you have said that they shouldn't have write access....
Secondly, they execute their script as a specific user. If they are locked in a file using open_basedir, it will not be a problem if they can write their files. If there is a hack, it will destroy only that user's files. Even without open_basedir, they should only be able to write in their files unless you have files with 777 rights which is another problem.
Thirdly, many websites need write access to, at least, certains files/folders. Per example, Wordpress needs to write in case there is a file upload. Write access for websites is not necessarily a security hole if you manage it well.
suexec is a very good start and open_basedir will make sure your users with write access stay in the defined directory.
suexec
always struck me as a kludge to work around the fact that you’re in an inherently shared hosting environment — allowing untrusted requests to invoke a script as the owning user is very very bad (and how WordPress installs get rooted) — if you were on a dedicated host, you wouldn’t set all of your files to mode 0777, after all. Just removing write access wouldn’t help, because the files are still owned by that user, and so ultimately writeable. Having two separate users doesn’t help much, either, for the same reason.The correct solution, to my mind, would be to run scripts as an unprivileged user, but
chroot
them — perhaps FastCGI would be a good solution here… where the fcgi process is chrooted, but the web server knows where to find the socket it creates.I realise this isn’t an “answer” as such, but I would place money on somebody having come up with this before and probably implemented it — perhaps even as a patch to
suexec
itself (I would envisageForceSUExecUID
andForceSUExecGID
options which could be applied on a per-virtual-host basis…)