Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [day] [month] [year] [list]
Date: Sat, 05 Nov 2016 03:30:41 -0500
From: php-dev@...dogsoftware.net
To: oss-security@...ts.openwall.com
Subject: CVE Request: PHP with Zend OPCache  code permission/sensitive data
 protection vulnerabilities

Hello,

I did not discover this, but to my knowledge no CVE has been requested 
to date.
The PHP project was informed of this vulnerability over 2 years ago and 
has not
fixed it. I am hoping more public discussion with a CVE will help to 
motivate
them.

SUMMARY:

Affects PHP with Zend OPCache enabled, PHP5 <= 5.6.27 and PHP7 <= 7.0.12
(http://php.net)

Zend OPCache has code permission and sensitive data protection 
vulnerabilities
when deployed on shared hosting web servers.

BACKGROUND:

OPCache uses shared memory to cache compiled PHP "opcode" between HTTP 
requests
for reuse. A single shared memory object is opened and initialized in a 
parent
process, and child processes inherit its file descriptor. Due to this 
design,
OPCache is intended for use with a SAPI with a peristent parent process, 
for
example php-fpm with its master process, or apache2handler where 
initialization
occurs in the Apache parent process.

Cache keys for compiled scripts have two modes of operation, simple
filenames and a "use_cwd" mode which includes additional information 
such as
parent script and working directory in cache keys. The "use_cwd" 
behavior only
occurs when scripts are invoked via relative paths, rare in practice in 
a web
server environment with common web applications. In most circumstances 
the
cache uses a simple filesystem path as a cache key for a cached script's
compiled form.

On shared servers PHP is often deployed so that it will switch to a 
local user
account before running a script, for example using mod_ruid2 if deployed 
as an
Apache module, or using "pools" if deployed as php-fpm. In these
configurations, users expect that they can protect sensitive information 
in PHP
scripts with filesystem permissions.

VULNERABILITY DESCRIPTION:

The single shared OPCache circumvents filesystem permissions. For 
example, when
user alice's WordPress site is requested, PHP runs as user alice and
wp-config.php is read, compiled, and cached, including constants for 
database
credentials, API auth keys, and hash salts.  User bob can then include 
alice's
wp-config.php script via the persistent OPCache, regardless of the 
original
script's file permissions. User bob only has to know the filesystem path 
of the
script.

PHP's open_basedir setting is also circumvented; with a restrictive
open_basedir, a nonfatal error occurs, but a cached script outside of
open_basedir will still load and run.

If PHP is running in chroots, unintentional cross-user script execution 
can
occur due to filename hash key collisions. This might be considered a 
separate
bug, but both stem from the simplistic design of opcache keys.

With a default configuration (other than the zend_extension directive to 
load
OPCache, which is not loaded by default) opcache_get_status() can be 
used to
enumerate cached scripts, making exploitation even easier.

The software's documentation does not mention the issue, so most users 
would
see no reason not to enable OPCache on a shared server:
http://php.net/manual/en/book.opcache.php

Original reporter in bug #67481 closed his bug report stating "It turns 
out
this is not a bug, it is the behaviour that is expected when 
opcache.use_cwd is
set to zero," but the same behavior occurs when opcache.use_cwd is 
enabled
unless scripts are invoked with relative paths. Absolute paths are 
typically
used by web servers and web applications.

I've proposed a fix in bug #69090 with patch linked below.

I have point-and-click proof of concept exploit scripts but I plan to 
give
the PHP project a few more days to patch the issue.

REFERENCES:

https://bugs.php.net/bug.php?id=67481
https://bugs.php.net/bug.php?id=69090
https://bugs.php.net/patch-display.php?bug_id=69090&patch=opcache_bug69090_user_id_keys&revision=latest
http://marc.info/?l=php-internals&m=147825816026557&w=2

In PHP 5.6, the problem is in cache key construction in
accel_make_persistent_key_ex():
https://raw.githubusercontent.com/php/php-src/php-5.6.27/ext/opcache/ZendAccelerator.c

In PHP 7.0, equivalent code is in accel_make_persistent_key():
https://raw.githubusercontent.com/php/php-src/php-7.0.12/ext/opcache/ZendAccelerator.c

Please let me know if more details are needed.

-- 
- php-dev@...dogsoftware.net

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ