Edit report at https://bugs.php.net/bug.php?id=69090&edit=1
ID: 69090
Comment by: kmark937 at gmail dot com
Reported by: simon at ikanobori dot jp
Summary: add prefix/xor to cache keys/check permissions or
separate caches
Status: Analyzed
Type: Feature/Change Request
Package: opcache
Operating System: linux/debian
PHP Version: 5.6.5
Block user comment: N
Private report: N
New Comment:
php-dev,
Thanks for providing further insight into this issue. I'd like to take you up on your offer of
a PoC for replicating under mod_php + open_basedir. FPM works as well but I'm particularly
interested in the mod_php case.
Thanks!
Previous Comments:
------------------------------------------------------------------------
[2016-11-07 15:13:13] php-dev at coydogsoftware dot net
dol+list, thank you for your comments. Your observations are consistent with my own experiences,
with the exception that I haven't had a chance to test exploitation under CloudLinux/CageFS. I
haven't bothered testing with cPanel's "Jail Apache" virtfs feature either, due
to unrelated reliability problems with that feature. I'm trying to avoid too much discussion of
such platform-specific mitigations because they're out of scope for a PHP bug report, and they
shouldn't even be necessary. I feel strongly that this is a PHP bug which needs to be fixed in
PHP.
I agree that device+inode should ideally be added to the key scheme, but they alone are
insufficient. They are not necessarily private information, and can be read if permissions of the
parent directory allow. This breaks user expectations; if wp-config.php is unreadable for a user,
that user should not be able to execute that script, period. This is why I think EUID should be part
of the key. I don't like the thought of opcache playing permissions referee and I think it
suggests a fundamental design flaw with the way SHM is being used, but working within the existing
SHM design I think EUID is the best way forward. Perhaps a more radical change would be better, but
I'm not familiar enough with prior art in PHP opcode caching to know what it is.
Using device+inode is also less straightforward than using EUID, otherwise I'm sure the
maintainers would have already done it: it seems inappropriate to stat() for this info during key
generation for performance reasons. APC apparently got a stat struct passed from the SAPI so the
stat() was already done outside of APC code (does this imply APC cached scripts per compilation unit
and not per file, since the web server wouldn't know which files are included? I haven't
reviewed APC code in enough detail yet to confirm).
For my patch I use EUID simply because there's no undue performance hit and it fixes the
cross-user permissions bypass in both "out of the box" and common control panel
environments. It's probably not perfect but surely we can agree it's better than the
existing code.
For anyone using FPM who wants to mitigate before PHP fixes the vulnerability, 2 years ago Mattias
Geniar confirmed that separate FPM master daemons is the way to go, and provided example configs.
It's cumbersome and inefficient and shouldn't be necessary: https://ma.ttias.be/a-better-way-to-run-php-fpm/
------------------------------------------------------------------------
[2016-11-07 11:46:20] dol+list at cyon dot ch
First off all thank you php-dev to bringing this issue back on the table.
I'd like to bring in my view from a shared hosting provider.
IMHO the two big hosting panel softwares Plesk and cPanel are vulnerable to this issue. We currently
use cPanel. cPanel provides a different set of options to isolate the user from reading other users
files. In addition to the user isolation it's also possible to isolate you processes any
further by running them in a chroot environment. This could be easy leveraged by using tools/distros
like Cloudlinux CageFS (https://www.cloudlinux.com/cagefs), which we use.
All this countermeasures to separate processes users on process and file system level are voided if
the OpCache is accessible without the user boundaries.
Our stack currently is not vulnerable to the mentioned issue due to the combination of additional
tools and server softwares that isolate users also on the OpCache level. The magic is a combination
of Cloudlinix as file system isolation and Litespeed as a PHP SAPI process and OpCache isolation.
Having some insights into the hosting industry this stack is not the majority. IMHO most of the
cPanel users use the built in capabilities of the EasyApache stack, which is vulnerable.
In the past we've seen some attacks targeting multiple users on the same server. The most
effective was: Symlink Bypass http://www.rafayhackingarticles.net/2012/01/hack-website-on-shared-host-symlink.html
A skilled attacker could easily take over dozens of shared hosting with the help of this
vulnerability. Depending on the shared hosting provider I guess an average of users per host is
approx. 200-1000 users. Given the current market share of Wordpress (easy extractable secrets) of
approx. 60% ( https://w3techs.com/technologies/details/cm-wordpress/all/all
) the impact of a hacked website/CMS/Plugin is very high. In automatic manner an attacker could take
over half of shared hostings only by optimizing for Wordpress.
This is IMHO a pressing matter for all the other shared hosting providers and customers support
staffs out there.
I'm in favor to the current solution to fix the issue by appending a contextual part to the
path.
IMHO the best solution from a security point of view would be the inode information.
From a operations point of view inodes also solve the issue of deploying with symlinks. E.g. https://www.scalingphpbook.com/blog/2014/01/30/zend-opcache-and-atomic-deploys.html
------------------------------------------------------------------------
[2016-11-07 09:39:26] sjon at hortensius dot net
jpauli, using separate pools does not fix this issue; the cache is maintained by the master process
that has access to all pools regardless of permissions of those pools.
------------------------------------------------------------------------
[2016-11-06 20:54:49] php-dev at coydogsoftware dot net
bjh438-git, thank you for your comments. I had previously read that article. The setup described
mitigates the security concerns I've outlined for one reason: It recommends disabling OPCache
completely.
Such a multi-user setup is generally recommended, but as I mentioned in my response to jpauli,
it's dangerous when combined with a single SHM cache with a simplistic hash keying scheme which
makes no attempt to segregate users.
My readings of php-internals archives suggest that OPCache was indeed meant to be usable in
multi-user setups so perhaps the maintainers simply haven't thought through the all
implications of the key scheme, though they have discussed its other shortcomimgs. I'm working
on a brief but more comprehensive advisory which I'll post here and on php-internals soon if we
don't get more meaningful engagement on this issue.
------------------------------------------------------------------------
[2016-11-06 17:27:01] bjh438-git at yahoo dot com
php-dev - would it not be best (at least when using fpm) to run each pool under a separate user /
group account as discussed here: https://www.digitalocean.com/community/tutorials/how-to-host-multiple-websites-securely-with-nginx-and-php-fpm-on-ubuntu-14-04
This would seem to satisfy the original suggestions earlier in the thread to leave as much as
possible to the OS level security controls.
I mention because I was wondering if your patches (which are warmly welcomed...I've been
posting on this issue for a while now on SF & SE) presume that these types of controls would
also be implemented or perhaps obviate them.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=69090
--
Edit this bug report at https://bugs.php.net/bug.php?id=69090&edit=1