Has anyone set up any form of apache user isolation on CentOS? I have multiple virtual hosts on my machine, run by users who do not trust eachother. The problem is that any php script run by apache is able to do things like raw file io on other users' .htpasswds, php scripts, hidden directory listings, and so on. Database passwords can even be divulged in this way, since they are often stored in .php scripts, which can be read "in the raw" as files by other php scripts.
What is the easiest method for dealing with this? I found http://webauth.stanford.edu/manual/mod/perchild.html but it does not seem to be compiled with the CentOS 5 apache, and I've read elsewhere that php has issues with mutlithreaded apache. Is there any easy way to isolate individual users, by either having apache setuid, or chrooting php scripts, or (ugh) a clean way to run a new apache copy for each vhost?
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Has anyone set up any form of apache user isolation on CentOS? I have multiple virtual hosts on my machine, run by users who do not trust eachother. The problem is that any php script run by apache is able to do things like raw file io on other users' .htpasswds, php scripts, hidden directory listings, and so on. Database passwords can even be divulged in this way, since they are often stored in .php scripts, which can be read "in the raw" as files by other php scripts.
What is the easiest method for dealing with this? I found http://webauth.stanford.edu/manual/mod/perchild.html but it does not seem to be compiled with the CentOS 5 apache, and I've read elsewhere that php has issues with mutlithreaded apache. Is there any easy way to isolate individual users, by either having apache setuid, or chrooting php scripts, or (ugh) a clean way to run a new apache copy for each vhost?
There are a few links here discussing these issues. I have read them, but not implemented them.
http://www.linode.com/forums/viewtopic.php?t=2723
Barry
On Wed, 2 May 2007 07:04:28 -0500 (CDT) Barry Brimer lists@brimer.org wrote:
Has anyone set up any form of apache user isolation on CentOS?
The most paranoid apache setup I've seen was chrooted apache with mod_ruid taking user's uid/gid on per vhost basis. As fubar as it looks, it mostly works. I guess this is the way to go if you don't want t implement some kind of virtual machines (vps/xen/vmware).
On May 3, 2007, at 2:28 AM, Jure Pečar wrote:
The most paranoid apache setup I've seen was chrooted apache with mod_ruid taking user's uid/gid on per vhost basis. As fubar as it looks, it mostly works.
I just looked at mod_ruid's homepage. It's the worst security "enhancement" I've ever seen. I quote from the webpage:
-it has better performance than mod_suid2 because it doesn`t need to kill httpd children after one request. it makes use of kernel capabilites and after receiving a new request suids again. -there are some security issues, for instance if attacker successfully exploits the httpd process, he can set effective capabilities and setuid to root. i recommend to use some security patch in kernel (grsec), or something..
Like mod_suid2, it is parsing and dispatching requests as root (or CAP_SETUID, which is basically the same thing), so another Apache request parsing flaw would mean a root compromise. This module's special sauce is that it is also responding to the requests with CAP_SETUID - it is never dropping privileges! Here's my PHP-based exploit (forgive my syntax, which is probably wrong):
# r00t and crash machine with mod_ruid and mod_php! lolz! # <insert more stupid leetspeak here> # <trivial "exploits" don't work unless they're filled with stupid, arrogant, illegible comments>
# Use CAP_SYS_SETUID to get r00t! posix_setuid(0);
# Crash the system through L1nux's "killing processes makes them die" vulnerability! posix_kill(1, SIGKILL);
There is no way to distinguish between mod_ruid calling setuid() and mod_php (which runs in the same process) doing so.
In contrast, a standard Apache server setuid()s to user/group apache/ apache after binding the sockets in such a way that all special capabilities are lost and there's no going back.
The webpage recommends mitigating its insecurity with grsec "or something", but I don't understand how grsec can solve the fundamentally flawed design.
The proxied Apache or FastCGI setups are *MUCH* more secure.
I guess this is the way to go if you don't want t implement some kind of virtual machines (vps/xen/vmware).
Now that is a secure option, though not light-weight of course.
--- Scott Lamb slamb@slamb.org wrote:
[ Hilariously simple exploit ]
There is no way to distinguish between mod_ruid calling setuid() and mod_php (which runs in the same process) doing so.
Hahahaha. Very nice.
The proxied Apache or FastCGI setups are *MUCH* more secure.
Ok, so at the end of the day FCGI was quite a bit different than the FastCGI writups, plus I wanted to maintain my current selinux posture (no shell scripts executed by daemons, since most shellcode tries to execute, um shells).
Interestingly enough, the citi-fan.org repo maintainer is the author of the fcgi SRPM you linked. Turns out, he provides not only RPMS for rhel5, but also a selinux policy for it. Respekt 2 city-fan!
http://www.city-fan.org/ftp/contrib/yum-repo/
For the benefit of the archives, here is the quick rundown of what I did, following mostly the docs at http://fastcgi.coremail.cn/doc.htm:
-1. rm /var/log/audit/audit.log 0. /etc/init.d/auditd restart 1. yum install mod_fcgid-selinux 2. setenforce 0 (to make adapting my custom policy easier, since there are always mods to this stuff) 3. mkdir /var/www/cgi-bin/vhostuser1 4. cp /usr/bin/php-cgi /var/www/cgi-bin/vhostuser1 5. chown -R vhostuser1:vhostuser1 /var/www/cgi-bin/vhostuser1 6. chmod 755 /var/www/cgi-bin/vhostuser1 7. Add "SuexecUserGroup vhostuser1 vhostuser1" to vhost1's VirtualHost block 8. Add this block right after the vhost directive: <Directory /data/web/vhostuser1/virtual.host.one> AddHandler fcgid-script .php FCGIWrapper /var/www/cgi-bin/vhostuser1/php-cgi .php Options +ExecCGI allow from all </Directory> 9. semodule -b /usr/share/selinux/targeted/enableaudit.pp 10. /etc/init.d/httpd reload 11. Browse php scripts, database connects, etc 12. audit2allow -M my_fcgi < /var/log/audit/audit.log 13. installed that module with the on-screen instructions audit2allow prints (see RHEL5 selinux section for more details). 14. semodule -b /usr/share/selinux/targeted/base.pp
Steps 9 and 14 are required because some selinux messages are superfluous and are marked dontaudit, but for this setup a couple of these messages in my case were actually required permissions for this setup.
Note also this is only a from-memory sketch of that I did. You are advised to read the documentation for fcgi, and perhaps some other howtos from linked from this thread as well. In particular, I found these useful, though the FCGI apache config syntax is different than FastCGI:
http://ckdake.com/projects/documentation/php_security http://www.seaoffire.net/fcgi-faq.html
Note that I did not bother with their shell script wrapper, because I feel the environment variables they set were irrelevant, given that I use selinux and fcgi auto-adapts to load. Also, running shell-scripts from daemons is a no-go with selinux (unless you want to remove a good deal of the benefit selinux provides).
I guess this is the way to go if you don't want t implement some kind of virtual machines (vps/xen/vmware).
Now that is a secure option, though not light-weight of course.
Hrmm.. Not necessarily. Last I checked the Xen people were still in the process of hardening their kernel APIs to prevent vm guest breakout. I don't think the process was completed for 3.0, but I could be wrong..
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
On May 3, 2007, at 7:39 PM, Dan Mensom wrote:
For the benefit of the archives, here is the quick rundown of what I did, following mostly the docs at http://fastcgi.coremail.cn/doc.htm:
Thanks; I'll have to look back at your steps if I ever get around to setting up SELinux.
Now that is a secure option, though not light-weight of course.
Hrmm.. Not necessarily. Last I checked the Xen people were still in the process of hardening their kernel APIs to prevent vm guest breakout. I don't think the process was completed for 3.0, but I could be wrong..
Well, I hope it is, because I've got a server at a Xen-based virtual hosting company containing somewhat sensitive data.
Googling "xen guest breakout" doesn't turn up much. There are people saying they haven't formally proven there are no vulnerabilities in the design or implementation [1], but that's not too surprising - the same's true for the Linux kernel. I basically have to trust Linux anyway in the absence of specific bug reports, or I'd get nothing done.
[1] - http://article.gmane.org/gmane.comp.emulators.xen.user/23297
On 5/2/07, Dan Mensom mensomman@yahoo.com wrote:
Has anyone set up any form of apache user isolation on CentOS? I have multiple virtual hosts on my machine, run by users who do not trust eachother. The problem is that any php script run by apache is able to do things like raw file io on other users' .htpasswds, php scripts, hidden directory listings, and so on. Database passwords can even be divulged in this way, since they are often stored in .php scripts, which can be read "in the raw" as files by other php scripts.
What is the easiest method for dealing with this? I found http://webauth.stanford.edu/manual/mod/perchild.html but it does not seem to be compiled with the CentOS 5 apache, and I've read elsewhere that php has issues with mutlithreaded apache. Is there any easy way to isolate individual users, by either having apache setuid, or chrooting php scripts, or (ugh) a clean way to run a new apache copy for each vhost?
Apache gets interesting for things like this. Mostly you can use selinux and the suexec function for apache to run processes as users. This will get you the separation your users want, however it will only apply to php if you run php as a cgi, and not as a module. You'll take a performance hit doing it this way, but it should do everything you want.
On Wed, 2 May 2007, Dan Mensom wrote:
Has anyone set up any form of apache user isolation on CentOS? I have multiple virtual hosts on my machine, run by users who do not trust eachother. The problem is that any php script run by apache is able to do things like raw file io on other users' .htpasswds, php scripts, hidden directory listings, and so on. Database passwords can even be divulged in this way, since they are often stored in .php scripts, which can be read "in the raw" as files by other php scripts.
What is the easiest method for dealing with this? I found http://webauth.stanford.edu/manual/mod/perchild.html but it does not seem to be compiled with the CentOS 5 apache, and I've read elsewhere that php has issues with mutlithreaded apache. Is there any easy way to isolate individual users, by either having apache setuid, or chrooting php scripts, or (ugh) a clean way to run a new apache copy for each vhost?
One "using a canon to kill a fly" approach would be
* each vhost runs Apache under a vhost-specific uid/gid and bound only to the loopback interface on a port you assign, e.g.,
vhost01 -- User vhost01, Group vhost01, Listen 127:0.0.1:6001 vhost01 -- User vhost02, Group vhost02, Listen 127:0.0.1:6002
* the main apache does little but reverse proxy all the vhosts out to the Internet.
<VirtualHost *:80> ServerName vhost01.domain ProxyRequests Off ProxyPass / http://localhost:6001/ ProxyPassReverse / http://localhost:6001/ <Proxy *> Order deny,allow Allow from all </Proxy> </VirtualHost>
Given the right file permissions, no vhost would have access to another except via HTTP.
Downside: You're essentially doubling the number of Apache processes on your system. Another Upside: Configuration blunders in the vhosts won't throw errors in your main server process.
Quoting Paul Heinlein heinlein@madboa.com:
On Wed, 2 May 2007, Dan Mensom wrote:
Has anyone set up any form of apache user isolation on CentOS? I have multiple virtual hosts on my machine, run by users who do not trust eachother. The problem is that any php script run by apache is able to do things like raw file io on other users' .htpasswds, php scripts, hidden directory listings, and so on. Database passwords can even be divulged in this way, since they are often stored in .php scripts, which can be read "in the raw" as files by other php scripts.
What is the easiest method for dealing with this? I found http://webauth.stanford.edu/manual/mod/perchild.html but it does not seem to be compiled with the CentOS 5 apache, and I've read elsewhere that php has issues with mutlithreaded apache. Is there any easy way to isolate individual users, by either having apache setuid, or chrooting php scripts, or (ugh) a clean way to run a new apache copy for each vhost?
One "using a canon to kill a fly" approach would be
each vhost runs Apache under a vhost-specific uid/gid and bound only to the loopback interface on a port you assign, e.g.,
vhost01 -- User vhost01, Group vhost01, Listen 127:0.0.1:6001 vhost01 -- User vhost02, Group vhost02, Listen 127:0.0.1:6002
the main apache does little but reverse proxy all the vhosts out to the Internet.
<VirtualHost *:80> ServerName vhost01.domain ProxyRequests Off ProxyPass / http://localhost:6001/ ProxyPassReverse / http://localhost:6001/ <Proxy *> Order deny,allow Allow from all
</Proxy> </VirtualHost>
Given the right file permissions, no vhost would have access to another except via HTTP.
Downside: You're essentially doubling the number of Apache processes on your system. Another Upside: Configuration blunders in the vhosts won't throw errors in your main server process.
I had previously considered this, but never went anywhere with it. Would you also need something like mod_proxy_html to rewrite HTML on the fly, or would that not be required in this case?
On Wed, 2 May 2007, Barry Brimer wrote:
Quoting Paul Heinlein heinlein@madboa.com:
On Wed, 2 May 2007, Dan Mensom wrote:
Has anyone set up any form of apache user isolation on CentOS? I have multiple virtual hosts on my machine, run by users who do not trust eachother. The problem is that any php script run by apache is able to do things like raw file io on other users' .htpasswds, php scripts, hidden directory listings, and so on. Database passwords can even be divulged in this way, since they are often stored in .php scripts, which can be read "in the raw" as files by other php scripts.
What is the easiest method for dealing with this? I found http://webauth.stanford.edu/manual/mod/perchild.html but it does not seem to be compiled with the CentOS 5 apache, and I've read elsewhere that php has issues with mutlithreaded apache. Is there any easy way to isolate individual users, by either having apache setuid, or chrooting php scripts, or (ugh) a clean way to run a new apache copy for each vhost?
One "using a canon to kill a fly" approach would be
each vhost runs Apache under a vhost-specific uid/gid and bound only to the loopback interface on a port you assign, e.g.,
vhost01 -- User vhost01, Group vhost01, Listen 127:0.0.1:6001 vhost01 -- User vhost02, Group vhost02, Listen 127:0.0.1:6002
the main apache does little but reverse proxy all the vhosts out to the Internet.
<VirtualHost *:80> ServerName vhost01.domain ProxyRequests Off ProxyPass / http://localhost:6001/ ProxyPassReverse / http://localhost:6001/ <Proxy *> Order deny,allow Allow from all
</Proxy> </VirtualHost>
Given the right file permissions, no vhost would have access to another except via HTTP.
Downside: You're essentially doubling the number of Apache processes on your system. Another Upside: Configuration blunders in the vhosts won't throw errors in your main server process.
I had previously considered this, but never went anywhere with it. Would you also need something like mod_proxy_html to rewrite HTML on the fly, or would that not be required in this case?
At a minimum, you'd need mod_proxy and mod_proxy_http. Other modules might be required to tunnel SSL or whatever.
On May 2, 2007, at 8:18 AM, Barry Brimer wrote:
I had previously considered this, but never went anywhere with it. Would you also need something like mod_proxy_html to rewrite HTML on the fly, or would that not be required in this case?
Not necessarily - you can set the ServerName and such of each proxied host to be correct when proxied, not when accessed directly.
Another option would be to use mod_fcgid to delegate to different PHP instances using FastCGI. FastCGI is popular lately (particularly with the Ruby-on-Rails people) for other reasons - asynchronous webservers like lighttpd and nginx have started to become trendy, and because PHP is not written asynchronously they have no mod_php equivalent.
The biggest advantage to using FastCGI here would be to reduce the number of processes running and memory footprint. As Paul Heinlein said, this proxied Apache setup would mean doubling the number of Apache processes running. Here you just have a few PHP processes running per vhost to handle the dynamic stuff - static files can be handled by the main server. Presumably a FastCGI PHP process would have less of a memory footprint than a whole Apache also.
If you do go with the two layers of Apache instances, at least turn off keepalives on the proxied ones (a waste when accessed only locally) and turn down the number of processes they have running.
In an earlier message:
On May 2, 2007, at 2:45 AM, Dan Mensom wrote:
What is the easiest method for dealing with this? I found http://webauth.stanford.edu/manual/mod/perchild.html but it does not seem to be compiled with the CentOS 5 apache, and I've read elsewhere that php has issues with mutlithreaded apache.
perchild is dead, I'm afraid.
--- Scott Lamb slamb@slamb.org wrote:
Another option would be to use mod_fcgid to delegate to different PHP instances using FastCGI. FastCGI is popular lately (particularly with the Ruby-on-Rails people) for other reasons - asynchronous webservers like lighttpd and nginx have started to become trendy, and because PHP is not written asynchronously they have no mod_php equivalent.
The biggest advantage to using FastCGI here would be to reduce the number of processes running and memory footprint. As Paul Heinlein said, this proxied Apache setup would mean doubling the number of Apache processes running. Here you just have a few PHP processes running per vhost to handle the dynamic stuff - static files can be handled by the main server. Presumably a FastCGI PHP process would have less of a memory footprint than a whole Apache also.
From the various howtos and docs, this, plus suexec seems like the option
I want. However, I don't see a package for fastcgi in base or rpmforge.. Can mod_cgid provide similar functionality? Or do I really want to compile mod_fastcgi (presumably from http://fastcgi.com/?)
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
On May 2, 2007, at 10:34 PM, Dan Mensom wrote:
From the various howtos and docs, this, plus suexec seems like the option
I want. However, I don't see a package for fastcgi in base or rpmforge.. Can mod_cgid provide similar functionality? Or do I really want to compile mod_fastcgi (presumably from http://fastcgi.com/?)
mod_cgid's something else. mod_fastcgi's unmaintained since 2003. mod_fcgid works for me, and there's a Fedora Extras 6 source RPM that rebuilds fine on CentOS 5.
http://download.fedora.redhat.com/pub/fedora/linux/extras/6/SRPMS/ repoview/mod_fcgid.html