Hi internals,
I added "virtual_root_level" new security related directive
into php-4.3.4.
Full description with the patch can be found in here
http://www.boulat.net/projects/virtual_root_level/
Some feedback/comments would be appreciated.
Regards,
Boulat
No new features are being accepted into the 4.3.X tree, only bug fixes.
The patch itself seems to duplicate the open_basedir functionality anyway.
Ilia
Hi internals,
I added "virtual_root_level" new security related directive
into php-4.3.4.Full description with the patch can be found in here
http://www.boulat.net/projects/virtual_root_level/
Some feedback/comments would be appreciated.
Regards,
Boulat
So if your script is:
/path1/path2/path3/foo.php
And your virtual_root_level is set to 2 then foo.php will be able to open
files anywhere under /path1/path2
How is that different from simply setting open_basedir to /path1/path2 ?
Is it because you have a bunch of different paths for every user and you
don't want to add all these to your open_basedir list? It seems a bit
fishy to me. There is nothing wrong with have vhost-specific open_basedir
settings.
-Rasmus
Hi internals,
I added "virtual_root_level" new security related directive
into php-4.3.4.Full description with the patch can be found in here
http://www.boulat.net/projects/virtual_root_level/
Some feedback/comments would be appreciated.
Regards,
Boulat
So if your script is:
/path1/path2/path3/foo.php
And your virtual_root_level is set to 2 then foo.php will be able to open
files anywhere under /path1/path2How is that different from simply setting open_basedir to /path1/path2 ?
Is it because you have a bunch of different paths for every user and you
don't want to add all these to your open_basedir list?
Bingo, I have too many clients to add them all, instead determining the
value on the fly is the best way to go IMHO.
It seems a bit
fishy to me. There is nothing wrong with have vhost-specific >open_basedir
settings.
Agreed, but for me it seems that using that directive would save you time
and would make your vhost-specific settings shorter, especially if all
your virtual hosts are located in the same directory-tree.
-Rasmus
Hi internals,
I added "virtual_root_level" new security related directive
into php-4.3.4.Full description with the patch can be found in here
http://www.boulat.net/projects/virtual_root_level/
Some feedback/comments would be appreciated.
Regards,
Boulat
Bingo, I have too many clients to add them all, instead determining the
value on the fly is the best way to go IMHO.
If you have many clients you probably should've automated the account creation
process and modification of all the appropriate config files including
httpd.conf. As such as it would be trivial to add 1 line to every virtual
host, that would limit the PHP's ability to open files to that user's
directories.
Ilia
Bingo, I have too many clients to add them all, instead determining the
value on the fly is the best way to go IMHO.If you have many clients you probably should've automated the account
creation
process and modification of all the appropriate config files including
httpd.conf. As such as it would be trivial to add 1 line to every virtual
host, that would limit the PHP's ability to open files to that user's
directories.
The reason why I would want to play with settings in php.ini or/and
httpd.conf often is because everytime I modify those config files I MUST
restart apache in order for changes to take place, meaning I will have
DOWNTIME. Now imagine hundreds of new accounts added per day to your
hosting machine, that means the webserver will end up getting restarted
hundreds of times... Hundreds of seconds per day add up to minutes of
downtime... and as we all know downtime is something everyone tries to
avoid at all costs.
Cheers.
Ilia
The reason why I would want to play with settings in php.ini or/and
httpd.conf often is because everytime I modify those config files I MUST
restart apache in order for changes to take place, meaning I will have
DOWNTIME. Now imagine hundreds of new accounts added per day to your
hosting machine, that means the webserver will end up getting restarted
hundreds of times... Hundreds of seconds per day add up to minutes of
downtime... and as we all know downtime is something everyone tries to
avoid at all costs.
That's a good point. But this implementation still doesn't seem very
slick to me. What about something like:
open_basedir = /var/www/{user}/public_html
Where {user} would map to the owner of the script being executed. Other
things that might be supported as well: {group}, {regex:a.*$}, {host}
and probably other things as well. I haven't thought through this very
much yet, but that seems like a more flexible approach to this problem.
-Rasmus
Restarting apache takes roughly 1 second. Your argument about hundreds of
accounts being added each time implies that you intend to have A LOT of users
who may end up using PHP on a single machine. Based on this 'guestimate'
within 1 month you intend to have 3000+ users on a single machine. Now, I am
simply curios as to what hardware do you have that supports this wonder?
Additionally apache HUP does not affect users as current requests are sent 1st
and then apache is restarted, the entire process is transparent to the user,
for whom a 1 second delay is hardly noticeable. Download & generation of most
pages will take >1 second anyway.
As for Rasmus' idea of adding various options and possibly regular expression.
open_basedir works right now with a minimum amount of overhead in most
situations. Which still makes the file operations a fair bit slower, but
certainly acceptable loss given the security benefits. However, adding more
options, that would make open_basedir resolving quite a bit slower will
quickly tip the scales in favor of performance. With complex file system
operation checks, you certainly will not be able to host anywhere near 3000
users.
Ilia
The reason why I would want to play with settings in php.ini or/and
httpd.conf often is because everytime I modify those config files I MUST
restart apache in order for changes to take place, meaning I will have
DOWNTIME. Now imagine hundreds of new accounts added per day to your
hosting machine, that means the webserver will end up getting restarted
hundreds of times... Hundreds of seconds per day add up to minutes of
downtime... and as we all know downtime is something everyone tries to
avoid at all costs.That's a good point. But this implementation still doesn't seem very
slick to me. What about something like:open_basedir = /var/www/{user}/public_html
Where {user} would map to the owner of the script being executed. Other
things that might be supported as well: {group}, {regex:a.*$}, {host}
and probably other things as well. I haven't thought through this very
much yet, but that seems like a more flexible approach to this problem.-Rasmus
As for Rasmus' idea of adding various options and possibly regular expression.
open_basedir works right now with a minimum amount of overhead in most
situations. Which still makes the file operations a fair bit slower, but
certainly acceptable loss given the security benefits. However, adding more
options, that would make open_basedir resolving quite a bit slower will
quickly tip the scales in favor of performance. With complex file system
operation checks, you certainly will not be able to host anywhere near 3000
users.
If you are using open_basedir at all, you have already given up all hope
of any sort of performance.
-Rasmus
If you are using open_basedir at all, you have already given up all hope
of any sort of performance.
Certainly, but this would make the existing situation much worse then it
already is. Ideally fastcgi or ap2 should be used where it is possible to
make the web server processes run under the user's account hence avoiding the
needed for open_basedir, safe_mode, etc... all together.
Ilia
If you are using open_basedir at all, you have already given up all hope
of any sort of performance.Certainly, but this would make the existing situation much worse then it
already is. Ideally fastcgi or ap2 should be used where it is possible to
make the web server processes run under the user's account hence avoiding the
needed for open_basedir, safe_mode, etc... all together.
The code could easily be written such that there is virtually no
performance degradation unless the dir actually contains a {} component,
so I don't buy that argument. We are always trading convenience for
performance here.
-Rasmus
If you are using open_basedir at all, you have already given up all hope
of any sort of performance.Certainly, but this would make the existing situation much worse then it
already is. Ideally fastcgi or ap2 should be used where it is possible to
make the web server processes run under the user's account hence avoiding
the
needed for open_basedir, safe_mode, etc... all together.
So then following your logic why not remove open_basedir,safe_mode,etc all
together from PHP, just to increase the performance?
However, if you do decide to keep those since
"the alternatives at the web server and OS levels aren't very realistic,
many people, especially ISP's, use safe mode "
why not improve open_basedir, safe_mode, etc.. security options making PHP
even more popular and robust?
Cheers,
Boulat.
Ilia
So then following your logic why not remove open_basedir,safe_mode,etc all
together from PHP, just to increase the performance?
Because it would break BC. When these options were developed Apache 2 was not
around and fastcgi support was flimsy at best. Using plain CGI (which MANY
ISPs use) to run PHP is quite resource intensive.
Popularity of PHP will not be affected by these features and the robustness
would only take a step backwards. More over the 'security' you add is easily
bypassed through a variety of means.
The open_basedir, safe_mode are hacks that were added because webservers at
the time didn't not have the ability to easily distinguish individual user
accounts and adjust the process uid/gid accordingly. Adding more to these
'features' when real support is already avaliable seems highly counter
productive IMO.
Ilia
So then following your logic why not remove open_basedir,safe_mode,etc all
together from PHP, just to increase the performance?Because it would break BC. When these options were developed Apache 2 was not
around and fastcgi support was flimsy at best. Using plain CGI (which MANY
ISPs use) to run PHP is quite resource intensive.
Ilia, come back to reality man! Are you really suggesting that people use
Apache2 with the perchild MPM to solve this problem? If so, that's pretty
funny. I also fail to see how fastcgi solves the thousands of users on a
machine problem. It's not like fastcgi can switch back and forth either,
so you would need to run thousands of backend fastcgi php's all the time.
The open_basedir, safe_mode are hacks that were added because webservers
at the time didn't not have the ability to easily distinguish individual
user accounts and adjust the process uid/gid accordingly.
And they still don't.
-Rasmus
Because it would break BC. When these options were developed Apache 2 was not
around and fastcgi support was flimsy at best. Using plain CGI (which MANY
ISPs use) to run PHP is quite resource intensive.Ilia, come back to reality man! Are you really suggesting that people use
Apache2 with the perchild MPM to solve this problem?
There is also something as mod_suid:
http://www.jdimedia.nl/igmar/mod_suid/
(note, Apache only starts as root, the requests are not handled as root
of course).
Derick
Ilia, come back to reality man!
But it's so boring ;-).
Are you really suggesting that people use
Apache2 with the perchild MPM to solve this problem? If so, that's pretty
funny. I also fail to see how fastcgi solves the thousands of users on a
machine problem. It's not like fastcgi can switch back and forth either,
so you would need to run thousands of backend fastcgi php's all the time.
Thousands of users on a single machines at least half (probably more) use
dynamic scripts, would require some superb hardware and even then I very much
doubt it could be done effectively. It would be far more practical and
economical to have several cheaper servers with perhaps 100-300 (or less)
users each.
The bottom line that right now solutions do exist, Apache2 perchild MPM could
work, so will Fastcgi. There are also things like mod_become, mod_suid and
mod_diffprivs that can perform uid/gid changes for Apache1.
http://www.jdimedia.nl/igmar/mod_suid/
http://www.snert.com/Software/mod_become/
http://sourceforge.net/projects/moddiffprivs/
Unlike with PHP implemented 'security' controls these are much less trivial to
bypass.
Ilia
Thousands of users on a single machines at least half (probably more) use
dynamic scripts, would require some superb hardware and even then I very much
doubt it could be done effectively. It would be far more practical and
economical to have several cheaper servers with perhaps 100-300 (or less)
users each.
I am not arguing that.
The bottom line that right now solutions do exist, Apache2 perchild MPM could
work
I suppose it could, but it doesn't. Have you tried it?
so will Fastcgi. There are also things like mod_become, mod_suid and
mod_diffprivs that can perform uid/gid changes for Apache1.http://www.jdimedia.nl/igmar/mod_suid/
http://www.snert.com/Software/mod_become/
http://sourceforge.net/projects/moddiffprivs/Unlike with PHP implemented 'security' controls these are much less trivial to
bypass.
And much more harmful once you do bypass them. These rely on a config
where setreuid() can get you back to the root id after any http request.
It is effectively equivalent to running your web server as root and has
the same disastrous consequences if hacked. If you read the mod_suid page
and README you will see disclaimers all over the place about how insecure
this mechanism is.
Look, my preferred solution to this has always been to run multiple Apache
servers behind a reverse proxy. Every virtual host gets its own Apache
instance running as that users own uid. If you keep the Apache binary the
same for all the hosts the memory requirements aren't even that excessive.
You of course can't do thousands of hosts, but no mechanism can
effectively do that anyway. But you can surely do dozens or maybe even
hundreds on a decent server.
But people still like the efficiency and convenience of a runtime
open_basedir check. It gets you 90% of the way there and it doesn't cost
you that much. Until there is a realworld alternative for folks, and no,
nothing mentioned so far are realistic alternatives, I just don't see this
demand going away.
-Rasmus
I suppose it could, but it doesn't. Have you tried it?
I've tried on a small scale.
But people still like the efficiency and convenience of a runtime
open_basedir check. It gets you 90% of the way there and it doesn't cost
you that much. Until there is a realworld alternative for folks, and no,
nothing mentioned so far are realistic alternatives, I just don't see this
demand going away.
I am not suggesting we remove open_basedir or safe_mode although I still
maintain they are horrible kludges implemented in the wrong place as it is
not the job of scripting language to implement file system security. Adding
further hacks, prevents the development of real solutions to the problem
rather then hacks trivially bypassed.
These open_basedir/safe_mode will not prevent the use of CGI (supported by
most IPS) to bypass these limits, INI leaks can be used to bypass those
'security' measures as well, etc... Ultimately the choice to use easy to
implement hacks creates a false a sense of security, which ultimately leads
to compromised servers.
Regardless of who is right or wrong at this point PHP 4 is feature locked and
so is PHP 5.
Ilia
I am not suggesting we remove open_basedir or safe_mode although I still
maintain they are horrible kludges implemented in the wrong place as it is
not the job of scripting language to implement file system security. Adding
further hacks, prevents the development of real solutions to the problem
rather then hacks trivially bypassed.
This is also not the argument here. How many times have you heard me say
that this should not be PHP's problem? It is architecturally incorrect to
fix this problem in PHP and it can never be done correctly. However, PHP
is also the pragmatic solution to the web problem and until such a time
when someone else decides to actually fix this, we have to address it.
And I completely don't buy the "improving our hacks prevents development
of a real solution" argument. If we were talking about the same
developers working on both, or even if there was a clear way to solve the
actual problem that argument might have some weight, but it isn't the same
developers nor is there a straightforward way to solve this just looking
for someone to sit down and write the code.
Even if someone was to actually fix the perchild MPM in Apache2 that still
leaves us with all the thread safety problems in many extensions and the
lack of tools to debug these problems. And a non-threaded perchild
implementation doesn't make any sense. So where does this leave us?
Looking for ideas and stuck with open_basedir for a while which in my
opinion means we need to make our crappy hack as useful as possible since
there is no sign of a white knight arriving any time soon to solve this
problem for us.
-Rasmus
This is also not the argument here. How many times have you heard me say
that this should not be PHP's problem? It is architecturally incorrect to
fix this problem in PHP and it can never be done correctly. However, PHP
is also the pragmatic solution to the web problem and until such a time
when someone else decides to actually fix this, we have to address it.
And I completely don't buy the "improving our hacks prevents development
of a real solution" argument. If we were talking about the same
developers working on both, or even if there was a clear way to solve the
actual problem that argument might have some weight, but it isn't the same
developers nor is there a straightforward way to solve this just looking
for someone to sit down and write the code.
Once PHP begins (already did I suppose) implementing these hacks we'll just
have more and more people convinced that this is a PHP issue and push for
further hacks on top of the existing ones. Between adding these hacks and
fixing various bugs resultant from these hacks or various bypasses of these
'security' measures much developer time (better spent elsewhere) is wasted.
Before this discussion goes even further let me just summarize my position:
-1
Ilia
So then following your logic why not remove open_basedir,safe_mode,etc
all
together from PHP, just to increase the performance?Because it would break BC. When these options were developed Apache 2 was
not around and fastcgi support was flimsy at best.
Ilia as far as Im concerned Apache 2 MPM does not currently work on most
platforms http://httpd.apache.org/docs-2.0/mod/perchild.html
thus unfortunatelly MPM can not be used in production environment.
Using plain CGI (which MANY
ISPs use) to run PHP is quite resource intensive.
Which is exactly why I dont use plain CGI to run PHP.
Popularity of PHP will not be affected by these features and the
robustness
would only take a step backwards. More over the 'security' you add is
easily
bypassed through a variety of means.
So just because there might be means to bypass security options in PHP we
shouldnt even bother improving security? Lets give up.
IMHO it should be the other way around, we should try to improve security
the best way possible, especially knowing that at the moment there might
be ways of bypassing it.
Adding more to these
'features' when real support is already avaliable seems highly counter
productive IMO.Ilia
Cheers,
Boulat
So just because there might be means to bypass security options in PHP we
shouldnt even bother improving security? Lets give up.
The issue is not the fact that these setting can be bypassed by PHP, those are
bugs to be fixed. But the fact since the settings are PHP specific, other
scripting languages (mod_perl|python) and CGI could be used to do actions
restrictred from PHP. The real solution is in the webserver not a scripting
language that is being run from inside the webserver.
Ilia